diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index a4cbd89..34b4fe2 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -40,10 +40,6 @@ site-sidebar {
/* For jade, light on dark looks better */
--success-color: #70FCBA; /* Pico jade 100 */
--success-bg: #015234; /* Pico jade 700 */
- --backlog-color: #424751; /* Pico zinc 700 */
- --backlog-bg: #E0E3E7; /* Pico zinc 100 */
- --analysis-color: #5B4200; /* Pico amber 700 */
- --analysis-bg: #FDDEA6; /* Pico amber 100 */
--info-color: #014C75; /* Pico azure 700 */
--info-bg: #D1E5FB; /* Pico azure 100 */
}
diff --git a/app/assets/stylesheets/tasks.css b/app/assets/stylesheets/tasks.css
index c754dff..6396fc6 100644
--- a/app/assets/stylesheets/tasks.css
+++ b/app/assets/stylesheets/tasks.css
@@ -6,8 +6,8 @@
}
.task-status {
- --color: var(--backlog-color);
- --background-color: var(--backlog-bg);
+ --color: #424751; /* Pico zinc 700 */
+ --background-color: #E0E3E7; /* Pico zinc 100 */
&.badge {
border: 2px solid var(--border-color, currentColor);
@@ -15,20 +15,30 @@
background-color: var(--background-color);
}
- &.analysis {
- --color: var(--analysis-color);
- --background-color: var(--analysis-bg);
+ &.blue {
+ --color: #1D59D0; /* Pico blue 600 */
+ --background-color: #E0E1FA/* Pico blue 100 */
}
- &.development {
- --color: var(--info-color);
- --background-color: var(--info-bg);
+ &.yellow {
+ --background-color: #FDDEA6; /* Pico amber 100 */
+ --border-color: #A77C00; /* Pico amber 450 */
}
- &.fulfillment {
+ &.green {
--color: var(--success-color);
--background-color: var(--success-bg);
}
+
+ &.purple {
+ --color: #9236A4; /* Pico purple 600 */
+ --background-color: #F2DCF4; /* Pico purple 100 */
+ }
+
+ &.pink {
+ --color: #B21E4F; /* Pico pink 600 */
+ --background-color: #F9DBDF; /* Pico pink 100 */
+ }
}
.task-show-info {
diff --git a/app/models/task_status.rb b/app/models/task_status.rb
index 7bc4582..847d9d3 100644
--- a/app/models/task_status.rb
+++ b/app/models/task_status.rb
@@ -4,10 +4,11 @@ class TaskStatus < ApplicationRecord
belongs_to :workflow
has_one :project, through: :workflow
- enum :category, { backlog: 100, analysis: 1000, development: 20_000, fulfillment: 60_000 }
+ enum :icon, %w[new achived done circle_dash hammer play tool].index_by(&:itself), default: 'new', scopes: false
+ enum :color, %w[blue gray yellow green purple pink].index_by(&:itself), default: 'gray', scopes: false
validates :name, presence: true, uniqueness: { scope: :workflow }
validates :category, presence: true
- scope :default_order, -> { order(:category, :name) }
+ scope :default_order, -> { order(:position, :name) }
end
diff --git a/app/view_models/tasks/statuses/selector_view_model.rb b/app/view_models/tasks/statuses/selector_view_model.rb
index 64fd319..91824e1 100644
--- a/app/view_models/tasks/statuses/selector_view_model.rb
+++ b/app/view_models/tasks/statuses/selector_view_model.rb
@@ -3,6 +3,16 @@
module Tasks
module Statuses
class SelectorViewModel
+ ICONS = {
+ new: 'add_circle_fill',
+ archived: 'archive_line',
+ done: 'checks_line',
+ circle_dash: 'circle_dash_line',
+ hammer: 'hammer_fill',
+ play: 'play_circle_fill',
+ tool: 'tool_line'
+ }.freeze
+
def initialize(task, with_form: false)
@task = task
@with_form = with_form
@@ -25,15 +35,19 @@ module Tasks
private
def workflow_task_statuses
- @task.workflow.task_statuses.sort_by { |e| [e.category, e.name] }
+ @task.workflow.task_statuses.sort_by { |e| [e.position, e.name] }
end
def task_status_badge(status, view_context)
view_context.content_tag(
- :span, status.name,
- class: ['badge', 'task-status', status.category.dasherize]
+ :span, view_context.mask_icon(icon(status)) + status.name,
+ class: ['badge', 'task-status', status.color]
)
end
+
+ def icon(status)
+ ICONS.fetch(status.icon.to_sym)
+ end
end
end
end
diff --git a/db/migrate/20260404215813_replace_old_status_fields_with_new.rb b/db/migrate/20260404215813_replace_old_status_fields_with_new.rb
new file mode 100644
index 0000000..5e17ac7
--- /dev/null
+++ b/db/migrate/20260404215813_replace_old_status_fields_with_new.rb
@@ -0,0 +1,11 @@
+class ReplaceOldStatusFieldsWithNew < ActiveRecord::Migration[8.1]
+ def change
+ change_table :task_statuses, bulk: true do |t|
+ t.string :icon
+ t.string :color
+ t.integer :position, default: 0
+
+ t.remove :category, type: :integer
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 6cfd8d2..2fdfb89 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.1].define(version: 2026_03_21_132740) do
+ActiveRecord::Schema[8.1].define(version: 2026_04_04_215813) do
create_table "action_text_rich_texts", charset: "utf8mb4", collation: "utf8mb4_uca1400_ai_ci", force: :cascade do |t|
t.text "body", size: :long
t.datetime "created_at", null: false
@@ -70,9 +70,11 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_21_132740) do
end
create_table "task_statuses", charset: "utf8mb4", collation: "utf8mb4_uca1400_ai_ci", force: :cascade do |t|
- t.integer "category", limit: 2, null: false, unsigned: true
+ t.string "color"
t.datetime "created_at", null: false
+ t.string "icon"
t.string "name", null: false
+ t.integer "position", default: 0
t.datetime "updated_at", null: false
t.bigint "workflow_id", null: false
t.index ["workflow_id", "name"], name: "index_task_statuses_on_workflow_id_and_name", unique: true
diff --git a/lib/tasks/data_migrations.rake b/lib/tasks/data_migrations.rake
index 5b42249..ba203ea 100644
--- a/lib/tasks/data_migrations.rake
+++ b/lib/tasks/data_migrations.rake
@@ -35,4 +35,11 @@ namespace :data_migrations do
task.save!
end
end
+
+ desc 'Backfill task status icons and colors'
+ task backfill_task_status_icons_and_colors: :environment do
+ TaskStatus.in_batches do |batch|
+ batch.update_all(icon: 'circle_dash', color: 'blue')
+ end
+ end
end
diff --git a/vendor/assets/images/mingcute/add_circle_fill.svg b/vendor/assets/images/mingcute/add_circle_fill.svg
new file mode 100644
index 0000000..a37730b
--- /dev/null
+++ b/vendor/assets/images/mingcute/add_circle_fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/archive_line.svg b/vendor/assets/images/mingcute/archive_line.svg
new file mode 100644
index 0000000..07e2e0f
--- /dev/null
+++ b/vendor/assets/images/mingcute/archive_line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/checks_line.svg b/vendor/assets/images/mingcute/checks_line.svg
new file mode 100644
index 0000000..92c5a81
--- /dev/null
+++ b/vendor/assets/images/mingcute/checks_line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/circle_dash_line.svg b/vendor/assets/images/mingcute/circle_dash_line.svg
new file mode 100644
index 0000000..0abc8ba
--- /dev/null
+++ b/vendor/assets/images/mingcute/circle_dash_line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/external_link_line.svg b/vendor/assets/images/mingcute/external_link_line.svg
index 63a2fc0..a34fb20 100644
--- a/vendor/assets/images/mingcute/external_link_line.svg
+++ b/vendor/assets/images/mingcute/external_link_line.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/hamburger_line.svg b/vendor/assets/images/mingcute/hamburger_line.svg
index bbcef4a..f8626f5 100644
--- a/vendor/assets/images/mingcute/hamburger_line.svg
+++ b/vendor/assets/images/mingcute/hamburger_line.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/hammer_fill.svg b/vendor/assets/images/mingcute/hammer_fill.svg
new file mode 100644
index 0000000..300b796
--- /dev/null
+++ b/vendor/assets/images/mingcute/hammer_fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/play_circle_fill.svg b/vendor/assets/images/mingcute/play_circle_fill.svg
new file mode 100644
index 0000000..eb3f416
--- /dev/null
+++ b/vendor/assets/images/mingcute/play_circle_fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/right_fill.svg b/vendor/assets/images/mingcute/right_fill.svg
index 930e72a..d7a8dcd 100644
--- a/vendor/assets/images/mingcute/right_fill.svg
+++ b/vendor/assets/images/mingcute/right_fill.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/signature_line.svg b/vendor/assets/images/mingcute/signature_line.svg
new file mode 100644
index 0000000..65cf1bb
--- /dev/null
+++ b/vendor/assets/images/mingcute/signature_line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/task_line.svg b/vendor/assets/images/mingcute/task_line.svg
index e303c87..58b6fb8 100644
--- a/vendor/assets/images/mingcute/task_line.svg
+++ b/vendor/assets/images/mingcute/task_line.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/tool_line.svg b/vendor/assets/images/mingcute/tool_line.svg
new file mode 100644
index 0000000..f434cf1
--- /dev/null
+++ b/vendor/assets/images/mingcute/tool_line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/assets/images/mingcute/warning_line.svg b/vendor/assets/images/mingcute/warning_line.svg
index 5ecd642..06c8f48 100644
--- a/vendor/assets/images/mingcute/warning_line.svg
+++ b/vendor/assets/images/mingcute/warning_line.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file