Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
aba8f9b
WIP
seanmarcia Aug 1, 2025
f34b00d
wip
seanmarcia Aug 4, 2025
d12793d
wip
seanmarcia Aug 4, 2025
cfcb6ab
Wip
seanmarcia Aug 4, 2025
16b2189
Wip
seanmarcia Aug 4, 2025
b777c5b
wip
seanmarcia Aug 8, 2025
316e8f4
wip
seanmarcia Aug 13, 2025
5d3475c
wip
seanmarcia Sep 13, 2025
e791089
wip
seanmarcia Sep 13, 2025
4bcbf61
Fix pagination and password reset tests after Tailwind conversion
seanmarcia Sep 29, 2025
ccbde42
Adjust topics search ordering and filter behavior; simplify order sel…
seanmarcia Sep 29, 2025
adaa276
Fix remaining topic search state/month test failures
seanmarcia Sep 30, 2025
1edb1aa
Wip
seanmarcia Oct 1, 2025
55d37a1
Remove unnecessary links
Oli0li Nov 10, 2025
76c43a0
Fix merge conflict
Oli0li Nov 10, 2025
3795fe7
Fix upload management specs
Oli0li Nov 10, 2025
a6811e4
Fix search spec expectations
Oli0li Nov 10, 2025
1948d05
Remove duplicate gem
Oli0li Nov 10, 2025
1b5061c
Fix pagination
Oli0li Nov 17, 2025
e9c5a4c
Fix missing closing div in Regions#index view
Oli0li Nov 17, 2025
572389f
Remove purple letter on Topic list
Oli0li Nov 17, 2025
51e7536
Fix alignement on Topic form
Oli0li Nov 18, 2025
c610c22
Merge main
Oli0li Nov 20, 2025
d18ea15
Fix broken svgs
Oli0li Nov 20, 2025
db90cd7
Fix Topic form loading button logic
Oli0li Nov 20, 2025
e5411cf
Style file upload interface
Oli0li Nov 20, 2025
806d61d
Merge branch 'main' into tailwinds_conversions
Oli0li Nov 20, 2025
d3411d1
Change Topic edit form header color
Oli0li Nov 20, 2025
6b90948
Use Tom Select for Topic search tag selection
Oli0li Nov 27, 2025
aa89d19
Fix layout on Topic form
Oli0li Nov 27, 2025
92c42df
Extract repeated stylings into classes/partials
Oli0li Nov 27, 2025
09ad7fd
Use full length for query field
Oli0li Nov 27, 2025
c4a5679
Use same dropdown styles everywhere
Oli0li Nov 28, 2025
7857a2e
Merge branch 'main' into tailwinds_conversions
Oli0li Nov 29, 2025
4c17b64
Use Tom Select to display provider_ids field
Oli0li Nov 29, 2025
83e0b56
Only make password required for new users
Oli0li Nov 29, 2025
95ad8e6
Remove unused files
Oli0li Nov 29, 2025
58367a9
Only allow uploads of accepted content types
Oli0li Nov 29, 2025
b3774ef
Fix vulnerability warning for pagination partial
Oli0li Nov 29, 2025
0fdac98
Fix password reset page
Oli0li Nov 29, 2025
d2dc1e0
Remove unused code for Tag form
Oli0li Nov 29, 2025
15e7094
Fix tagging helper
Oli0li Nov 29, 2025
93a8100
Fix topics/creation_spec
Oli0li Nov 29, 2025
1d21809
Fix topics/search spec
Oli0li Nov 29, 2025
1623a8e
Fix upload_management_spec
Oli0li Nov 29, 2025
e2822d4
Fix pagination tests
Oli0li Nov 29, 2025
a3db405
Fix tag update spec
Oli0li Nov 29, 2025
9059a44
Fix CI issue not finding tailwind.css
Oli0li Nov 29, 2025
ef035af
Fix Tags#show page
Oli0li Nov 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jobs:
ruby-version: .ruby-version
bundler-cache: true

- name: Build Tailwind CSS
run: bin/rails tailwindcss:build

- name: Run tests
run: bin/rails db:test:prepare && bin/rspec

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ db/structure.sql
# Ignore IDE config files
.idea/
.DS_Store

