Commit e30c2a00 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 33517ed1 82253cc6
/* eslint-disable class-methods-use-this, no-new */
import $ from 'jquery';
import { property } from 'lodash';
import issuableEventHub from '~/issues_list/eventhub';
import LabelsSelect from '~/labels/labels_select';
import MilestoneSelect from '~/milestones/milestone_select';
......@@ -16,8 +14,6 @@ const SIDEBAR_COLLAPSED_CLASS = 'right-sidebar-collapsed issuable-bulk-update-si
export default class IssuableBulkUpdateSidebar {
constructor() {
this.vueIssuablesListFeature = property(['gon', 'features', 'vueIssuablesList'])(window);
this.initDomElements();
this.bindEvents();
this.initDropdowns();
......@@ -143,7 +139,7 @@ export default class IssuableBulkUpdateSidebar {
}
toggleCheckboxDisplay(show) {
this.$checkAllContainer.toggleClass(HIDDEN_CLASS, !show || this.vueIssuablesListFeature);
this.$checkAllContainer.toggleClass(HIDDEN_CLASS, !show);
this.$issueChecks.toggleClass(HIDDEN_CLASS, !show);
}
......
......@@ -20,7 +20,7 @@ const updateIssue = (url, issueList, { move_before_id, move_after_id }) =>
});
});
const initManualOrdering = (draggableSelector = 'li.issue') => {
const initManualOrdering = () => {
const issueList = document.querySelector('.manual-ordering');
if (!issueList || !(gon.current_user_id > 0)) {
......@@ -37,14 +37,14 @@ const initManualOrdering = (draggableSelector = 'li.issue') => {
group: {
name: 'issues',
},
draggable: draggableSelector,
draggable: 'li.issue',
onStart: () => {
sortableStart();
},
onUpdate: (event) => {
const el = event.item;
const url = el.getAttribute('url') || el.dataset.url;
const url = el.getAttribute('url');
const prev = el.previousElementSibling;
const next = el.nextElementSibling;
......
......@@ -9,62 +9,6 @@ import {
OPERATOR_IS_NOT,
} from '~/vue_shared/components/filtered_search_bar/constants';
// Maps sort order as it appears in the URL query to API `order_by` and `sort` params.
const PRIORITY = 'priority';
const ASC = 'asc';
const DESC = 'desc';
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
const DUE_DATE = 'due_date';
const MILESTONE_DUE = 'milestone_due';
const POPULARITY = 'popularity';
const WEIGHT = 'weight';
const LABEL_PRIORITY = 'label_priority';
const TITLE = 'title';
export const RELATIVE_POSITION = 'relative_position';
export const LOADING_LIST_ITEMS_LENGTH = 8;
export const PAGE_SIZE = 20;
export const PAGE_SIZE_MANUAL = 100;
export const sortOrderMap = {
priority: { order_by: PRIORITY, sort: ASC }, // asc and desc are flipped for some reason
created_date: { order_by: CREATED_AT, sort: DESC },
created_asc: { order_by: CREATED_AT, sort: ASC },
updated_desc: { order_by: UPDATED_AT, sort: DESC },
updated_asc: { order_by: UPDATED_AT, sort: ASC },
milestone_due_desc: { order_by: MILESTONE_DUE, sort: DESC },
milestone: { order_by: MILESTONE_DUE, sort: ASC },
due_date_desc: { order_by: DUE_DATE, sort: DESC },
due_date: { order_by: DUE_DATE, sort: ASC },
popularity: { order_by: POPULARITY, sort: DESC },
popularity_asc: { order_by: POPULARITY, sort: ASC },
label_priority: { order_by: LABEL_PRIORITY, sort: ASC }, // asc and desc are flipped
relative_position: { order_by: RELATIVE_POSITION, sort: ASC },
weight_desc: { order_by: WEIGHT, sort: DESC },
weight: { order_by: WEIGHT, sort: ASC },
title: { order_by: TITLE, sort: ASC },
title_desc: { order_by: TITLE, sort: DESC },
};
export const availableSortOptionsJira = [
{
id: 1,
title: __('Created date'),
sortDirection: {
descending: 'created_desc',
ascending: 'created_asc',
},
},
{
id: 2,
title: __('Last updated'),
sortDirection: {
descending: 'updated_desc',
ascending: 'updated_asc',
},
},
];
export const i18n = {
anonymousSearchingMessage: __('You must sign in to search for specific terms.'),
calendarLabel: __('Subscribe to calendar'),
......@@ -108,11 +52,13 @@ export const i18n = {
upvotes: __('Upvotes'),
};
export const JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY = 'jira-import-success-alert-hide-map';
export const MAX_LIST_SIZE = 10;
export const PAGE_SIZE = 20;
export const PAGE_SIZE_MANUAL = 100;
export const PARAM_DUE_DATE = 'due_date';
export const PARAM_SORT = 'sort';
export const PARAM_STATE = 'state';
export const RELATIVE_POSITION = 'relative_position';
export const defaultPageSizeParams = {
firstPageSize: PAGE_SIZE,
......@@ -183,8 +129,6 @@ export const urlSortParams = {
[TITLE_DESC]: 'title_desc',
};
export const MAX_LIST_SIZE = 10;
export const API_PARAM = 'apiParam';
export const URL_PARAM = 'urlParam';
export const NORMAL_FILTER = 'normalFilter';
......
......@@ -4,8 +4,7 @@ import VueApollo from 'vue-apollo';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
import IssuesListApp from 'ee_else_ce/issues_list/components/issues_list_app.vue';
import createDefaultClient from '~/lib/graphql';
import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
import IssuablesListApp from './components/issuables_list_app.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import JiraIssuesImportStatusRoot from './components/jira_issues_import_status_app.vue';
export function mountJiraIssuesListApp() {
......@@ -45,35 +44,6 @@ export function mountJiraIssuesListApp() {
});
}
export function mountIssuablesListApp() {
if (!gon.features?.vueIssuablesList) {
return;
}
document.querySelectorAll('.js-issuables-list').forEach((el) => {
const { canBulkEdit, emptyStateMeta = {}, scopedLabelsAvailable, ...data } = el.dataset;
return new Vue({
el,
provide: {
scopedLabelsAvailable: parseBoolean(scopedLabelsAvailable),
},
render(createElement) {
return createElement(IssuablesListApp, {
props: {
...data,
emptyStateMeta:
Object.keys(emptyStateMeta).length !== 0
? convertObjectPropsToCamelCase(JSON.parse(emptyStateMeta))
: {},
canBulkEdit: Boolean(canBulkEdit),
},
});
},
});
});
}
export function mountIssuesListApp() {
const el = document.querySelector('.js-issues-list');
......
import { __, s__ } from '~/locale';
/**
* Generates empty state messages for Service Desk issues list.
*
* @param {emptyStateMeta} emptyStateMeta - Meta data used to generate empty state messages
* @returns {Object} Object containing empty state messages generated using the meta data.
*/
export function generateMessages(emptyStateMeta) {
const {
svgPath,
serviceDeskHelpPage,
serviceDeskAddress,
editProjectPage,
incomingEmailHelpPage,
} = emptyStateMeta;
const serviceDeskSupportedTitle = s__(
'ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab',
);
const serviceDeskSupportedMessage = s__(
'ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation.',
);
const commonDescription = `
<span>${serviceDeskSupportedMessage}</span>
<a href="${serviceDeskHelpPage}">${__('Learn more.')}</a>`;
return {
serviceDeskEnabledAndCanEditProjectSettings: {
title: serviceDeskSupportedTitle,
svgPath,
description: `<p>${s__('ServiceDesk|Your users can send emails to this address:')}
<code>${serviceDeskAddress}</code>
</p>
${commonDescription}`,
},
serviceDeskEnabledAndCannotEditProjectSettings: {
title: serviceDeskSupportedTitle,
svgPath,
description: commonDescription,
},
serviceDeskDisabledAndCanEditProjectSettings: {
title: serviceDeskSupportedTitle,
svgPath,
description: commonDescription,
primaryLink: editProjectPage,
primaryText: s__('ServiceDesk|Enable Service Desk'),
},
serviceDeskDisabledAndCannotEditProjectSettings: {
title: serviceDeskSupportedTitle,
svgPath,
description: commonDescription,
},
serviceDeskIsNotSupported: {
title: s__('ServiceDesk|Service Desk is not supported'),
svgPath,
description: s__(
'ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email.',
),
primaryLink: incomingEmailHelpPage,
primaryText: __('Learn more.'),
},
serviceDeskIsNotEnabled: {
title: s__('ServiceDesk|Service Desk is not enabled'),
svgPath,
description: s__(
'ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator.',
),
},
};
}
/**
* Returns the attributes used for gl-empty-state in the Service Desk issues list.
*
* @param {Object} emptyStateMeta - Meta data used to generate empty state messages
* @returns {Object}
*/
export function emptyStateHelper(emptyStateMeta) {
const messages = generateMessages(emptyStateMeta);
const { isServiceDeskSupported, canEditProjectSettings, isServiceDeskEnabled } = emptyStateMeta;
if (isServiceDeskSupported) {
if (isServiceDeskEnabled && canEditProjectSettings) {
return messages.serviceDeskEnabledAndCanEditProjectSettings;
}
if (isServiceDeskEnabled && !canEditProjectSettings) {
return messages.serviceDeskEnabledAndCannotEditProjectSettings;
}
// !isServiceDeskEnabled && canEditProjectSettings
if (canEditProjectSettings) {
return messages.serviceDeskDisabledAndCanEditProjectSettings;
}
// !isServiceDeskEnabled && !canEditProjectSettings
return messages.serviceDeskDisabledAndCannotEditProjectSettings;
}
// !serviceDeskSupported && canEditProjectSettings
if (canEditProjectSettings) {
return messages.serviceDeskIsNotSupported;
}
// !serviceDeskSupported && !canEditProjectSettings
return messages.serviceDeskIsNotEnabled;
}
import { __ } from '~/locale';
export const JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY = 'jira-import-success-alert-hide-map';
export const debounceWait = 500;
export const dropdownLabel = __(
......
import { last } from 'lodash';
import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from './constants';
export const IMPORT_STATE = {
FAILED: 'failed',
......
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import { initBulkUpdateSidebar } from '~/issuable/bulk_update_sidebar';
import { mountIssuablesListApp, mountIssuesListApp } from '~/issues_list';
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';
......@@ -23,8 +23,4 @@ if (gon.features?.vueIssuesList) {
});
projectSelect();
initManualOrdering();
if (gon.features?.vueIssuablesList) {
mountIssuablesListApp();
}
}
......@@ -2,7 +2,7 @@ import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
import { initBulkUpdateSidebar, initIssueStatusSelect } from '~/issuable/bulk_update_sidebar';
import { mountIssuablesListApp, mountIssuesListApp, mountJiraIssuesListApp } from '~/issues_list';
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';
......@@ -27,10 +27,6 @@ if (gon.features?.vueIssuesList) {
initCsvImportExportButtons();
initIssuableByEmail();
initManualOrdering();
if (gon.features?.vueIssuablesList) {
mountIssuablesListApp();
}
}
new ShortcutsNavigation(); // eslint-disable-line no-new
......
import { initFilteredSearchServiceDesk } from '~/issues';
import { mountIssuablesListApp } from '~/issues_list';
initFilteredSearchServiceDesk();
if (gon.features?.vueIssuablesList) {
mountIssuablesListApp();
}
......@@ -32,7 +32,6 @@ class GroupsController < Groups::ApplicationController
before_action :user_actions, only: [:show]
before_action do
push_frontend_feature_flag(:vue_issuables_list, @group)
push_frontend_feature_flag(:vue_issues_list, @group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, @group, default_enabled: :yaml)
end
......
......@@ -43,7 +43,6 @@ class Projects::IssuesController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:tribute_autocomplete, @project)
push_frontend_feature_flag(:vue_issuables_list, project)
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
push_frontend_feature_flag(:vue_issues_list, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
......
......@@ -168,21 +168,6 @@ module IssuesHelper
issue.moved_from.project.service_desk_enabled? && !issue.project.service_desk_enabled?
end
def use_startup_call?
request.query_parameters.empty? && @sort == 'created_date'
end
def startup_call_params
{
state: 'opened',
with_labels_details: 'true',
page: 1,
per_page: 20,
order_by: 'created_at',
sort: 'desc'
}
end
def issue_header_actions_data(project, issuable, current_user)
new_issuable_params = { issue: { description: _('Related to #%{issue_id}.') % { issue_id: issuable.iid } + "\n\n" } }
if issuable.incident?
......
# frozen_string_literal: true
module Projects::Issues::ServiceDeskHelper
def service_desk_meta(project)
empty_state_meta = {
is_service_desk_supported: Gitlab::ServiceDesk.supported?,
is_service_desk_enabled: project.service_desk_enabled?,
can_edit_project_settings: can?(current_user, :admin_project, project)
}
if Gitlab::ServiceDesk.supported?
empty_state_meta.merge(supported_meta(project))
else
empty_state_meta.merge(unsupported_meta(project))
end
end
private
def supported_meta(project)
{
service_desk_address: project.service_desk_address,
service_desk_help_page: help_page_path('user/project/service_desk'),
edit_project_page: edit_project_path(project),
svg_path: image_path('illustrations/service_desk_empty.svg')
}
end
def unsupported_meta(project)
{
incoming_email_help_page: help_page_path('administration/incoming_email', anchor: 'set-it-up'),
svg_path: image_path('illustrations/service-desk-setup.svg')
}
end
end
......@@ -136,13 +136,18 @@ module Ci
.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
}
# deprecated
scope :belonging_to_parent_group_of_project, -> (project_id) {
raise ArgumentError, "only 1 project_id allowed for performance reasons" unless project_id.is_a?(Integer)
project_groups = ::Group.joins(:projects).where(projects: { id: project_id })
joins(:groups)
.where(namespaces: { id: project_groups.self_and_ancestors.as_ids })
.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
if Feature.enabled?(:ci_decompose_belonging_to_parent_group_of_project_query, default_enabled: :yaml)
belonging_to_group(project_groups.self_and_ancestors.pluck(:id))
else
joins(:groups)
.where(namespaces: { id: project_groups.self_and_ancestors.as_ids })
.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
end
}
# deprecated
......
......@@ -25,14 +25,4 @@
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
- if Feature.enabled?(:vue_issuables_list, @group) && @issues.to_a.any?
- if use_startup_call?
- add_page_startup_api_call(api_v4_groups_issues_path(id: @group.id, params: startup_call_params))
.js-issuables-list{ data: { endpoint: expose_url(api_v4_groups_issues_path(id: @group.id)),
'can-bulk-edit': @can_bulk_update.to_json,
'empty-state-meta': { svg_path: image_path('illustrations/issues.svg') },
'sort-key': @sort,
type: 'issues',
'scoped-labels-available': scoped_labels_available?(@group).to_json } }
- else
= render 'shared/issues', project_select_button: true
= render 'shared/issues', project_select_button: true
-# DANGER: Any changes to this file need to be reflected in issuables_list/components/issuable.vue!
%li{ id: dom_id(issue), class: issue_css_classes(issue), url: issue_path(issue), data: { labels: issue.label_ids, id: issue.id, qa_selector: 'issue_container', qa_issue_title: issue.title } }
.issuable-info-container
- if @can_bulk_update
......
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
= render 'shared/alerts/positioning_disabled' if @sort == 'relative_position'
- if Feature.enabled?(:vue_issuables_list, @project) && !is_project_overview
- data_endpoint = local_assigns.fetch(:data_endpoint, expose_path(api_v4_projects_issues_path(id: @project.id)))
- default_empty_state_meta = { create_issue_path: new_project_issue_path(@project), svg_path: image_path('illustrations/issues.svg') }
- data_empty_state_meta = local_assigns.fetch(:data_empty_state_meta, default_empty_state_meta)
- type = local_assigns.fetch(:type, 'issues')
- if type == 'issues' && use_startup_call?
- add_page_startup_api_call(api_v4_projects_issues_path(id: @project.id, params: startup_call_params))
.js-issuables-list{ data: { endpoint: data_endpoint,
'empty-state-meta': data_empty_state_meta.to_json,
'can-bulk-edit': @can_bulk_update.to_json,
'sort-key': @sort,
type: type,
'scoped-labels-available': scoped_labels_available?(@project).to_json } }
- else
- empty_state_path = local_assigns.fetch(:empty_state_path, 'shared/empty_states/issues')
%ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class }
= render partial: "projects/issues/issue", collection: @issues
- if @issues.blank?
= render empty_state_path
%ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class }
= render partial: "projects/issues/issue", collection: @issues
- if @issues.blank?
- empty_state_path = local_assigns.fetch(:empty_state_path, 'shared/empty_states/issues')
= render empty_state_path
- if @issues.present?
= paginate_collection @issues, total_pages: @total_pages
- if @issues.present?
= paginate_collection @issues, total_pages: @total_pages
......@@ -27,7 +27,11 @@
.svg-content
= render 'shared/empty_states/icons/service_desk_setup.svg'
.text-content
%h4= s_('ServiceDesk|Service Desk is enabled but not yet active')
%p
= s_("ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email.")
= link_to _('Learn more.'), help_page_path('administration/incoming_email', anchor: 'set-it-up')
- if can_edit_project_settings
%h4= s_('ServiceDesk|Service Desk is not supported')
%p
= s_("ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email.")
= link_to _('Learn more.'), help_page_path('administration/incoming_email', anchor: 'set-it-up')
- else
%h4= s_('ServiceDesk|Service Desk is not enabled')
%p= s_("ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator.")
......@@ -7,9 +7,7 @@
- support_bot_attrs = { service_desk_enabled: @project.service_desk_enabled?, **UserSerializer.new.represent(User.support_bot) }.to_json
- data_endpoint = "#{expose_path(api_v4_projects_issues_path(id: @project.id))}?author_username=#{User.support_bot.username}"
%div{ class: "js-service-desk-issues service-desk-issues", data: { support_bot: support_bot_attrs, service_desk_meta: service_desk_meta(@project) } }
.js-service-desk-issues.service-desk-issues{ data: { support_bot: support_bot_attrs } }
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls.d-block.d-sm-none
......@@ -20,12 +18,5 @@
- if Gitlab::ServiceDesk.supported?
= render 'service_desk_info_content'
-# TODO Remove empty_state_path once vue_issuables_list FF is removed.
-# https://gitlab.com/gitlab-org/gitlab/-/issues/235652
-# `empty_state_path` is used to render the empty state in the HAML version of issuables list.
.issues-holder
= render 'projects/issues/issues',
empty_state_path: 'service_desk_empty_state',
data_endpoint: data_endpoint,
data_empty_state_meta: service_desk_meta(@project),
type: 'service_desk'
= render 'projects/issues/issues', empty_state_path: 'service_desk_empty_state'
---
name: vue_issuables_list
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15091
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/208093
milestone: '12.5'
name: ci_decompose_belonging_to_parent_group_of_project_query
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76454
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348560
milestone: '14.7'
type: development
group: group::project management
group: group::pipeline execution
default_enabled: false
......@@ -9,8 +9,6 @@ RSpec.describe 'Blocking issues count' do
let_it_be(:issue2) { build(:issue, project: project, created_at: 3.days.ago, title: 'blocks two issues') }
before do
stub_feature_flags(vue_issuables_list: false)
visit project_issues_path(project)
end
......
......@@ -147,14 +147,6 @@ RSpec.describe 'Filter issues by iteration', :js do
it_behaves_like 'filters by iteration'
it_behaves_like 'shows iterations when using iteration token'
context 'when vue_issuables_list is disabled' do
before do
stub_feature_flags(vue_issuables_list: false)
end
it_behaves_like 'filters by iteration'
end
end
context 'group issues list' do
......@@ -164,14 +156,6 @@ RSpec.describe 'Filter issues by iteration', :js do
it_behaves_like 'filters by iteration'
it_behaves_like 'shows iterations when using iteration token'
context 'when vue_issuables_list is disabled' do
before do
stub_feature_flags(vue_issuables_list: false)
end
it_behaves_like 'filters by iteration'
end
end
context 'project board' do
......
......@@ -21,7 +21,6 @@ RSpec.describe 'Filter issues by epic', :js do
before do
stub_licensed_features(epics: true)
stub_feature_flags(vue_issuables_list: false)
group.add_maintainer(user)
sign_in(user)
......
......@@ -14,14 +14,6 @@ RSpec.describe 'Filter issues weight', :js do
let(:filter_dropdown) { find("#js-dropdown-weight .filter-dropdown") }
shared_examples 'filters by negated weight' do
it 'excludes issues with specified weight' do
input_filtered_search(search)
expect_issues_list_count(1)
end
end
def expect_issues_list_count(open_count, closed_count = 0)
all_count = open_count + closed_count
......@@ -57,14 +49,10 @@ RSpec.describe 'Filter issues weight', :js do
describe 'negated weight only' do
let(:search) { 'weight:!=2' }
it_behaves_like 'filters by negated weight'
context 'when vue_issuables_list is disabled' do
before do
stub_feature_flags(vue_issuables_list: false)
end
it 'excludes issues with specified weight' do
input_filtered_search(search)
it_behaves_like 'filters by negated weight'
expect_issues_list_count(1)
end
end
......
......@@ -10,7 +10,6 @@ RSpec.describe 'User views issues page', :js do
let_it_be(:issue3) { create(:issue, project: project, health_status: 'at_risk') }
before do
stub_feature_flags(vue_issuables_list: false)
sign_in(user)
visit project_issues_path(project)
end
......
......@@ -841,9 +841,6 @@ msgstr ""
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
......@@ -31098,9 +31095,6 @@ msgstr ""
msgid "Search GitLab"
msgstr ""
msgid "Search Jira issues"
msgstr ""
msgid "Search a group"
msgstr ""
......@@ -32419,18 +32413,12 @@ msgstr ""
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
msgid "ServiceDesk|Service Desk is enabled but not yet active"
msgstr ""
msgid "ServiceDesk|Service Desk is not enabled"
msgstr ""
msgid "ServiceDesk|Service Desk is not supported"
msgstr ""
msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""
......@@ -41925,12 +41913,6 @@ msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
msgid "created %{timeAgoString} by %{user}"
msgstr ""
msgid "created %{timeAgoString} by %{user} in Jira"
msgstr ""
msgid "created %{timeAgo}"
msgstr ""
......
......@@ -9,8 +9,6 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
let_it_be(:support_bot) { User.support_bot }
before do
stub_feature_flags(vue_issuables_list: true)
# The following two conditions equate to Gitlab::ServiceDesk.supported == true
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(true)
......
......@@ -8,8 +8,6 @@ RSpec.describe 'New issue breadcrumb' do
let(:user) { project.creator }
before do
stub_feature_flags(vue_issuables_list: false)
sign_in(user)
visit(new_project_issue_path(project))
end
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Issuables list component with empty issues response with all state should display a catch-all if there are no issues to show 1`] = `
<gl-empty-state-stub
svgpath="/emptySvg"
title="There are no issues to show"
/>
`;
exports[`Issuables list component with empty issues response with closed state should display a message "There are no closed issues" if there are no closed issues 1`] = `"There are no closed issues"`;
exports[`Issuables list component with empty issues response with empty query should display the message "There are no open issues" 1`] = `"There are no open issues"`;
exports[`Issuables list component with empty issues response with query in window location should display "Sorry, your filter produced no results" if filters are too specific 1`] = `"Sorry, your filter produced no results"`;
This diff is collapsed.
export const simpleIssue = {
id: 442,
iid: 31,
title: 'Dismiss Cipher with no integrity',
state: 'opened',
created_at: '2019-08-26T19:06:32.667Z',
updated_at: '2019-08-28T19:53:58.314Z',
labels: [],
milestone: null,
assignees: [],
author: {
id: 3,
name: 'Elnora Bernhard',
username: 'treva.lesch',
state: 'active',
avatar_url: 'https://www.gravatar.com/avatar/a8c0d9c2882406cf2a9b71494625a796?s=80&d=identicon',
web_url: 'http://localhost:3001/treva.lesch',
},
assignee: null,
user_notes_count: 0,
blocking_issues_count: 0,
merge_requests_count: 0,
upvotes: 0,
downvotes: 0,
due_date: null,
confidential: false,
web_url: 'http://localhost:3001/h5bp/html5-boilerplate/issues/31',
has_tasks: false,
weight: null,
references: {
relative: 'html-boilerplate#45',
},
health_status: 'on_track',
};
export const testLabels = [
{
id: 1,
name: 'Tanuki',
description: 'A cute animal',
color: '#ff0000',
text_color: '#ffffff',
},
{
id: 2,
name: 'Octocat',
description: 'A grotesque mish-mash of whiskers and tentacles',
color: '#333333',
text_color: '#000000',
},
{
id: 3,
name: 'scoped::label',
description: 'A scoped label',
color: '#00ff00',
text_color: '#ffffff',
},
];
export const testAssignees = [
{
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
web_url: 'http://localhost:3001/root',
},
{
id: 22,
name: 'User 0',
username: 'user0',
state: 'active',
avatar_url: 'https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon',
web_url: 'http://localhost:3001/user0',
},
];
import { emptyStateHelper, generateMessages } from '~/issues_list/service_desk_helper';
describe('service desk helper', () => {
const emptyStateMessages = generateMessages({});
// Note: isServiceDeskEnabled must not be true when isServiceDeskSupported is false (it's an invalid case).
describe.each`
isServiceDeskSupported | isServiceDeskEnabled | canEditProjectSettings | expectedMessage
${true} | ${true} | ${true} | ${'serviceDeskEnabledAndCanEditProjectSettings'}
${true} | ${true} | ${false} | ${'serviceDeskEnabledAndCannotEditProjectSettings'}
${true} | ${false} | ${true} | ${'serviceDeskDisabledAndCanEditProjectSettings'}
${true} | ${false} | ${false} | ${'serviceDeskDisabledAndCannotEditProjectSettings'}
${false} | ${false} | ${true} | ${'serviceDeskIsNotSupported'}
${false} | ${false} | ${false} | ${'serviceDeskIsNotEnabled'}
`(
'isServiceDeskSupported = $isServiceDeskSupported, isServiceDeskEnabled = $isServiceDeskEnabled, canEditProjectSettings = $canEditProjectSettings',
({ isServiceDeskSupported, isServiceDeskEnabled, canEditProjectSettings, expectedMessage }) => {
it(`displays ${expectedMessage} message`, () => {
const emptyStateMeta = {
isServiceDeskEnabled,
isServiceDeskSupported,
canEditProjectSettings,
};
expect(emptyStateHelper(emptyStateMeta)).toEqual(emptyStateMessages[expectedMessage]);
});
},
);
});
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/jira_import/utils/constants';
import {
calculateJiraImportLabel,
extractJiraProjectsOptions,
......
......@@ -246,27 +246,6 @@ RSpec.describe IssuesHelper do
end
end
describe '#use_startup_call' do
it 'returns false when a query param is present' do
allow(controller.request).to receive(:query_parameters).and_return({ foo: 'bar' })
expect(helper.use_startup_call?).to eq(false)
end
it 'returns false when user has stored sort preference' do
controller.instance_variable_set(:@sort, 'updated_asc')
expect(helper.use_startup_call?).to eq(false)
end
it 'returns true when request.query_parameters is empty with default sorting preference' do
controller.instance_variable_set(:@sort, 'created_date')
allow(controller.request).to receive(:query_parameters).and_return({})
expect(helper.use_startup_call?).to eq(true)
end
end
describe '#issue_header_actions_data' do
let(:current_user) { create(:user) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::Issues::ServiceDeskHelper do
let_it_be(:project) { create(:project, :public, service_desk_enabled: true) }
let(:user) { build_stubbed(:user) }
let(:current_user) { user }
describe '#service_desk_meta' do
subject { helper.service_desk_meta(project) }
context "when service desk is supported and user can edit project settings" do
before do
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(true)
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).with(current_user, :admin_project, project).and_return(true)
end
it {
is_expected.to eq({
is_service_desk_supported: true,
is_service_desk_enabled: true,
can_edit_project_settings: true,
service_desk_address: project.service_desk_address,
service_desk_help_page: help_page_path('user/project/service_desk'),
edit_project_page: edit_project_path(project),
svg_path: ActionController::Base.helpers.image_path('illustrations/service_desk_empty.svg')
})
}
end
context "when service desk is not supported and user cannot edit project settings" do
before do
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(false)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(false)
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).with(current_user, :admin_project, project).and_return(false)
end
it {
is_expected.to eq({
is_service_desk_supported: false,
is_service_desk_enabled: false,
can_edit_project_settings: false,
incoming_email_help_page: help_page_path('administration/incoming_email', anchor: 'set-it-up'),
svg_path: ActionController::Base.helpers.image_path('illustrations/service-desk-setup.svg')
})
}
end
end
end
......@@ -203,28 +203,80 @@ RSpec.describe Ci::Runner do
end
end
describe '.belonging_to_parent_group_of_project' do
let(:project) { create(:project, group: group) }
let(:group) { create(:group) }
let(:runner) { create(:ci_runner, :group, groups: [group]) }
let!(:unrelated_group) { create(:group) }
let!(:unrelated_project) { create(:project, group: unrelated_group) }
let!(:unrelated_runner) { create(:ci_runner, :group, groups: [unrelated_group]) }
shared_examples '.belonging_to_parent_group_of_project' do
let!(:group1) { create(:group) }
let!(:project1) { create(:project, group: group1) }
let!(:runner1) { create(:ci_runner, :group, groups: [group1]) }
let!(:group2) { create(:group) }
let!(:project2) { create(:project, group: group2) }
let!(:runner2) { create(:ci_runner, :group, groups: [group2]) }
let(:project_id) { project1.id }
subject(:result) { described_class.belonging_to_parent_group_of_project(project_id) }
it 'returns the specific group runner' do
expect(described_class.belonging_to_parent_group_of_project(project.id)).to contain_exactly(runner)
expect(result).to contain_exactly(runner1)
end
context 'with a parent group with a runner' do
let(:runner) { create(:ci_runner, :group, groups: [parent_group]) }
let(:project) { create(:project, group: group) }
let(:group) { create(:group, parent: parent_group) }
let(:parent_group) { create(:group) }
context 'with a parent group with a runner', :sidekiq_inline do
before do
group1.update!(parent: group2)
end
it 'returns the group runner from the parent group' do
expect(described_class.belonging_to_parent_group_of_project(project.id)).to contain_exactly(runner)
it 'returns the group runner from the group and the parent group' do
expect(result).to contain_exactly(runner1, runner2)
end
end
context 'with multiple project ids' do
let(:project_id) { [project1.id, project2.id] }
it 'raises ArgumentError' do
expect { result }.to raise_error(ArgumentError)
end
end
end
context 'when ci_decompose_belonging_to_parent_group_of_project_query is enabled' do
context 'when use_traversal_ids* are enabled' do
it_behaves_like '.belonging_to_parent_group_of_project'
end
context 'when use_traversal_ids* are disabled' do
before do
stub_feature_flags(
use_traversal_ids: false,
use_traversal_ids_for_ancestors: false,
use_traversal_ids_for_ancestor_scopes: false
)
end
it_behaves_like '.belonging_to_parent_group_of_project'
end
end
context 'when ci_decompose_belonging_to_parent_group_of_project_query is disabled' do
before do
stub_feature_flags(ci_decompose_belonging_to_parent_group_of_project_query: false)
end
context 'when use_traversal_ids* are enabled' do
it_behaves_like '.belonging_to_parent_group_of_project'
end
context 'when use_traversal_ids* are disabled' do
before do
stub_feature_flags(
use_traversal_ids: false,
use_traversal_ids_for_ancestors: false,
use_traversal_ids_for_ancestor_scopes: false
)
end
it_behaves_like '.belonging_to_parent_group_of_project'
end
end
describe '.owned_or_instance_wide' do
......
......@@ -202,7 +202,7 @@ RSpec.describe PipelineSerializer do
# Existing numbers are high and require performance optimization
# Ongoing issue:
# https://gitlab.com/gitlab-org/gitlab/-/issues/225156
expected_queries = Gitlab.ee? ? 74 : 70
expected_queries = Gitlab.ee? ? 78 : 74
expect(recorded.count).to be_within(2).of(expected_queries)
expect(recorded.cached_count).to eq(0)
......
......@@ -290,10 +290,9 @@ RSpec.configure do |config|
stub_feature_flags(diffs_virtual_scrolling: false)
# The following `vue_issues_list`/`vue_issuables_list` stubs can be removed
# The following `vue_issues_list` stub can be removed
# once the Vue issues page has feature parity with the current Haml page
stub_feature_flags(vue_issues_list: false)
stub_feature_flags(vue_issuables_list: false)
# Disable `refactor_blob_viewer` as we refactor
# the blob viewer. See the follwing epic for more:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment