Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 12:08:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 12:08:11 +0300
commit026a5e91019666751e54629b91ebbdefec95c5bc (patch)
treef755e5ba388b0fed37faf7647ef841c58dbe5f6b /app
parent864dae0d98424b463501c21eda1b633c14956fa9 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci_secure_files/components/secure_files_list.vue2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js20
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json3
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js25
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js32
-rw-r--r--app/controllers/clusters/clusters_controller.rb106
-rw-r--r--app/controllers/groups_controller.rb6
-rw-r--r--app/controllers/projects/commits_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb11
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb9
-rw-r--r--app/graphql/types/work_item_type.rb2
-rw-r--r--app/graphql/types/work_items/widget_interface.rb25
-rw-r--r--app/graphql/types/work_items/widget_type_enum.rb14
-rw-r--r--app/graphql/types/work_items/widgets/description_type.rb25
-rw-r--r--app/models/user.rb42
-rw-r--r--app/models/work_item.rb6
-rw-r--r--app/models/work_items/type.rb16
-rw-r--r--app/models/work_items/widgets/base.rb21
-rw-r--r--app/models/work_items/widgets/description.rb9
-rw-r--r--app/views/groups/issues.html.haml28
-rw-r--r--app/views/projects/issues/index.html.haml31
21 files changed, 146 insertions, 289 deletions
diff --git a/app/assets/javascripts/ci_secure_files/components/secure_files_list.vue b/app/assets/javascripts/ci_secure_files/components/secure_files_list.vue
index dbc4565b19d..ebcc4b85ac4 100644
--- a/app/assets/javascripts/ci_secure_files/components/secure_files_list.vue
+++ b/app/assets/javascripts/ci_secure_files/components/secure_files_list.vue
@@ -191,7 +191,7 @@ export default {
<div class="col-md-12 col-lg-6">
<div class="gl-display-flex gl-flex-wrap gl-justify-content-end">
- <gl-button v-if="admin" class="gl-mt-3" variant="info" @click="loadFileSelctor">
+ <gl-button v-if="admin" class="gl-mt-3" variant="confirm" @click="loadFileSelctor">
<span v-if="uploading">
<gl-loading-icon size="sm" class="gl-my-5" inline />
{{ $options.i18n.uploadingLabel }}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 6216ab5401d..359a276aa74 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -1,5 +1,3 @@
-import { __ } from '~/locale';
-
export default class FilteredSearchTokenKeys {
constructor(tokenKeys = [], alternativeTokenKeys = [], conditions = []) {
this.tokenKeys = tokenKeys;
@@ -76,24 +74,6 @@ export default class FilteredSearchTokenKeys {
);
}
- addExtraTokensForIssues() {
- const confidentialToken = {
- formattedKey: __('Confidential'),
- key: 'confidential',
- type: 'string',
- param: '',
- symbol: '',
- icon: 'eye-slash',
- tag: __('Yes or No'),
- lowercaseValueOnSubmit: true,
- uppercaseTokenName: false,
- capitalizeTokenValue: true,
- };
-
- this.tokenKeys.push(confidentialToken);
- this.tokenKeysWithAlternative.push(confidentialToken);
- }
-
removeTokensForKeys(...keys) {
const keysSet = new Set(keys);
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index 7ca3f20ec1c..3885be1dadc 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -129,5 +129,8 @@
"VulnerabilityLocationGeneric",
"VulnerabilityLocationSast",
"VulnerabilityLocationSecretDetection"
+ ],
+ "WorkItemWidget": [
+ "WorkItemWidgetDescription"
]
}
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 725c38defc3..912a4ea2c11 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,26 +1,3 @@
-import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import { initBulkUpdateSidebar } from '~/issuable/bulk_update_sidebar';
import { mountIssuesListApp } from '~/issues/list';
-import initManualOrdering from '~/issues/manual_ordering';
-import { FILTERED_SEARCH } from '~/filtered_search/constants';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
-import projectSelect from '~/project_select';
-if (gon.features?.vueIssuesList) {
- mountIssuesListApp();
-} else {
- const ISSUE_BULK_UPDATE_PREFIX = 'issue_';
-
- IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
- IssuableFilteredSearchTokenKeys.removeTokensForKeys('release');
- initBulkUpdateSidebar(ISSUE_BULK_UPDATE_PREFIX);
-
- initFilteredSearch({
- page: FILTERED_SEARCH.ISSUES,
- isGroupDecendent: true,
- useDefaultState: true,
- filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
- });
- projectSelect();
- initManualOrdering();
-}
+mountIssuesListApp();
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index 44b1d5277d1..b320d8a61c2 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -1,34 +1,6 @@
-import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
-import { initBulkUpdateSidebar, initIssueStatusSelect } from '~/issuable/bulk_update_sidebar';
import { mountIssuesListApp, mountJiraIssuesListApp } from '~/issues/list';
-import initManualOrdering from '~/issues/manual_ordering';
-import { FILTERED_SEARCH } from '~/filtered_search/constants';
-import { ISSUABLE_INDEX } from '~/issuable/constants';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
-import UsersSelect from '~/users_select';
-
-if (gon.features?.vueIssuesList) {
- mountIssuesListApp();
-} else {
- IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
-
- initFilteredSearch({
- page: FILTERED_SEARCH.ISSUES,
- filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
- useDefaultState: true,
- });
-
- initBulkUpdateSidebar(ISSUABLE_INDEX.ISSUE);
- initIssueStatusSelect();
- new UsersSelect(); // eslint-disable-line no-new
-
- initCsvImportExportButtons();
- initIssuableByEmail();
- initManualOrdering();
-}
-
-new ShortcutsNavigation(); // eslint-disable-line no-new
+mountIssuesListApp();
mountJiraIssuesListApp();
+new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index ae3b6125bde..a04fd09aa22 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -8,7 +8,7 @@ class Clusters::ClustersController < Clusters::BaseController
before_action :cluster, only: [:cluster_status, :show, :update, :destroy, :clear_cache]
before_action :user_cluster, only: [:connect]
before_action :authorize_read_cluster!, only: [:show, :index]
- before_action :authorize_create_cluster!, only: [:connect, :authorize_aws_role]
+ before_action :authorize_create_cluster!, only: [:connect]
before_action :authorize_update_cluster!, only: [:update]
before_action :update_applications_status, only: [:cluster_status]
before_action :ensure_feature_enabled!, except: [:index, :new_cluster_docs]
@@ -16,15 +16,6 @@ class Clusters::ClustersController < Clusters::BaseController
helper_method :token_in_session
STATUS_POLLING_INTERVAL = 10_000
- AWS_CSP_DOMAINS = %w[https://ec2.ap-east-1.amazonaws.com https://ec2.ap-northeast-1.amazonaws.com https://ec2.ap-northeast-2.amazonaws.com https://ec2.ap-northeast-3.amazonaws.com https://ec2.ap-south-1.amazonaws.com https://ec2.ap-southeast-1.amazonaws.com https://ec2.ap-southeast-2.amazonaws.com https://ec2.ca-central-1.amazonaws.com https://ec2.eu-central-1.amazonaws.com https://ec2.eu-north-1.amazonaws.com https://ec2.eu-west-1.amazonaws.com https://ec2.eu-west-2.amazonaws.com https://ec2.eu-west-3.amazonaws.com https://ec2.me-south-1.amazonaws.com https://ec2.sa-east-1.amazonaws.com https://ec2.us-east-1.amazonaws.com https://ec2.us-east-2.amazonaws.com https://ec2.us-west-1.amazonaws.com https://ec2.us-west-2.amazonaws.com https://ec2.af-south-1.amazonaws.com https://iam.amazonaws.com].freeze
-
- content_security_policy do |p|
- next if p.directives.blank?
-
- default_connect_src = p.directives['connect-src'] || p.directives['default-src']
- connect_src_values = Array.wrap(default_connect_src) | AWS_CSP_DOMAINS
- p.connect_src(*connect_src_values)
- end
def index
@clusters = cluster_list
@@ -95,19 +86,6 @@ class Clusters::ClustersController < Clusters::BaseController
redirect_to clusterable.index_path, status: :found
end
- def create_aws
- @aws_cluster = ::Clusters::CreateService
- .new(current_user, create_aws_cluster_params)
- .execute
- .present(current_user: current_user)
-
- if @aws_cluster.persisted?
- head :created, location: @aws_cluster.show_path
- else
- render status: :unprocessable_entity, json: @aws_cluster.errors
- end
- end
-
def create_user
@user_cluster = ::Clusters::CreateService
.new(current_user, create_user_cluster_params)
@@ -117,23 +95,10 @@ class Clusters::ClustersController < Clusters::BaseController
if @user_cluster.persisted?
redirect_to @user_cluster.show_path
else
- generate_gcp_authorize_url
- validate_gcp_token
- gcp_cluster
-
render :connect
end
end
- def authorize_aws_role
- response = Clusters::Aws::AuthorizeRoleService.new(
- current_user,
- params: aws_role_params
- ).execute
-
- render json: response.body, status: response.status
- end
-
def clear_cache
cluster.delete_cached_resources!
@@ -204,27 +169,6 @@ class Clusters::ClustersController < Clusters::BaseController
end
end
- def create_aws_cluster_params
- params.require(:cluster).permit(
- *base_permitted_cluster_params,
- :name,
- provider_aws_attributes: [
- :kubernetes_version,
- :key_name,
- :role_arn,
- :region,
- :vpc_id,
- :instance_type,
- :num_nodes,
- :security_group_id,
- subnet_ids: []
- ]).merge(
- provider_type: :aws,
- platform_type: :kubernetes,
- clusterable: clusterable.__subject__
- )
- end
-
def create_user_cluster_params
params.require(:cluster).permit(
*base_permitted_cluster_params,
@@ -242,29 +186,6 @@ class Clusters::ClustersController < Clusters::BaseController
)
end
- def aws_role_params
- params.require(:cluster).permit(:role_arn, :region)
- end
-
- def generate_gcp_authorize_url
- connect_path = clusterable.connect_path().to_s
- error_path = @project ? project_clusters_path(@project) : connect_path
-
- state = generate_session_key_redirect(connect_path, error_path)
-
- @authorize_url = GoogleApi::CloudPlatform::Client.new(
- nil, callback_google_api_auth_url,
- state: state).authorize_url
- rescue GoogleApi::Auth::ConfigMissingError
- # no-op
- end
-
- def gcp_cluster
- cluster = Clusters::BuildService.new(clusterable.__subject__).execute
- cluster.build_provider_gcp
- @gcp_cluster = cluster.present(current_user: current_user)
- end
-
def proxyable
cluster.cluster
end
@@ -295,11 +216,6 @@ class Clusters::ClustersController < Clusters::BaseController
@user_cluster = cluster.present(current_user: current_user)
end
- def validate_gcp_token
- @valid_gcp_token = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
- .validate_token(expires_at_in_session)
- end
-
def token_in_session
session[GoogleApi::CloudPlatform::Client.session_key_for_token]
end
@@ -309,26 +225,6 @@ class Clusters::ClustersController < Clusters::BaseController
session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
end
- def generate_session_key_redirect(uri, error_uri)
- GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
- session[key] = uri
- session[:error_uri] = error_uri
- end
- end
-
- ##
- # Unfortunately the EC2 API doesn't provide a list of
- # possible instance types. There is a workaround, using
- # the Pricing API, but instead of requiring the
- # user to grant extra permissions for this we use the
- # values that validate the CloudFormation template.
- def load_instance_types
- stack_template = File.read(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml'))
- instance_types = YAML.safe_load(stack_template).dig('Parameters', 'NodeInstanceType', 'AllowedValues')
-
- instance_types.map { |type| Hash(name: type, value: type) }
- end
-
def update_applications_status
@cluster.applications.each(&:schedule_status_update)
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 8e395a6f446..fd3bcc67b12 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -30,10 +30,6 @@ class GroupsController < Groups::ApplicationController
before_action :user_actions, only: [:show]
- before_action do
- push_frontend_feature_flag(:vue_issues_list, @group)
- end
-
before_action :check_export_rate_limit!, only: [:export, :download_export]
before_action :track_experiment_event, only: [:new]
@@ -212,7 +208,7 @@ class GroupsController < Groups::ApplicationController
end
def issues
- return super if !html_request? || Feature.disabled?(:vue_issues_list, group)
+ return super unless html_request?
@has_issues = IssuesFinder.new(current_user, group_id: group.id, include_subgroups: true).execute
.non_archived
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 60b8e45f5be..f4125fd0a15 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -84,7 +84,7 @@ class Projects::CommitsController < Projects::ApplicationController
@commits.each(&:lazy_author) # preload authors
- @commits = @commits.with_latest_pipeline(@ref)
+ @commits = @commits.with_markdown_cache.with_latest_pipeline(@ref)
@commits = set_commits_for_rendering(@commits)
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 3763fcf6c4d..acca85c0bf9 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -23,7 +23,7 @@ class Projects::IssuesController < Projects::ApplicationController
after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
before_action :set_issuables_index, if: ->(c) {
- SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !vue_issues_list?
+ SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !index_html_request?
}
# Allow write(create) issue
@@ -39,7 +39,6 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_download_code!, only: [:related_branches]
before_action do
- push_frontend_feature_flag(:vue_issues_list, project&.group)
push_frontend_feature_flag(:contacts_autocomplete, project&.group)
push_frontend_feature_flag(:incident_timeline, project)
end
@@ -82,7 +81,7 @@ class Projects::IssuesController < Projects::ApplicationController
attr_accessor :vulnerability_id
def index
- if vue_issues_list?
+ if index_html_request?
set_sort_order
else
@issues = @issuables
@@ -258,10 +257,8 @@ class Projects::IssuesController < Projects::ApplicationController
protected
- def vue_issues_list?
- action_name.to_sym == :index &&
- html_request? &&
- Feature.enabled?(:vue_issues_list, project&.group)
+ def index_html_request?
+ action_name.to_sym == :index && html_request?
end
def sorting_field
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index ee50327be8f..491074f39f9 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -27,14 +27,7 @@ module Projects
).to_json
end
- if current_user.ci_owned_runners_cross_joins_fix_enabled?
- render
- else
- # @assignable_runners is using ci_owned_runners
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336436') do
- render
- end
- end
+ render
end
def update
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
index cd784d54959..18b9bfd1c9a 100644
--- a/app/graphql/types/work_item_type.rb
+++ b/app/graphql/types/work_item_type.rb
@@ -18,6 +18,8 @@ module Types
description: 'State of the work item.'
field :title, GraphQL::Types::String, null: false,
description: 'Title of the work item.'
+ field :widgets, [Types::WorkItems::WidgetInterface], null: true,
+ description: 'Collection of widgets that belong to the work item.'
field :work_item_type, Types::WorkItems::TypeType, null: false,
description: 'Type assigned to the work item.'
diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb
new file mode 100644
index 00000000000..67765c5b432
--- /dev/null
+++ b/app/graphql/types/work_items/widget_interface.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module WidgetInterface
+ include Types::BaseInterface
+
+ graphql_name 'WorkItemWidget'
+
+ field :type, ::Types::WorkItems::WidgetTypeEnum, null: true,
+ description: 'Widget type.'
+
+ def self.resolve_type(object, context)
+ case object
+ when ::WorkItems::Widgets::Description
+ ::Types::WorkItems::Widgets::DescriptionType
+ else
+ raise "Unknown GraphQL type for widget #{object}"
+ end
+ end
+
+ orphan_types ::Types::WorkItems::Widgets::DescriptionType
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widget_type_enum.rb b/app/graphql/types/work_items/widget_type_enum.rb
new file mode 100644
index 00000000000..4e5933bff86
--- /dev/null
+++ b/app/graphql/types/work_items/widget_type_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ class WidgetTypeEnum < BaseEnum
+ graphql_name 'WorkItemWidgetType'
+ description 'Type of a work item widget'
+
+ ::WorkItems::Type.available_widgets.each do |widget|
+ value widget.type.to_s.upcase, value: widget.type, description: "#{widget.type.to_s.titleize} widget."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/description_type.rb b/app/graphql/types/work_items/widgets/description_type.rb
new file mode 100644
index 00000000000..79192d7c3d4
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/description_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ # Disabling widget level authorization as it might be too granular
+ # and we already authorize the parent work item
+ # rubocop:disable Graphql/AuthorizeTypes
+ class DescriptionType < BaseObject
+ graphql_name 'WorkItemWidgetDescription'
+ description 'Represents a description widget'
+
+ implements Types::WorkItems::WidgetInterface
+
+ field :description, GraphQL::Types::String, null: true,
+ description: 'Description of the work item.'
+
+ markdown_field :description_html, null: true do |resolved_object|
+ resolved_object.work_item
+ end
+ end
+ # rubocop:enable Graphql/AuthorizeTypes
+ end
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 8aae4441852..982398e846b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1650,33 +1650,15 @@ class User < ApplicationRecord
def ci_owned_runners
@ci_owned_runners ||= begin
- if ci_owned_runners_cross_joins_fix_enabled?
- Ci::Runner
- .from_union([ci_owned_project_runners_from_project_members,
- ci_owned_project_runners_from_group_members,
- ci_owned_group_runners])
- else
- Ci::Runner
- .from_union([ci_legacy_owned_project_runners, ci_legacy_owned_group_runners])
- .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336436')
- end
+ Ci::Runner
+ .from_union([ci_owned_project_runners_from_project_members,
+ ci_owned_project_runners_from_group_members,
+ ci_owned_group_runners])
end
end
def owns_runner?(runner)
- if ci_owned_runners_cross_joins_fix_enabled?
- ci_owned_runners.exists?(runner.id)
- else
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336436') do
- ci_owned_runners.exists?(runner.id)
- end
- end
- end
-
- def ci_owned_runners_cross_joins_fix_enabled?
- strong_memoize(:ci_owned_runners_cross_joins_fix_enabled) do
- Feature.enabled?(:ci_owned_runners_cross_joins_fix, self)
- end
+ ci_owned_runners.exists?(runner.id)
end
def notification_email_for(notification_group)
@@ -2258,20 +2240,6 @@ class User < ApplicationRecord
::Gitlab::Auth::Ldap::Access.allowed?(self)
end
- def ci_legacy_owned_project_runners
- Ci::RunnerProject
- .select('ci_runners.*')
- .joins(:runner)
- .where(project: authorized_projects(Gitlab::Access::MAINTAINER))
- end
-
- def ci_legacy_owned_group_runners
- Ci::RunnerNamespace
- .select('ci_runners.*')
- .joins(:runner)
- .where(namespace_id: owned_groups.self_and_descendant_ids)
- end
-
def ci_owned_project_runners_from_project_members
project_ids = project_members.where('access_level >= ?', Gitlab::Access::MAINTAINER).pluck(:source_id)
diff --git a/app/models/work_item.rb b/app/models/work_item.rb
index 84646daf59b..381b5650167 100644
--- a/app/models/work_item.rb
+++ b/app/models/work_item.rb
@@ -15,6 +15,12 @@ class WorkItem < Issue
'issue'
end
+ def widgets
+ work_item_type.widgets.map do |widget_class|
+ widget_class.new(self)
+ end
+ end
+
private
def record_create_action
diff --git a/app/models/work_items/type.rb b/app/models/work_items/type.rb
index 0d390fa131d..f708a30f128 100644
--- a/app/models/work_items/type.rb
+++ b/app/models/work_items/type.rb
@@ -20,6 +20,14 @@ module WorkItems
task: { name: 'Task', icon_name: 'issue-type-task', enum_value: 4 }
}.freeze
+ WIDGETS_FOR_TYPE = {
+ issue: [Widgets::Description],
+ incident: [Widgets::Description],
+ test_case: [Widgets::Description],
+ requirement: [Widgets::Description],
+ task: [Widgets::Description]
+ }.freeze
+
cache_markdown_field :description, pipeline: :single_line
enum base_type: BASE_TYPES.transform_values { |value| value[:enum_value] }
@@ -40,6 +48,10 @@ module WorkItems
scope :order_by_name_asc, -> { order(arel_table[:name].lower.asc) }
scope :by_type, ->(base_type) { where(base_type: base_type) }
+ def self.available_widgets
+ WIDGETS_FOR_TYPE.values.flatten.uniq
+ end
+
def self.default_by_type(type)
found_type = find_by(namespace_id: nil, base_type: type)
return found_type if found_type
@@ -60,6 +72,10 @@ module WorkItems
namespace.blank?
end
+ def widgets
+ WIDGETS_FOR_TYPE[base_type.to_sym]
+ end
+
private
def strip_whitespace
diff --git a/app/models/work_items/widgets/base.rb b/app/models/work_items/widgets/base.rb
new file mode 100644
index 00000000000..9d1e48690e0
--- /dev/null
+++ b/app/models/work_items/widgets/base.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ class Base
+ def self.type
+ name.demodulize.underscore.to_sym
+ end
+
+ def type
+ self.class.type
+ end
+
+ def initialize(work_item)
+ @work_item = work_item
+ end
+
+ attr_reader :work_item
+ end
+ end
+end
diff --git a/app/models/work_items/widgets/description.rb b/app/models/work_items/widgets/description.rb
new file mode 100644
index 00000000000..1e84d172bef
--- /dev/null
+++ b/app/models/work_items/widgets/description.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ class Description < Base
+ delegate :description, to: :work_item
+ end
+ end
+end
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 209faa937dc..925e7d46f14 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -1,28 +1,8 @@
-- @can_bulk_update = can?(current_user, :admin_issue, @group) && @group.licensed_feature_available?(:group_bulk_edit)
-
-- page_title _("Issues")
+- page_title _('Issues')
- add_page_specific_style 'page_bundles/issues_list'
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
-- if Feature.enabled?(:vue_issues_list, @group)
- .js-issues-list{ data: group_issues_list_data(@group, current_user) }
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
-- else
- .top-area
- = render 'shared/issuable/nav', type: :issues
- .nav-controls
- = render 'shared/issuable/feed_buttons'
-
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/bulk_update_button', type: :issues
-
- = render 'shared/new_project_item_select', path: 'issues/new', label: _("issue"), type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
-
- = render 'shared/issuable/search_bar', type: :issues
-
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
-
- = render 'shared/issues', project_select_button: true
+.js-issues-list{ data: group_issues_list_data(@group, current_user) }
+- if can?(current_user, :admin_issue, @group) && @group.licensed_feature_available?(:group_bulk_edit)
+ = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index fe2be0f73c9..b730eb5072e 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -1,10 +1,5 @@
-- @can_bulk_update = can?(current_user, :admin_issue, @project)
-
-- page_title _("Issues")
-- new_issue_email = @project.new_issuable_address(current_user, 'issue')
+- page_title _('Issues')
- add_page_specific_style 'page_bundles/issues_list'
-- issuable_type = 'issue'
-
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")
@@ -13,24 +8,6 @@
issues_path: project_issues_path(@project),
project_path: @project.full_path } }
-- if Feature.enabled?(:vue_issues_list, @project&.group)
- .js-issues-list{ data: project_issues_list_data(@project, current_user) }
- - if @can_bulk_update
- = render 'shared/issuable/bulk_update_sidebar', type: :issues
-- elsif project_issues(@project).exists?
- .top-area
- = render 'shared/issuable/nav', type: :issues
- = render "projects/issues/nav_btns"
- = render 'shared/issuable/search_bar', type: :issues
-
- - if @can_bulk_update
- = render 'shared/issuable/bulk_update_sidebar', type: :issues
-
- .issues-holder
- = render 'issues'
- - if new_issue_email
- .gl-text-center.gl-pt-5.gl-pb-7
- .js-issuable-by-email{ data: { initial_email: new_issue_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
-- else
- - new_project_issue_button_path = @project.archived? ? false : new_project_issue_path(@project)
- = render 'shared/empty_states/issues', new_project_issue_button_path: new_project_issue_button_path, show_import_button: true
+.js-issues-list{ data: project_issues_list_data(@project, current_user) }
+- if can?(current_user, :admin_issue, @project)
+ = render 'shared/issuable/bulk_update_sidebar', type: :issues