/app/assets/builds/*
!/app/assets/builds/.keep
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ gem "solid_cache"
gem "solid_queue"
gem "solid_queue_monitor", "~> 0.3.2"
gem "stimulus-rails"
gem "tailwindcss-rails"
gem "thruster", require: false
gem "turbo-rails"

Expand Down
11 changes: 11 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,16 @@ GEM
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.7)
tailwindcss-rails (4.3.0)
railties (>= 7.0.0)
tailwindcss-ruby (~> 4.0)
tailwindcss-ruby (4.1.11)
tailwindcss-ruby (4.1.11-aarch64-linux-gnu)
tailwindcss-ruby (4.1.11-aarch64-linux-musl)
tailwindcss-ruby (4.1.11-arm64-darwin)
tailwindcss-ruby (4.1.11-x86_64-darwin)
tailwindcss-ruby (4.1.11-x86_64-linux-gnu)
tailwindcss-ruby (4.1.11-x86_64-linux-musl)
thor (1.4.0)
thruster (0.1.16)
thruster (0.1.16-aarch64-linux)
Expand Down Expand Up @@ -646,6 +656,7 @@ DEPENDENCIES
solid_queue
solid_queue_monitor (~> 0.3.2)
stimulus-rails
tailwindcss-rails
thruster
turbo-rails
tzinfo-data
Expand Down
1 change: 1 addition & 0 deletions Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
web: bin/rails server -p 3000
worker: bin/jobs -c config/queue.yml
css: bin/rails tailwindcss:watch
Empty file added app/assets/builds/.keep
Empty file.
49 changes: 49 additions & 0 deletions app/assets/images/skill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
* depending on specificity.
*
* Consider organizing styles into separate files for maintainability.
*
* Note: Tailwind CSS is loaded separately via stylesheet_link_tag in the layout.
*/
216 changes: 216 additions & 0 deletions app/assets/tailwind/application.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
@import "tailwindcss";

/* Tom Select Tailwind Styles */

/* Hide the original select element */
.ts-wrapper .ts-control + select,
.ts-wrapper + select {
@apply hidden;
}

select[data-select-tags-target="tagList"] {
@apply hidden;
}

.ts-wrapper {
@apply relative;
}

.ts-wrapper.single .ts-control,
.ts-wrapper.multi .ts-control {
@apply w-full px-3.5 py-2.5 border border-gray-300 rounded-lg text-sm bg-white transition-all duration-200;
min-height: 42px;
}

.ts-wrapper.multi .ts-control {
@apply flex flex-wrap items-center gap-1.5;
padding: 0.375rem 0.625rem;
}

.ts-wrapper .ts-control:focus-within {
@apply border-blue-500 outline-none ring-4 ring-blue-500/10;
}

.ts-wrapper.single .ts-control:hover:not(:focus-within),
.ts-wrapper.multi .ts-control:hover:not(:focus-within) {
@apply border-gray-400 bg-gray-50;
}

.ts-wrapper .ts-control > input {
@apply flex-grow outline-none bg-transparent text-sm;
min-width: 60px;
padding: 0.25rem;
}

.ts-wrapper .ts-control > input::placeholder {
@apply text-gray-400;
}

/* Selected items (tags/badges) */
.ts-wrapper.multi .ts-control > div {
@apply inline-flex items-center gap-1.5 px-2.5 py-1 bg-blue-500 text-white text-sm rounded-md;
max-width: 100%;
}

.ts-wrapper.multi .ts-control > div.active {
@apply bg-blue-600;
}

/* Remove button */
.ts-wrapper .ts-control .remove {
@apply inline-flex items-center justify-center ml-1 text-white/80 hover:text-white cursor-pointer;
font-size: 1.125rem;
line-height: 1;
padding: 0;
border: none;
background: none;
}

.ts-wrapper .ts-control .remove:hover {
@apply text-white;
}

/* Dropdown */
.ts-dropdown {
@apply absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden;
max-height: 280px;
overflow-y: auto;
}

.ts-dropdown .ts-dropdown-content {
@apply py-1;
}

/* Dropdown options */
.ts-dropdown .option {
@apply px-3.5 py-2 text-sm text-gray-700 cursor-pointer transition-colors duration-150;
}

.ts-dropdown .option:hover,
.ts-dropdown .option.active {
@apply bg-blue-500 text-white;
}

.ts-dropdown .option.selected {
@apply hidden;
}

/* No results message */
.ts-dropdown .no-results {
@apply px-3.5 py-2 text-sm text-gray-500 italic;
}

/* Loading state */
.ts-wrapper.loading::after {
content: '';
@apply absolute right-3 top-1/2 w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin;
margin-top: -0.5rem;
}

/* Disabled state */
.ts-wrapper.disabled .ts-control {
@apply bg-gray-100 text-gray-500 cursor-not-allowed border-gray-200;
}

/* Single select caret */
.ts-wrapper.single .ts-control::after {
content: '';
@apply absolute right-3 top-1/2 w-0 h-0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #6b7280;
margin-top: -2.5px;
pointer-events: none;
}

