Skip to content

WorkItems: Introduce color widget to EPIC work item type

Abhilash Kotte requested to merge 394863-add-color-widget-to-work-items into master

What does this MR do and why?

Add new widget(WorkItems::Color) to support the color highlight feature present in epics.

  • The `color` attribute should be stored in a separate table(work_item_colors).
  • Add this widget to Epic WorkItemType(post migration and add it to BaseTypeImporter file)
  • Have this featured licensed under EE
  • Add a GraphQl Query to include color widget to workItem query

GraphQl Query

{
  workItem(id: "gid://gitlab/WorkItem/652") {
    id,
    workItemType {
      id,
      name
    },
    widgets {
      type
      ... on WorkItemWidgetColor {
        color,
        textColor,
        type
      }
    }
  }
}
GraphQl Response
{
  "data": {
    "workItem": {
      "id": "gid://gitlab/WorkItem/652",
      "workItemType": {
        "id": "gid://gitlab/WorkItems::Type/8",
        "name": "Epic"
      },
      "widgets": [
        {
          "type": "ASSIGNEES"
        },
        {
          "type": "DESCRIPTION"
        },
        {
          "type": "HIERARCHY"
        },
        {
          "type": "LABELS"
        },
        {
          "type": "NOTES"
        },
        {
          "type": "START_AND_DUE_DATE"
        },
        {
          "type": "HEALTH_STATUS"
        },
        {
          "type": "STATUS"
        },
        {
          "type": "NOTIFICATIONS"
        },
        {
          "type": "AWARD_EMOJI"
        },
        {
          "type": "LINKED_ITEMS"
        },
        {
          "type": "CURRENT_USER_TODOS"
        },
        {
          "type": "COLOR",
          "color": "#1068bf",
          "textColor": "#FFFFFF"
        }
      ]
    }
  }
}

Migrations

bundle exec rails db:migrate:up:main VERSION=20231220113459
main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 66847
main: == 20231220113459 AddWorkItemColor: migrating =================================
main: -- create_table(:work_item_colors, {:id=>false})
main: -- quote_column_name(:color)
main:    -> 0.0000s
main:    -> 0.0057s
main: == 20231220113459 AddWorkItemColor: migrated (0.0649s) ========================

