From 7173270eb496d0bec6759a22c4af7a4f37ca8dd7 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 24 Mar 2022 15:09:10 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/issue_templates/Default.md | 11 ++ .gitlab/merge_request_templates/Default.md | 44 +++++++ .rubocop.yml | 1 + .rubocop_todo.yml | 26 ---- .../metrics/perceived_complexity.yml | 24 ++++ app/assets/javascripts/sidebar/graphql.js | 3 - .../javascripts/work_items/constants.js | 4 - .../work_items/graphql/provider.js | 36 +----- .../work_items/graphql/resolvers.js | 29 ----- .../work_items/graphql/typedefs.graphql | 56 --------- .../graphql/widget.fragment.graphql | 3 - .../work_items/pages/create_work_item.vue | 4 - .../dashboard/application_controller.rb | 2 +- .../projects/pipelines_controller.rb | 2 +- .../routing/pseudonymization_helper.rb | 4 + app/models/project.rb | 10 +- app/services/concerns/deploy_token_methods.rb | 2 +- doc/api/linked_epics.md | 119 ++++++++++++++++++ .../testing_guide/best_practices.md | 6 +- doc/integration/jira/issues.md | 2 +- doc/user/admin_area/index.md | 23 ++-- .../project/issues/sorting_issue_lists.md | 21 +--- doc/user/project/requirements/index.md | 2 +- doc/user/search/img/sort_projects.png | Bin 59495 -> 0 bytes doc/user/search/index.md | 12 +- lib/api/snippets.rb | 2 +- spec/finders/concerns/finder_methods_spec.rb | 2 + .../finder_with_cross_project_access_spec.rb | 4 +- .../components/work_item_title_spec.js | 18 ++- spec/frontend/work_items/mock_data.js | 57 +++------ .../work_items/pages/create_work_item_spec.js | 14 +-- .../work_items/pages/work_item_detail_spec.js | 6 +- spec/frontend/work_items/router_spec.js | 2 +- .../routing/pseudonymization_helper_spec.rb | 6 +- .../lib/gitlab/search_context/builder_spec.rb | 1 - spec/models/project_spec.rb | 45 +++---- 36 files changed, 307 insertions(+), 296 deletions(-) create mode 100644 .gitlab/issue_templates/Default.md create mode 100644 .gitlab/merge_request_templates/Default.md create mode 100644 .rubocop_todo/metrics/perceived_complexity.yml delete mode 100644 app/assets/javascripts/work_items/graphql/resolvers.js delete mode 100644 app/assets/javascripts/work_items/graphql/typedefs.graphql delete mode 100644 app/assets/javascripts/work_items/graphql/widget.fragment.graphql delete mode 100644 doc/user/search/img/sort_projects.png diff --git a/.gitlab/issue_templates/Default.md b/.gitlab/issue_templates/Default.md new file mode 100644 index 00000000000..f87b82e341b --- /dev/null +++ b/.gitlab/issue_templates/Default.md @@ -0,0 +1,11 @@ +Before raising an issue to the GitLab issue tracker, please read through our guide for finding help to determine the best place to post: + +* https://about.gitlab.com/getting-help/ + +If you are experiencing an issue when using GitLab.com, your first port of call should be the Community Forum. Your issue may have already been reported there by another user. Please check: + +* https://forum.gitlab.com/ + +If you feel that your issue can be categorized as a reproducible bug or a feature proposal, please use one of the issue templates provided and include as much information as possible. + +Thank you for helping to make GitLab a better product. diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md new file mode 100644 index 00000000000..9d5ab41afbe --- /dev/null +++ b/.gitlab/merge_request_templates/Default.md @@ -0,0 +1,44 @@ +## What does this MR do and why? + +_Describe in detail what your merge request does and why._ + + + +## Screenshots or screen recordings + +_These are strongly recommended to assist reviewers and reduce the time to merge your change._ + + + +## How to set up and validate locally + +_Numbered steps to set up and validate the change are strongly suggested._ + + + +## MR acceptance checklist + +This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability. + +* [ ] I have evaluated the [MR acceptance checklist](https://docs.gitlab.com/ee/development/code_review.html#acceptance-checklist) for this MR. diff --git a/.rubocop.yml b/.rubocop.yml index 99424713bd8..bf74841b3d0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -48,6 +48,7 @@ AllCops: Metrics/ParameterLists: Exclude: + # See https://gitlab.com/gitlab-org/gitlab/-/issues/356771 - 'app/components/**/*' Cop/AvoidKeywordArgumentsInSidekiqWorkers: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 45dc5864773..c3e4bb0c370 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -107,11 +107,6 @@ Lint/MixedRegexpCaptureTypes: Lint/RedundantCopDisableDirective: Enabled: false -# Offense count: 1 -Lint/SelfAssignment: - Exclude: - - 'spec/lib/gitlab/search_context/builder_spec.rb' - # Offense count: 3 Lint/StructNewOverride: Exclude: @@ -125,11 +120,6 @@ Lint/StructNewOverride: Lint/UselessMethodDefinition: Enabled: false -# Offense count: 14 -# Configuration parameters: IgnoredMethods. -Metrics/PerceivedComplexity: - Max: 25 - # Offense count: 11 # Configuration parameters: EnforcedStyle. # SupportedStyles: lowercase, uppercase @@ -333,22 +323,6 @@ Rails/CreateTableWithTimestamps: Rails/FilePath: Enabled: false -# Offense count: 15 -# Cop supports --auto-correct. -Rails/FindById: - Exclude: - - 'app/controllers/projects/pipelines_controller.rb' - - 'app/services/concerns/deploy_token_methods.rb' - - 'ee/app/controllers/ee/groups/group_members_controller.rb' - - 'ee/lib/api/audit_events.rb' - - 'ee/lib/api/merge_request_approval_rules.rb' - - 'ee/lib/ee/api/groups.rb' - - 'ee/lib/ee/api/projects.rb' - - 'ee/spec/finders/audit_log_finder_spec.rb' - - 'lib/api/snippets.rb' - - 'spec/finders/concerns/finder_methods_spec.rb' - - 'spec/finders/concerns/finder_with_cross_project_access_spec.rb' - # Offense count: 354 # Configuration parameters: Include. # Include: app/models/**/*.rb diff --git a/.rubocop_todo/metrics/perceived_complexity.yml b/.rubocop_todo/metrics/perceived_complexity.yml new file mode 100644 index 00000000000..0f2d3030064 --- /dev/null +++ b/.rubocop_todo/metrics/perceived_complexity.yml @@ -0,0 +1,24 @@ +--- +Metrics/PerceivedComplexity: + Exclude: + - 'app/controllers/admin/application_settings_controller.rb' + - 'app/finders/deployments_finder.rb' + - 'app/helpers/button_helper.rb' + - 'app/helpers/nav/top_nav_helper.rb' + - 'app/helpers/submodule_helper.rb' + - 'app/services/projects/create_service.rb' + - 'ee/app/controllers/ee/groups_controller.rb' + - 'ee/lib/elastic/latest/git_class_proxy.rb' + - 'lib/banzai/filter/references/abstract_reference_filter.rb' + - 'lib/banzai/renderer.rb' + - 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb' + - 'lib/gitlab/conflict/file.rb' + - 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb' + - 'lib/gitlab/diff/parser.rb' + - 'lib/gitlab/utils/merge_hash.rb' + - 'qa/qa/runtime/browser.rb' + - 'qa/qa/specs/runner.rb' + - 'qa/qa/support/repeater.rb' + - 'rubocop/cop/gitlab/mark_used_feature_flags.rb' + - 'sidekiq_cluster/cli.rb' + - 'spec/support/cycle_analytics_helpers/test_generation.rb' diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js index fc757922f09..034bdc71122 100644 --- a/app/assets/javascripts/sidebar/graphql.js +++ b/app/assets/javascripts/sidebar/graphql.js @@ -1,11 +1,9 @@ import produce from 'immer'; import VueApollo from 'vue-apollo'; import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.graphql'; -import { resolvers as workItemResolvers } from '~/work_items/graphql/resolvers'; import createDefaultClient from '~/lib/graphql'; const resolvers = { - ...workItemResolvers, Mutation: { updateIssueState: (_, { issueType = undefined, isDirty = false }, { cache }) => { const sourceData = cache.readQuery({ query: getIssueStateQuery }); @@ -14,7 +12,6 @@ const resolvers = { }); cache.writeQuery({ query: getIssueStateQuery, data }); }, - ...workItemResolvers.Mutation, }, }; diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js index 22f24ad8af6..d3bcaf0f95f 100644 --- a/app/assets/javascripts/work_items/constants.js +++ b/app/assets/javascripts/work_items/constants.js @@ -4,7 +4,3 @@ export const i18n = { fetchError: s__('WorkItem|Something went wrong when fetching the work item. Please try again.'), updateError: s__('WorkItem|Something went wrong while updating the work item. Please try again.'), }; - -export const widgetTypes = { - title: 'TITLE', -}; diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js index c15382874d8..3c2955ce1e2 100644 --- a/app/assets/javascripts/work_items/graphql/provider.js +++ b/app/assets/javascripts/work_items/graphql/provider.js @@ -1,45 +1,11 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import workItemQuery from './work_item.query.graphql'; -import { resolvers } from './resolvers'; -import typeDefs from './typedefs.graphql'; export function createApolloProvider() { Vue.use(VueApollo); - const defaultClient = createDefaultClient(resolvers, { - typeDefs, - cacheConfig: { - possibleTypes: { - LocalWorkItemWidget: ['LocalTitleWidget'], - }, - }, - }); - - defaultClient.cache.writeQuery({ - query: workItemQuery, - variables: { - id: 'gid://gitlab/WorkItem/1', - }, - data: { - workItem: { - __typename: 'WorkItem', - id: 'gid://gitlab/WorkItem/1', - // eslint-disable-next-line @gitlab/require-i18n-strings - title: 'Test Work Item', - workItemType: { - __typename: 'WorkItemType', - id: 'work-item-type-1', - name: 'Type', // eslint-disable-line @gitlab/require-i18n-strings - }, - widgets: { - __typename: 'LocalWorkItemWidgetConnection', - nodes: [], - }, - }, - }, - }); + const defaultClient = createDefaultClient(); return new VueApollo({ defaultClient, diff --git a/app/assets/javascripts/work_items/graphql/resolvers.js b/app/assets/javascripts/work_items/graphql/resolvers.js deleted file mode 100644 index fb74e27f840..00000000000 --- a/app/assets/javascripts/work_items/graphql/resolvers.js +++ /dev/null @@ -1,29 +0,0 @@ -import workItemQuery from './work_item.query.graphql'; - -export const resolvers = { - Mutation: { - localUpdateWorkItem(_, { input }, { cache }) { - const workItem = { - __typename: 'LocalWorkItem', - type: 'FEATURE', - id: input.id, - title: input.title, - widgets: { - __typename: 'LocalWorkItemWidgetConnection', - nodes: [], - }, - }; - - cache.writeQuery({ - query: workItemQuery, - variables: { id: input.id }, - data: { localWorkItem: workItem }, - }); - - return { - __typename: 'LocalUpdateWorkItemPayload', - workItem, - }; - }, - }, -}; diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql deleted file mode 100644 index 9b4811203f5..00000000000 --- a/app/assets/javascripts/work_items/graphql/typedefs.graphql +++ /dev/null @@ -1,56 +0,0 @@ -enum LocalWorkItemType { - FEATURE -} - -enum LocalWidgetType { - TITLE -} - -interface LocalWorkItemWidget { - type: LocalWidgetType! -} - -# Replicating Relay connection type for client schema -type LocalWorkItemWidgetEdge { - cursor: String! - node: LocalWorkItemWidget -} - -type LocalWorkItemWidgetConnection { - edges: [LocalWorkItemWidgetEdge] - nodes: [LocalWorkItemWidget] - pageInfo: PageInfo! -} - -type LocalWorkItem { - id: ID! - type: LocalWorkItemType! - title: String! - widgets: [LocalWorkItemWidgetConnection] -} - -input LocalCreateWorkItemInput { - title: String! -} - -input LocalUpdateWorkItemInput { - id: ID! - title: String -} - -type LocalCreateWorkItemPayload { - workItem: LocalWorkItem! -} - -type LocalUpdateWorkItemPayload { - workItem: LocalWorkItem! -} - -extend type Query { - localWorkItem(id: ID!): LocalWorkItem! -} - -extend type Mutation { - localCreateWorkItem(input: LocalCreateWorkItemInput!): LocalCreateWorkItemPayload! - localUpdateWorkItem(input: LocalUpdateWorkItemInput!): LocalUpdateWorkItemPayload! -} diff --git a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql deleted file mode 100644 index 154367dc0d8..00000000000 --- a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment WidgetBase on LocalWorkItemWidget { - type -} diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue index 04d76f12d00..a95da80ac95 100644 --- a/app/assets/javascripts/work_items/pages/create_work_item.vue +++ b/app/assets/javascripts/work_items/pages/create_work_item.vue @@ -128,10 +128,6 @@ export default { id, title, workItemType, - widgets: { - __typename: 'LocalWorkItemWidgetConnection', - nodes: [], - }, }, }, }); diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb index 0e9fdc60363..95deacdc5b9 100644 --- a/app/controllers/dashboard/application_controller.rb +++ b/app/controllers/dashboard/application_controller.rb @@ -11,6 +11,6 @@ class Dashboard::ApplicationController < ApplicationController private def projects - @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived + @projects ||= current_user.authorized_projects.sorted_by_updated_desc.non_archived end end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index b7428826c91..02f041637ba 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -268,7 +268,7 @@ class Projects::PipelinesController < Projects::ApplicationController project .all_pipelines .includes(builds: :tags, user: :status) - .find_by!(id: params[:id]) + .find(params[:id]) .present(current_user: current_user) end end diff --git a/app/helpers/routing/pseudonymization_helper.rb b/app/helpers/routing/pseudonymization_helper.rb index f1fafd563ce..3e5d4ee21c0 100644 --- a/app/helpers/routing/pseudonymization_helper.rb +++ b/app/helpers/routing/pseudonymization_helper.rb @@ -5,7 +5,11 @@ module Routing class MaskHelper QUERY_PARAMS_TO_NOT_MASK = %w[ scope + severity + sortBy + sortDesc state + tab ].freeze def initialize(request_object, group, project) diff --git a/app/models/project.rb b/app/models/project.rb index ab50d61b93f..ba2e4b14042 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -546,8 +546,8 @@ class Project < ApplicationRecord .or(arel_table[:storage_version].eq(nil))) end - # last_activity_at is throttled every minute, but last_repository_updated_at is updated with every push - scope :sorted_by_activity, -> { reorder(Arel.sql("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC")) } + scope :sorted_by_updated_asc, -> { reorder(self.arel_table['updated_at'].asc) } + scope :sorted_by_updated_desc, -> { reorder(self.arel_table['updated_at'].desc) } scope :sorted_by_stars_desc, -> { reorder(self.arel_table['star_count'].desc) } scope :sorted_by_stars_asc, -> { reorder(self.arel_table['star_count'].asc) } # Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name @@ -783,9 +783,9 @@ class Project < ApplicationRecord # pass a string to avoid AR adding the table name reorder('project_statistics.storage_size DESC, projects.id DESC') when 'latest_activity_desc' - reorder(self.arel_table['last_activity_at'].desc) + sorted_by_updated_desc when 'latest_activity_asc' - reorder(self.arel_table['last_activity_at'].asc) + sorted_by_updated_asc when 'stars_desc' sorted_by_stars_desc when 'stars_asc' @@ -1404,7 +1404,7 @@ class Project < ApplicationRecord end def last_activity_date - [last_activity_at, last_repository_updated_at, updated_at].compact.max + updated_at end def project_id diff --git a/app/services/concerns/deploy_token_methods.rb b/app/services/concerns/deploy_token_methods.rb index c792f10fb73..578be53f82c 100644 --- a/app/services/concerns/deploy_token_methods.rb +++ b/app/services/concerns/deploy_token_methods.rb @@ -11,7 +11,7 @@ module DeployTokenMethods end def destroy_deploy_token(entity, params) - deploy_token = entity.deploy_tokens.find_by_id!(params[:token_id]) + deploy_token = entity.deploy_tokens.find(params[:token_id]) deploy_token.destroy end diff --git a/doc/api/linked_epics.md b/doc/api/linked_epics.md index 2f46786251c..df302be0555 100644 --- a/doc/api/linked_epics.md +++ b/doc/api/linked_epics.md @@ -91,6 +91,8 @@ Example response: ## Create a related epic link +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352840) in GitLab 14.10. + Create a two-way relation between two epics. The user must be allowed to update both epics to succeed. @@ -205,3 +207,120 @@ Example response: "link_type": "relates_to" } ``` + +## Delete a related epic link + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352840) in GitLab 14.10. + +Delete a two-way relation between two epics. The user must be allowed to +update both epics to succeed. + +```plaintext +DELETE /groups/:id/epics/:epic_iid/related_epics/:related_epic_link_id +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +|--------------------------|----------------|-----------------------------|---------------------------------------| +| `epic_iid` | integer | **{check-circle}** Yes | Internal ID of a group's epic. | +| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. | +| `related_epic_link_id` | integer/string | **{check-circle}** Yes | Internal ID of a related epic link. | + +Example request: + +```shell +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/26/epics/1/related_epics/1" +``` + +Example response: + +```json +{ + "source_epic": { + "id": 21, + "iid": 1, + "color": "#1068bf", + "text_color": "#FFFFFF", + "group_id": 26, + "parent_id": null, + "parent_iid": null, + "title": "Aspernatur recusandae distinctio omnis et qui est iste.", + "description": "some description", + "confidential": false, + "author": { + "id": 15, + "username": "trina", + "name": "Theresia Robel", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/085e28df717e16484cbf6ceca75e9a93?s=80&d=identicon", + "web_url": "http://gitlab.example.com/trina" + }, + "start_date": null, + "end_date": null, + "due_date": null, + "state": "opened", + "web_url": "http://gitlab.example.com/groups/flightjs/-/epics/1", + "references": { + "short": "&1", + "relative": "&1", + "full": "flightjs&1" + }, + "created_at": "2022-01-31T15:10:44.988Z", + "updated_at": "2022-03-16T09:32:35.712Z", + "closed_at": null, + "labels": [], + "upvotes": 0, + "downvotes": 0, + "_links": { + "self": "http://gitlab.example.com/api/v4/groups/26/epics/1", + "epic_issues": "http://gitlab.example.com/api/v4/groups/26/epics/1/issues", + "group": "http://gitlab.example.com/api/v4/groups/26", + "parent": null + } + }, + "target_epic": { + "id": 25, + "iid": 5, + "color": "#1068bf", + "text_color": "#FFFFFF", + "group_id": 26, + "parent_id": null, + "parent_iid": null, + "title": "Aut assumenda id nihil distinctio fugiat vel numquam est.", + "description": "some description", + "confidential": false, + "author": { + "id": 3, + "username": "valerie", + "name": "Erika Wolf", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/9ef7666abb101418a4716a8ed4dded80?s=80&d=identicon", + "web_url": "http://gitlab.example.com/valerie" + }, + "start_date": null, + "end_date": null, + "due_date": null, + "state": "opened", + "web_url": "http://gitlab.example.com/groups/flightjs/-/epics/5", + "references": { + "short": "&5", + "relative": "&5", + "full": "flightjs&5" + }, + "created_at": "2022-01-31T15:10:45.080Z", + "updated_at": "2022-03-16T09:32:35.842Z", + "closed_at": null, + "labels": [], + "upvotes": 0, + "downvotes": 0, + "_links": { + "self": "http://gitlab.example.com/api/v4/groups/26/epics/5", + "epic_issues": "http://gitlab.example.com/api/v4/groups/26/epics/5/issues", + "group": "http://gitlab.example.com/api/v4/groups/26", + "parent": null + } + }, + "link_type": "relates_to" +} +``` diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index fe0c4c13ba2..09306dfc2a7 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -404,7 +404,7 @@ click_link _('UI testing docs') fill_in _('Search projects'), with: 'gitlab' # fill in text input with text -select _('Last updated'), from: 'Sort by' # select an option from a select input +select _('Updated date'), from: 'Sort by' # select an option from a select input check _('Checkbox label') uncheck _('Checkbox label') @@ -465,8 +465,8 @@ expect(page).to have_checked_field _('Checkbox label') expect(page).to have_unchecked_field _('Radio input label') expect(page).to have_select _('Sort by') -expect(page).to have_select _('Sort by'), selected: 'Last updated' # assert the option is selected -expect(page).to have_select _('Sort by'), options: ['Last updated', 'Created date', 'Due date'] # assert an exact list of options +expect(page).to have_select _('Sort by'), selected: 'Updated date' # assert the option is selected +expect(page).to have_select _('Sort by'), options: ['Updated date', 'Created date', 'Due date'] # assert an exact list of options expect(page).to have_select _('Sort by'), with_options: ['Created date', 'Due date'] # assert a partial list of options expect(page).to have_text _('Some paragraph text.') diff --git a/doc/integration/jira/issues.md b/doc/integration/jira/issues.md index e24862242e1..28998851697 100644 --- a/doc/integration/jira/issues.md +++ b/doc/integration/jira/issues.md @@ -106,7 +106,7 @@ sorts by **Created date** by default, with the newest issues listed at the top: ![Jira issues integration enabled](img/open_jira_issues_list_v14_6.png) -- To display the most recently updated issues first, select **Last updated**. +- To display the most recently updated issues first, select **Updated date**. - You can [search and filter](#search-and-filter-the-issues-list) the issues list. - In GitLab [versions 13.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/299832), you can select an issue from the list to view it in GitLab: diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md index 08fb756e79f..f57672d3d36 100644 --- a/doc/user/admin_area/index.md +++ b/doc/user/admin_area/index.md @@ -79,28 +79,29 @@ To access the Projects page: By default, all projects are listed, in reverse order of when they were last updated. For each project, the following information is listed: -- Name. -- Namespace. -- Description. -- Size, updated every 15 minutes at most. +- Name +- Namespace +- Description +- Size, updated every 15 minutes at most Projects can be edited or deleted. The list of projects can be sorted by: -- Name. -- Last created. -- Oldest created. -- Last updated. -- Oldest updated. -- Owner. +- Updated date +- Last created +- Name +- Most stars +- Oldest created +- Oldest updated +- Largest repository A user can choose to hide or show archived projects in the list. In the **Filter by name** field, type the project name you want to find, and GitLab filters them as you type. -Select from the **Namespace** dropdown to filter only projects in that namespace. +To filter only projects in that namespace, select from the **Namespace** dropdown list. You can combine the filter options. For example, to list only public projects with `score` in their name: diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md index 9311ef590df..95a7e9387e8 100644 --- a/doc/user/project/issues/sorting_issue_lists.md +++ b/doc/user/project/issues/sorting_issue_lists.md @@ -6,20 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Sorting and ordering issue lists **(FREE)** -You can sort a list of issues several ways, including by: - -- [Blocking issues](#sorting-by-blocking-issues) -- [Created date](#sorting-by-created-date) -- [Due date](#sorting-by-due-date) -- [Label priority](#sorting-by-label-priority) -- [Last updated](#sorting-by-last-updated) -- [Manual sorting](#manual-sorting) -- [Milestone due date](#sorting-by-milestone-due-date) -- [Popularity](#sorting-by-popularity) -- [Priority](#sorting-by-priority) -- [Title](#sorting-by-title) -- [Weight](#sorting-by-weight) - +You can sort a list of issues several ways. The available sorting options can change based on the context of the list. ## Sorting by blocking issues **(PREMIUM)** @@ -51,10 +38,10 @@ For more information, see [issue 14523](https://gitlab.com/gitlab-org/gitlab/-/i To learn how to change label priority, see [Label priority](../labels.md#set-label-priority). -## Sorting by last updated +## Sorting by updated date -When you sort by **Last updated**, the issue list changes to sort by the time of a last -update. Issues changed the most recently are first. +When you sort by **Updated date**, the issue list changes to sort by the time of a last +update. Issues changed the most recently are shown first. ## Manual sorting diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md index 6abe9c08d28..8b80c494e2f 100644 --- a/doc/user/project/requirements/index.md +++ b/doc/user/project/requirements/index.md @@ -127,7 +127,7 @@ To search for a requirement: You can also sort the requirements list by: - Created date -- Last updated +- Updated date ## Allow requirements to be satisfied from a CI job diff --git a/doc/user/search/img/sort_projects.png b/doc/user/search/img/sort_projects.png deleted file mode 100644 index 9bf2770b299dbadd9c5f69976de6c7df5fa7329b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59495 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 diff --git a/doc/user/search/index.md b/doc/user/search/index.md index 44327af380e..21f35e76418 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -207,10 +207,14 @@ You can also look for the projects you [starred](../project/working_with_project You can **Explore** all public and internal projects available in GitLab.com, from which you can filter by visibility, through **Trending**, best rated with **Most stars**, or **All** of them. -You can also sort them by **Name**, **Last created**, **Oldest created**, **Last updated**, -**Oldest updated**, **Owner**, and choose to hide or show **archived projects**: +You can also sort them by: -![sort projects](img/sort_projects.png) +- Name +- Created date +- Updated date +- Owner + +You can also choose to hide or show archived projects. ## Groups @@ -221,7 +225,7 @@ On the field **Filter by name**, type the group name you want to find, and GitLa filters them for you as you type. You can also **Explore** all public and internal groups available in GitLab.com, -and sort them by **Last created**, **Oldest created**, **Last updated**, or **Oldest updated**. +and sort them by **Name**, **Last created**, **Oldest created**, or **Updated date**. ## Issue boards diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index aa122c13e0c..496532a15b2 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -200,7 +200,7 @@ module API get ":id/user_agent_detail" do authenticated_as_admin! - snippet = Snippet.find_by_id!(params[:id]) + snippet = Snippet.find(params[:id]) break not_found!('UserAgentDetail') unless snippet.user_agent_detail diff --git a/spec/finders/concerns/finder_methods_spec.rb b/spec/finders/concerns/finder_methods_spec.rb index 195449d70c3..98d6ca8da3b 100644 --- a/spec/finders/concerns/finder_methods_spec.rb +++ b/spec/finders/concerns/finder_methods_spec.rb @@ -30,6 +30,7 @@ RSpec.describe FinderMethods do authorized_project.add_developer(user) end + # rubocop:disable Rails/FindById describe '#find_by!' do it 'returns the project if the user has access' do expect(finder.find_by!(id: authorized_project.id)).to eq(authorized_project) @@ -53,6 +54,7 @@ RSpec.describe FinderMethods do finder.find_by!(id: authorized_project.id) end end + # rubocop:enable Rails/FindById describe '#find' do it 'returns the project if the user has access' do diff --git a/spec/finders/concerns/finder_with_cross_project_access_spec.rb b/spec/finders/concerns/finder_with_cross_project_access_spec.rb index 116b523bd99..0798528c200 100644 --- a/spec/finders/concerns/finder_with_cross_project_access_spec.rb +++ b/spec/finders/concerns/finder_with_cross_project_access_spec.rb @@ -93,11 +93,11 @@ RSpec.describe FinderWithCrossProjectAccess do it 'checks the accessibility of the subject directly' do expect_access_check_on_result - finder.find_by!(id: result.id) + finder.find(result.id) end it 're-enables the check after the find failed' do - finder.find_by!(id: non_existing_record_id) rescue ActiveRecord::RecordNotFound + finder.find(non_existing_record_id) rescue ActiveRecord::RecordNotFound expect(finder.instance_variable_get(:@should_skip_cross_project_check)) .to eq(false) diff --git a/spec/frontend/work_items/components/work_item_title_spec.js b/spec/frontend/work_items/components/work_item_title_spec.js index af4692857b3..9b1ef2d14e4 100644 --- a/spec/frontend/work_items/components/work_item_title_spec.js +++ b/spec/frontend/work_items/components/work_item_title_spec.js @@ -22,13 +22,14 @@ describe('WorkItemTitle component', () => { const findItemTitle = () => wrapper.findComponent(ItemTitle); const createComponent = ({ loading = false, mutationHandler = mutationSuccessHandler } = {}) => { + const { id, title, workItemType } = workItemQueryResponse.data.workItem; wrapper = shallowMount(WorkItemTitle, { apolloProvider: createMockApollo([[updateWorkItemMutation, mutationHandler]]), propsData: { loading, - workItemId: workItemQueryResponse.workItem.id, - workItemTitle: workItemQueryResponse.workItem.title, - workItemType: workItemQueryResponse.workItem.workItemType.name, + workItemId: id, + workItemTitle: title, + workItemType: workItemType.name, }, }); }; @@ -61,7 +62,7 @@ describe('WorkItemTitle component', () => { }); it('renders title', () => { - expect(findItemTitle().props('title')).toBe(workItemQueryResponse.workItem.title); + expect(findItemTitle().props('title')).toBe(workItemQueryResponse.data.workItem.title); }); }); @@ -73,13 +74,18 @@ describe('WorkItemTitle component', () => { findItemTitle().vm.$emit('title-changed', title); - expect(mutationSuccessHandler).toHaveBeenCalledWith({ input: { id: '1', title } }); + expect(mutationSuccessHandler).toHaveBeenCalledWith({ + input: { + id: workItemQueryResponse.data.workItem.id, + title, + }, + }); }); it('does not call a mutation when the title has not changed', () => { createComponent(); - findItemTitle().vm.$emit('title-changed', workItemQueryResponse.workItem.title); + findItemTitle().vm.$emit('title-changed', workItemQueryResponse.data.workItem.title); expect(mutationSuccessHandler).not.toHaveBeenCalled(); }); diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index b6d4a91ec32..2ee0dd14359 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -1,22 +1,14 @@ export const workItemQueryResponse = { - workItem: { - __typename: 'WorkItem', - id: '1', - title: 'Test', - workItemType: { - __typename: 'WorkItemType', - id: 'work-item-type-1', - name: 'Task', - }, - widgets: { - __typename: 'LocalWorkItemWidgetConnection', - nodes: [ - { - __typename: 'LocalTitleWidget', - type: 'TITLE', - contentText: 'Test', - }, - ], + data: { + workItem: { + __typename: 'WorkItem', + id: 'gid://gitlab/WorkItem/1', + title: 'Test', + workItemType: { + __typename: 'WorkItemType', + id: 'gid://gitlab/WorkItems::Type/5', + name: 'Task', + }, }, }, }; @@ -24,27 +16,16 @@ export const workItemQueryResponse = { export const updateWorkItemMutationResponse = { data: { workItemUpdate: { - __typename: 'LocalUpdateWorkItemPayload', + __typename: 'WorkItemUpdatePayload', workItem: { - __typename: 'LocalWorkItem', - id: '1', + __typename: 'WorkItem', + id: 'gid://gitlab/WorkItem/1', title: 'Updated title', workItemType: { __typename: 'WorkItemType', - id: 'work-item-type-1', + id: 'gid://gitlab/WorkItems::Type/5', name: 'Task', }, - widgets: { - __typename: 'LocalWorkItemWidgetConnection', - nodes: [ - { - __typename: 'LocalTitleWidget', - type: 'TITLE', - enabled: true, - contentText: 'Updated title', - }, - ], - }, }, }, }, @@ -53,11 +34,11 @@ export const updateWorkItemMutationResponse = { export const projectWorkItemTypesQueryResponse = { data: { workspace: { - id: '1', + id: 'gid://gitlab/WorkItem/1', workItemTypes: { nodes: [ - { id: 'work-item-1', name: 'Issue' }, - { id: 'work-item-2', name: 'Incident' }, + { id: 'gid://gitlab/WorkItems::Type/1', name: 'Issue' }, + { id: 'gid://gitlab/WorkItems::Type/2', name: 'Incident' }, ], }, }, @@ -70,11 +51,11 @@ export const createWorkItemMutationResponse = { __typename: 'WorkItemCreatePayload', workItem: { __typename: 'WorkItem', - id: '1', + id: 'gid://gitlab/WorkItem/1', title: 'Updated title', workItemType: { __typename: 'WorkItemType', - id: 'work-item-type-1', + id: 'gid://gitlab/WorkItems::Type/5', name: 'Task', }, }, diff --git a/spec/frontend/work_items/pages/create_work_item_spec.js b/spec/frontend/work_items/pages/create_work_item_spec.js index 022c23edd0d..fb1f1d56356 100644 --- a/spec/frontend/work_items/pages/create_work_item_spec.js +++ b/spec/frontend/work_items/pages/create_work_item_spec.js @@ -6,7 +6,6 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import CreateWorkItem from '~/work_items/pages/create_work_item.vue'; import ItemTitle from '~/work_items/components/item_title.vue'; -import { resolvers } from '~/work_items/graphql/resolvers'; import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql'; import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutation.graphql'; import createWorkItemFromTaskMutation from '~/work_items/graphql/create_work_item_from_task.mutation.graphql'; @@ -46,14 +45,11 @@ describe('Create work item component', () => { queryHandler = querySuccessHandler, mutationHandler = createWorkItemSuccessHandler, } = {}) => { - fakeApollo = createMockApollo( - [ - [projectWorkItemTypesQuery, queryHandler], - [createWorkItemMutation, mutationHandler], - [createWorkItemFromTaskMutation, mutationHandler], - ], - resolvers, - ); + fakeApollo = createMockApollo([ + [projectWorkItemTypesQuery, queryHandler], + [createWorkItemMutation, mutationHandler], + [createWorkItemFromTaskMutation, mutationHandler], + ]); wrapper = shallowMount(CreateWorkItem, { apolloProvider: fakeApollo, data() { diff --git a/spec/frontend/work_items/pages/work_item_detail_spec.js b/spec/frontend/work_items/pages/work_item_detail_spec.js index 650be38bc04..1eb6c0145e7 100644 --- a/spec/frontend/work_items/pages/work_item_detail_spec.js +++ b/spec/frontend/work_items/pages/work_item_detail_spec.js @@ -16,14 +16,14 @@ describe('WorkItemDetail component', () => { Vue.use(VueApollo); - const successHandler = jest.fn().mockResolvedValue({ data: workItemQueryResponse }); + const successHandler = jest.fn().mockResolvedValue(workItemQueryResponse); const initialSubscriptionHandler = jest.fn().mockResolvedValue(workItemTitleSubscriptionResponse); const findAlert = () => wrapper.findComponent(GlAlert); const findWorkItemTitle = () => wrapper.findComponent(WorkItemTitle); const createComponent = ({ - workItemId = workItemQueryResponse.workItem.id, + workItemId = workItemQueryResponse.data.workItem.id, handler = successHandler, subscriptionHandler = initialSubscriptionHandler, } = {}) => { @@ -93,7 +93,7 @@ describe('WorkItemDetail component', () => { createComponent(); expect(initialSubscriptionHandler).toHaveBeenCalledWith({ - issuableId: workItemQueryResponse.workItem.id, + issuableId: workItemQueryResponse.data.workItem.id, }); }); }); diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js index 8c9054920a8..7e68c5e4f0e 100644 --- a/spec/frontend/work_items/router_spec.js +++ b/spec/frontend/work_items/router_spec.js @@ -37,7 +37,7 @@ describe('Work items router', () => { it('renders work item on `/1` route', async () => { await createComponent('/1'); - expect(wrapper.find(WorkItemsRoot).exists()).toBe(true); + expect(wrapper.findComponent(WorkItemsRoot).exists()).toBe(true); }); it('renders create work item page on `/new` route', async () => { diff --git a/spec/helpers/routing/pseudonymization_helper_spec.rb b/spec/helpers/routing/pseudonymization_helper_spec.rb index 1221917e6b7..cf716931fe2 100644 --- a/spec/helpers/routing/pseudonymization_helper_spec.rb +++ b/spec/helpers/routing/pseudonymization_helper_spec.rb @@ -180,7 +180,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do end context 'when some query params are not required to be masked' do - let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=all&state=masked_state" } + let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=all&state=masked_state&tab=2" } let(:request) do double(:Request, path_parameters: { @@ -189,11 +189,11 @@ RSpec.describe ::Routing::PseudonymizationHelper do }, protocol: 'http', host: 'localhost', - query_string: 'author_username=root&scope=all&state=opened') + query_string: 'author_username=root&scope=all&state=opened&tab=2') end before do - stub_const('Routing::PseudonymizationHelper::MaskHelper::QUERY_PARAMS_TO_NOT_MASK', %w[scope].freeze) + stub_const('Routing::PseudonymizationHelper::MaskHelper::QUERY_PARAMS_TO_NOT_MASK', %w[scope tab].freeze) allow(helper).to receive(:request).and_return(request) end diff --git a/spec/lib/gitlab/search_context/builder_spec.rb b/spec/lib/gitlab/search_context/builder_spec.rb index 079477115bb..a09115f3f21 100644 --- a/spec/lib/gitlab/search_context/builder_spec.rb +++ b/spec/lib/gitlab/search_context/builder_spec.rb @@ -43,7 +43,6 @@ RSpec.describe Gitlab::SearchContext::Builder, type: :controller do def be_search_context(project: nil, group: nil, snippets: [], ref: nil) group = project ? project.group : group snippets.compact! - ref = ref have_attributes( project: project, diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index fcd2ccf45f5..3bff45f80dd 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1191,29 +1191,8 @@ RSpec.describe Project, factory_default: :keep do end describe 'last_activity_date' do - it 'returns the creation date of the project\'s last event if present' do - new_event = create(:event, :closed, project: project, created_at: Time.current) - - project.reload - expect(project.last_activity_at.to_i).to eq(new_event.created_at.to_i) - end - - it 'returns the project\'s last update date if it has no events' do - expect(project.last_activity_date).to eq(project.updated_at) - end - - it 'returns the most recent timestamp' do - project.update!(updated_at: nil, - last_activity_at: timestamp, - last_repository_updated_at: timestamp - 1.hour) - - expect(project.last_activity_date).to be_like_time(timestamp) - - project.update!(updated_at: timestamp, - last_activity_at: timestamp - 1.hour, - last_repository_updated_at: nil) - - expect(project.last_activity_date).to be_like_time(timestamp) + it 'returns the project\'s last update date' do + expect(project.last_activity_date).to be_like_time(project.updated_at) end end end @@ -1690,15 +1669,27 @@ RSpec.describe Project, factory_default: :keep do end describe '.sort_by_attribute' do - it 'reorders the input relation by start count desc' do - project1 = create(:project, star_count: 2) - project2 = create(:project, star_count: 1) - project3 = create(:project) + let_it_be(:project1) { create(:project, star_count: 2, updated_at: 1.minute.ago) } + let_it_be(:project2) { create(:project, star_count: 1) } + let_it_be(:project3) { create(:project, updated_at: 2.minutes.ago) } + it 'reorders the input relation by start count desc' do projects = described_class.sort_by_attribute(:stars_desc) expect(projects).to eq([project1, project2, project3]) end + + it 'reorders the input relation by last activity desc' do + projects = described_class.sort_by_attribute(:latest_activity_desc) + + expect(projects).to eq([project2, project1, project3]) + end + + it 'reorders the input relation by last activity asc' do + projects = described_class.sort_by_attribute(:latest_activity_asc) + + expect(projects).to eq([project3, project1, project2]) + end end describe '.with_shared_runners' do