.ts-wrapper.single.input-active .ts-control::after {
border-top-color: #3b82f6;
}

/* Focus visible for accessibility */
.ts-wrapper .ts-control:focus-visible {
@apply outline-none ring-4 ring-blue-500/10;
}

/* Form Styles */
.form-label {
@apply block text-sm font-semibold text-gray-700 mb-2;
}

.form-input,
.form-select,
.form-textarea {
@apply w-full px-4 py-3 border-2 border-gray-200 rounded-lg text-sm transition-all duration-200 bg-gray-50;
}

.form-select {
appearance: none;
padding-right: 2.5rem;
}

.form-textarea {
@apply resize-y;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
@apply outline-none border-blue-500 ring-4 ring-blue-500/10 bg-white;
}

.form-input:hover:not(:focus),
.form-select:hover:not(:focus),
.form-textarea:hover:not(:focus) {
@apply border-gray-300;
}

.form-required {
@apply text-red-500;
}

.form-help-text {
@apply mt-2 text-xs text-gray-500;
}

.form-grid {
@apply grid gap-6;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.form-grid-full {
grid-column: 1 / -1;
}

/* Alternative Input Styles (lighter borders, less padding) */
.input-label {
@apply block text-sm font-semibold text-gray-700 mb-2;
}

.input-field {
@apply w-full border border-gray-300 rounded-lg text-sm transition-all duration-200 bg-white;
padding: 0.625rem 0.875rem;
}

.input-field:focus {
@apply outline-none border-blue-500 bg-white;
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
}

.input-field:hover:not(:focus) {
@apply border-gray-400;
}

.select-field {
@apply w-full border border-gray-300 rounded-lg text-sm bg-white transition-all duration-200 cursor-pointer;
padding: 0.625rem 2.5rem 0.625rem 0.875rem;
appearance: none;
}

.select-field:focus {
@apply outline-none border-blue-500;
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
}

.select-field:hover:not(:focus) {
@apply border-gray-400;
}
15 changes: 15 additions & 0 deletions app/controllers/tags_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ def index
def show
end

def new
@tag = Tag.new
end

def create
@tag = Tag.new(tag_params)

if @tag.save
SynchronizeCognatesOnTopicsJob.perform_later(@tag) if tag_params[:cognates_list].reject(&:empty?).any?
redirect_to tags_path, notice: "Tag was successfully created."
else
render :new, status: :unprocessable_entity
end
end

def edit
end

Expand Down
19 changes: 16 additions & 3 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@ class UsersController < ApplicationController
include Pagy::Backend

before_action :redirect_contributors
before_action :set_user, only: %i[ edit update destroy ]
before_action :set_user, only: %i[ show edit update destroy ]

def index
@pagy, @users = pagy(User.all.search_with_params(user_search_params))
@pagy, @users = pagy(User.includes(:providers).search_with_params(user_search_params))

respond_to do |format|
format.html do
if turbo_frame_request?
render partial: "user_list"
else
render :index
end
end
end
end

def new
@user = User.new
end

def show
end

def create
@user = User.new(user_params)

Expand Down Expand Up @@ -48,7 +61,7 @@ def destroy
private

def set_user
@user = User.find(params.expect(:id))
@user = User.includes(:providers).find(params.expect(:id))
end

def user_params
Expand Down
22 changes: 22 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,26 @@ def flash_class(level)
else "alert-light-info"
end
end

def tailwind_flash_class(level)
case level
when "notice" then "bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 text-green-800 shadow-sm"
when "alert" then "bg-gradient-to-r from-red-50 to-rose-50 border border-red-200 text-red-800 shadow-sm"
when "warning" then "bg-gradient-to-r from-yellow-50 to-amber-50 border border-yellow-200 text-yellow-800 shadow-sm"
when "error" then "bg-gradient-to-r from-red-50 to-rose-50 border border-red-200 text-red-800 shadow-sm"
when "success" then "bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 text-green-800 shadow-sm"
when "info" then "bg-gradient-to-r from-blue-50 to-cyan-50 border border-blue-200 text-blue-800 shadow-sm"
else "bg-gradient-to-r from-gray-50 to-slate-50 border border-gray-200 text-gray-800 shadow-sm"
end
end

def nav_link_class(path)
base_style = "display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem; text-decoration: none; border-radius: 0.5rem; transition: all 0.2s; font-weight: 500;"

if current_page?(path)
base_style + " background-color: #dbeafe; color: #1d4ed8;"
else
base_style + " color: #374151;"
end
end
end
Loading