main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 66847
bundle exec rails db:migrate:up:ci VERSION=20231220113459
ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 67694
ci: == 20231220113459 AddWorkItemColor: migrating =================================
ci: -- create_table(:work_item_colors, {:id=>false})
ci: -- quote_column_name(:color)
ci:    -> 0.0000s
ci:    -> 0.0056s
I, [2023-12-26T16:10:30.015582 #67540]  INFO -- : Database: 'ci', Table: 'work_item_colors': Lock Writes
ci: == 20231220113459 AddWorkItemColor: migrated (0.0626s) ========================

ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 67694
bundle exec rails db:migrate:up:main VERSION=20231220115201
main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 68348
main: == 20231220115201 AddColorWorkItemWidget: migrating ===========================
main: == 20231220115201 AddColorWorkItemWidget: migrated (0.0213s) ==================

main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 68348
bundle exec rails db:migrate:up:ci VERSION=20231220115201
ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 68797
ci: == 20231220115201 AddColorWorkItemWidget: migrating ===========================
ci: -- The migration is skipped since it modifies the schemas: [:gitlab_main].
ci: -- This database can only apply migrations in one of the following schemas: [:gitlab_ci, :gitlab_internal, :gitlab_shared].
ci: == 20231220115201 AddColorWorkItemWidget: migrated (0.0077s) ==================

ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 68797
bundle exec rails db:migrate:up:main VERSION=20231226052618
main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 69359
main: == 20231226052618 AddWorkItemColorsForeignKeys: migrating =====================
main: -- transaction_open?(nil)
main:    -> 0.0000s
main: -- transaction_open?(nil)
main:    -> 0.0000s
main: -- execute("ALTER TABLE work_item_colors ADD CONSTRAINT fk_b15b0912d0 FOREIGN KEY (namespace_id) REFERENCES namespaces (id) ON DELETE SET NULL NOT VALID;")
main:    -> 0.0013s
main: -- execute("SET statement_timeout TO 0")
main:    -> 0.0001s
main: -- execute("ALTER TABLE work_item_colors VALIDATE CONSTRAINT fk_b15b0912d0;")
main:    -> 0.0015s
main: -- execute("RESET statement_timeout")
main:    -> 0.0002s
main: -- transaction_open?(nil)
main:    -> 0.0000s
main: -- view_exists?(:postgres_partitions)
main:    -> 0.0004s
main: -- index_exists?(:work_item_colors, :namespace_id, {:name=>"wi_colors_namespace_id_index", :algorithm=>:concurrently})
main:    -> 0.0010s
main: -- add_index(:work_item_colors, :namespace_id, {:name=>"wi_colors_namespace_id_index", :algorithm=>:concurrently})
main:    -> 0.0013s
main: == 20231226052618 AddWorkItemColorsForeignKeys: migrated (0.0949s) ============

main: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 69359
bundle exec rails db:migrate:up:ci VERSION=20231226052618
ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 69914
ci: == 20231226052618 AddWorkItemColorsForeignKeys: migrating =====================
ci: -- transaction_open?(nil)
ci:    -> 0.0000s
ci: -- transaction_open?(nil)
ci:    -> 0.0000s
ci: -- execute("ALTER TABLE work_item_colors ADD CONSTRAINT fk_b15b0912d0 FOREIGN KEY (namespace_id) REFERENCES namespaces (id) ON DELETE SET NULL NOT VALID;")
ci:    -> 0.0010s
ci: -- execute("SET statement_timeout TO 0")
ci:    -> 0.0001s
ci: -- execute("ALTER TABLE work_item_colors VALIDATE CONSTRAINT fk_b15b0912d0;")
ci:    -> 0.0066s
ci: -- execute("RESET statement_timeout")
ci:    -> 0.0002s
ci: -- transaction_open?(nil)
ci:    -> 0.0000s
ci: -- view_exists?(:postgres_partitions)
ci:    -> 0.0004s
ci: -- index_exists?(:work_item_colors, :namespace_id, {:name=>"wi_colors_namespace_id_index", :algorithm=>:concurrently})
ci:    -> 0.0010s
ci: -- add_index(:work_item_colors, :namespace_id, {:name=>"wi_colors_namespace_id_index", :algorithm=>:concurrently})
ci:    -> 0.0011s
ci: == 20231226052618 AddWorkItemColorsForeignKeys: migrated (0.0967s) ============

ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 69914
bundle exec rails db:migrate:down:main VERSION=20231220113459
main: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 74015
main: == 20231220113459 AddWorkItemColor: reverting =================================
main: -- drop_table(:work_item_colors)
main:    -> 0.0016s
main: == 20231220113459 AddWorkItemColor: reverted (0.0045s) ========================

main: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 74015
bundle exec rails db:migrate:down:ci VERSION=20231220113459
ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 73514
ci: == 20231220113459 AddWorkItemColor: reverting =================================
ci: -- drop_table(:work_item_colors)
ci:    -> 0.0017s
ci: == 20231220113459 AddWorkItemColor: reverted (0.0095s) ========================

ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 73514
bundle exec rails db:migrate:down:main VERSION=20231220115201
main: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 72908
main: == 20231220115201 AddColorWorkItemWidget: reverting ===========================
main: == 20231220115201 AddColorWorkItemWidget: reverted (0.0142s) ==================

main: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 72908
bundle exec rails db:migrate:down:ci VERSION=20231220115201
ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 72465
ci: == 20231220115201 AddColorWorkItemWidget: reverting ===========================
ci: -- The migration is skipped since it modifies the schemas: [:gitlab_main].
ci: -- This database can only apply migrations in one of the following schemas: [:gitlab_ci, :gitlab_internal, :gitlab_shared].
ci: == 20231220115201 AddColorWorkItemWidget: reverted (0.0080s) ==================

ci: == [advisory_lock_connection] object_id: 182360, pg_backend_pid: 72465
bundle exec rails db:migrate:down:main VERSION=20231226052618
main: == [advisory_lock_connection] object_id: 182420, pg_backend_pid: 77815
main: == 20231226052618 AddWorkItemColorsForeignKeys: reverting =====================
main: -- transaction_open?(nil)
main:    -> 0.0000s
main: -- view_exists?(:postgres_partitions)
main:    -> 0.1822s
main: -- indexes(:work_item_colors)
main:    -> 0.0022s
main: -- execute("SET statement_timeout TO 0")
main:    -> 0.0001s
main: -- remove_index(:work_item_colors, {:algorithm=>:concurrently, :name=>"wi_colors_namespace_id_index"})
main:    -> 0.0017s
main: -- execute("RESET statement_timeout")
main:    -> 0.0001s
main: -- remove_foreign_key(:work_item_colors, :namespaces, {:column=>:namespace_id})
main:    -> 0.0025s
main: == 20231226052618 AddWorkItemColorsForeignKeys: reverted (0.2138s) ============

main: == [advisory_lock_connection] object_id: 182420, pg_backend_pid: 77815
bundle exec rails db:migrate:down:ci VERSION=20231226052618
ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 78266
ci: == 20231226052618 AddWorkItemColorsForeignKeys: reverting =====================
ci: -- transaction_open?(nil)
ci:    -> 0.0000s
ci: -- view_exists?(:postgres_partitions)
ci:    -> 0.0996s
ci: -- indexes(:work_item_colors)
ci:    -> 0.0020s
ci: -- execute("SET statement_timeout TO 0")
ci:    -> 0.0001s
ci: -- remove_index(:work_item_colors, {:algorithm=>:concurrently, :name=>"wi_colors_namespace_id_index"})
ci:    -> 0.0011s
ci: -- execute("RESET statement_timeout")
ci:    -> 0.0001s
ci: -- remove_foreign_key(:work_item_colors, :namespaces, {:column=>:namespace_id})
ci:    -> 0.0025s
ci: == 20231226052618 AddWorkItemColorsForeignKeys: reverted (0.1297s) ============

ci: == [advisory_lock_connection] object_id: 182340, pg_backend_pid: 78266

How to set up and validate locally

  1. Run bundle exec rails db:migrate
  2. Enable namespace_level_work_items FF - Feature.enable(:namespace_level_work_items)
  3. Once done, visit any group on GDK and then navigate to its /work_items path, eg; https://gitlab.com/groups/gitlab-org/plan-stage/-/work_items. You should see a Create epic button and that will create a Work Item at group-level with type Epic. Copy the Gid of it.
  4. Got to graphql-explorer and enter the query mentioned above with the newly created epic Id. You should see default value for color returned.
  5. From rails console create a progress record for the objective you have created above WorkItems::Color.create(color: '#217645', issue_id: {replace with epic id})
  6. Repeat step number 4 to see updated color.

Related to #394863 (closed)

Edited by Abhilash Kotte

Merge request reports