From 9766430e69eeca2e885aea5faf7191122478b3c9 Mon Sep 17 00:00:00 2001 From: Artemiy Solopov Date: Mon, 6 Apr 2026 02:30:33 +0300 Subject: [PATCH] Task status model rework Replaced categories with colors, icons and positions --- app/assets/stylesheets/application.css | 4 --- app/assets/stylesheets/tasks.css | 28 +++++++++++++------ app/models/task_status.rb | 5 ++-- .../tasks/statuses/selector_view_model.rb | 20 +++++++++++-- ...5813_replace_old_status_fields_with_new.rb | 11 ++++++++ db/schema.rb | 6 ++-- lib/tasks/data_migrations.rake | 7 +++++ .../images/mingcute/add_circle_fill.svg | 1 + .../assets/images/mingcute/archive_line.svg | 1 + vendor/assets/images/mingcute/checks_line.svg | 1 + .../images/mingcute/circle_dash_line.svg | 1 + .../images/mingcute/external_link_line.svg | 2 +- .../assets/images/mingcute/hamburger_line.svg | 2 +- vendor/assets/images/mingcute/hammer_fill.svg | 1 + .../images/mingcute/play_circle_fill.svg | 1 + vendor/assets/images/mingcute/right_fill.svg | 2 +- .../assets/images/mingcute/signature_line.svg | 1 + vendor/assets/images/mingcute/task_line.svg | 2 +- vendor/assets/images/mingcute/tool_line.svg | 1 + .../assets/images/mingcute/warning_line.svg | 2 +- 20 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 db/migrate/20260404215813_replace_old_status_fields_with_new.rb create mode 100644 vendor/assets/images/mingcute/add_circle_fill.svg create mode 100644 vendor/assets/images/mingcute/archive_line.svg create mode 100644 vendor/assets/images/mingcute/checks_line.svg create mode 100644 vendor/assets/images/mingcute/circle_dash_line.svg create mode 100644 vendor/assets/images/mingcute/hammer_fill.svg create mode 100644 vendor/assets/images/mingcute/play_circle_fill.svg create mode 100644 vendor/assets/images/mingcute/signature_line.svg create mode 100644 vendor/assets/images/mingcute/tool_line.svg 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 @@ +circle_dash_line \ 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