diff options
Diffstat (limited to 'app/assets/javascripts/projects')
15 files changed, 235 insertions, 73 deletions
diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue index 1cdf26b76b7..4505dd1f85c 100644 --- a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue +++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue @@ -2,11 +2,11 @@ import { GlLoadingIcon } from '@gitlab/ui'; import createFlash from '~/flash'; import { __ } from '~/locale'; -import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; import { getQueryHeaders, toggleQueryPollingByVisibility, } from '~/pipelines/components/graph/utils'; +import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue'; import { formatStages } from '../utils'; import getLinkedPipelinesQuery from '../graphql/queries/get_linked_pipelines.query.graphql'; import getPipelineStagesQuery from '../graphql/queries/get_pipeline_stages.query.graphql'; @@ -21,8 +21,6 @@ export default { components: { GlLoadingIcon, PipelineMiniGraph, - LinkedPipelinesMiniList: () => - import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'), }, inject: { fullPath: { @@ -92,12 +90,12 @@ export default { }; }, computed: { - hasDownstream() { - return this.pipeline?.downstream?.nodes.length > 0; - }, downstreamPipelines() { return this.pipeline?.downstream?.nodes; }, + pipelinePath() { + return this.pipeline?.path ?? ''; + }, upstreamPipeline() { return this.pipeline?.upstream; }, @@ -128,23 +126,13 @@ export default { <template> <div class="gl-pt-2"> <gl-loading-icon v-if="$apollo.queries.pipeline.loading" /> - <div v-else class="gl-align-items-center gl-display-flex"> - <linked-pipelines-mini-list - v-if="upstreamPipeline" - :triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [ - upstreamPipeline, - ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */" - data-testid="commit-box-mini-graph-upstream" - /> - - <pipeline-mini-graph :stages="formattedStages" data-testid="commit-box-mini-graph" /> - - <linked-pipelines-mini-list - v-if="hasDownstream" - :triggered="downstreamPipelines" - :pipeline-path="pipeline.path" - data-testid="commit-box-mini-graph-downstream" - /> - </div> + <pipeline-mini-graph + v-else + data-testid="commit-box-pipeline-mini-graph" + :downstream-pipelines="downstreamPipelines" + :pipeline-path="pipelinePath" + :stages="formattedStages" + :upstream-pipeline="upstreamPipeline" + /> </div> </template> diff --git a/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue b/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue index ecd2288eb2f..06d96ef7bef 100644 --- a/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue +++ b/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue @@ -1,7 +1,7 @@ <script> import { GlAlert, GlSkeletonLoader } from '@gitlab/ui'; import { GlColumnChart } from '@gitlab/ui/dist/charts'; -import dateFormat from 'dateformat'; +import dateFormat from '~/lib/dateformat'; import { getDateInPast } from '~/lib/utils/datetime_utility'; import { __, s__, sprintf } from '~/locale'; import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue'; diff --git a/app/assets/javascripts/projects/project_visibility.js b/app/assets/javascripts/projects/project_visibility.js index b8ac17a01f2..84b8936c17f 100644 --- a/app/assets/javascripts/projects/project_visibility.js +++ b/app/assets/javascripts/projects/project_visibility.js @@ -1,13 +1,7 @@ import { escape } from 'lodash'; import { __, sprintf } from '~/locale'; import eventHub from '~/projects/new/event_hub'; - -// Values are from lib/gitlab/visibility_level.rb -const visibilityLevel = { - private: 0, - internal: 10, - public: 20, -}; +import { VISIBILITY_LEVELS_STRING_TO_INTEGER } from '~/visibility_level/constants'; function setVisibilityOptions({ name, visibility, showPath, editPath }) { document.querySelectorAll('.visibility-level-setting .gl-form-radio').forEach((option) => { @@ -19,13 +13,14 @@ function setVisibilityOptions({ name, visibility, showPath, editPath }) { const optionInput = option.querySelector('input[type=radio]'); const optionValue = optionInput ? parseInt(optionInput.value, 10) : 0; - if (visibilityLevel[visibility] < optionValue) { + if (VISIBILITY_LEVELS_STRING_TO_INTEGER[visibility] < optionValue) { option.classList.add('disabled'); optionInput.disabled = true; const reason = option.querySelector('.option-disabled-reason'); if (reason) { const optionTitle = option.querySelector('.js-visibility-level-radio span'); const optionName = optionTitle ? optionTitle.innerText.toLowerCase() : ''; + // eslint-disable-next-line no-unsanitized/property reason.innerHTML = sprintf( __( 'This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group.', diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue index ada951f6867..e8eaf0a70b2 100644 --- a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue +++ b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue @@ -1,16 +1,58 @@ <script> -import { __ } from '~/locale'; +import { s__ } from '~/locale'; +import createFlash from '~/flash'; +import branchRulesQuery from './graphql/queries/branch_rules.query.graphql'; +import BranchRule from './components/branch_rule.vue'; + +export const i18n = { + queryError: s__( + 'ProtectedBranch|An error occurred while loading branch rules. Please try again.', + ), + emptyState: s__( + 'ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured.', + ), +}; export default { name: 'BranchRules', - i18n: { heading: __('Branch') }, + i18n, + components: { + BranchRule, + }, + apollo: { + branchRules: { + query: branchRulesQuery, + variables() { + return { + projectPath: this.projectPath, + }; + }, + update(data) { + return data.project?.branchRules?.nodes || []; + }, + error() { + createFlash({ message: this.$options.i18n.queryError }); + }, + }, + }, + props: { + projectPath: { + type: String, + required: true, + }, + }, + data() { + return { + branchRules: [], + }; + }, }; </script> <template> - <div> - <strong>{{ $options.i18n.heading }}</strong> + <div class="settings-content"> + <branch-rule v-for="rule in branchRules" :key="rule.name" :name="rule.name" /> - <!-- TODO - List branch rules (https://gitlab.com/gitlab-org/gitlab/-/issues/362217) --> + <span v-if="!branchRules.length" data-testid="empty">{{ $options.i18n.emptyState }}</span> </div> </template> diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue new file mode 100644 index 00000000000..68750318029 --- /dev/null +++ b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue @@ -0,0 +1,61 @@ +<script> +import { GlBadge } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +export const i18n = { + defaultLabel: s__('BranchRules|default'), + protectedLabel: s__('BranchRules|protected'), +}; + +export default { + name: 'BranchRule', + i18n, + components: { + GlBadge, + }, + props: { + name: { + type: String, + required: true, + }, + isDefault: { + type: Boolean, + required: false, + default: false, + }, + isProtected: { + type: Boolean, + required: false, + default: false, + }, + approvalDetails: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + hasApprovalDetails() { + return this.approvalDetails && this.approvalDetails.length; + }, + }, +}; +</script> + +<template> + <div class="gl-border-b gl-pt-5 gl-pb-5"> + <strong class="gl-font-monospace">{{ name }}</strong> + + <gl-badge v-if="isDefault" variant="info" size="sm" class="gl-ml-2">{{ + $options.i18n.defaultLabel + }}</gl-badge> + + <gl-badge v-if="isProtected" variant="success" size="sm" class="gl-ml-2">{{ + $options.i18n.protectedLabel + }}</gl-badge> + + <ul v-if="hasApprovalDetails" class="gl-pl-6 gl-mt-2 gl-mb-0 gl-text-gray-500"> + <li v-for="(detail, index) in approvalDetails" :key="index">{{ detail }}</li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql b/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql new file mode 100644 index 00000000000..104a0c25a80 --- /dev/null +++ b/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql @@ -0,0 +1,10 @@ +query getBranchRules($projectPath: ID!) { + project(fullPath: $projectPath) { + id + branchRules { + nodes { + name + } + } + } +} diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js index abe0b93081e..35322e2e466 100644 --- a/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js +++ b/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js @@ -1,13 +1,28 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import BranchRulesApp from '~/projects/settings/repository/branch_rules/app.vue'; +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + export default function mountBranchRules(el) { if (!el) return null; + const { projectPath } = el.dataset; + return new Vue({ el, + apolloProvider, render(createElement) { - return createElement(BranchRulesApp); + return createElement(BranchRulesApp, { + props: { + projectPath, + }, + }); }, }); } diff --git a/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue index 9c8de9bef2d..3d553e71f71 100644 --- a/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue +++ b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue @@ -2,7 +2,7 @@ import { GlTokenSelector, GlAvatarLabeled } from '@gitlab/ui'; import { s__ } from '~/locale'; import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants'; -import searchProjectTopics from '../queries/project_topics_search.query.graphql'; +import searchProjectTopics from '~/graphql_shared/queries/project_topics_search.query.graphql'; export default { components: { diff --git a/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql b/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql deleted file mode 100644 index 0c0a874d950..00000000000 --- a/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql +++ /dev/null @@ -1,10 +0,0 @@ -query searchProjectTopics($search: String) { - topics(search: $search) { - nodes { - id - name - title - avatarUrl - } - } -} diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue index 14c8c53dd19..71ff3e892b1 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue @@ -1,12 +1,18 @@ <script> -import { GlAlert, GlSafeHtmlDirective } from '@gitlab/ui'; +import { GlAlert, GlSprintf, GlLink, GlSafeHtmlDirective } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; +import { helpPagePath } from '~/helpers/help_page_helper'; import { __, sprintf } from '~/locale'; import ServiceDeskSetting from './service_desk_setting.vue'; export default { + customEmailHelpPath: helpPagePath('/user/project/service_desk.html', { + anchor: 'using-a-custom-email-address', + }), components: { GlAlert, + GlSprintf, + GlLink, ServiceDeskSetting, }, directives: { @@ -43,6 +49,9 @@ export default { templates: { default: [], }, + publicProject: { + default: false, + }, }, data() { return { @@ -127,6 +136,27 @@ export default { <template> <div> + <gl-alert + v-if="publicProject && isEnabled" + class="mb-3" + variant="warning" + data-testid="public-project-alert" + :dismissible="false" + > + <gl-sprintf + :message=" + __( + 'This project is public. Non-members can guess the Service Desk email address, because it contains the group and project name. %{linkStart}How do I create a custom email address?%{linkEnd}', + ) + " + > + <template #link="{ content }"> + <gl-link :href="$options.customEmailHelpPath" target="_blank"> + {{ content }} + </gl-link> + </template> + </gl-sprintf> + </gl-alert> <gl-alert v-if="isAlertShowing" class="mb-3" :variant="alertVariant" @dismiss="onDismiss"> <span v-safe-html="alertMessage"></span> </gl-alert> diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue index 8a9a0b541f3..452e7a4fd21 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue @@ -176,7 +176,7 @@ export default { </template> </gl-form-input-group> <template v-if="email && hasCustomEmail" #description> - <span class="gl-mt-2 d-inline-block"> + <span class="gl-mt-2 gl-display-inline-block"> <gl-sprintf :message="__('Emails sent to %{email} are also supported.')"> <template #email> <code>{{ incomingEmail }}</code> @@ -190,7 +190,11 @@ export default { </template> </gl-form-group> - <gl-form-group :label="__('Email address suffix')" :state="!projectKeyError"> + <gl-form-group + :label="__('Email address suffix')" + :state="!projectKeyError" + data-testid="suffix-form-group" + > <gl-form-input v-if="hasProjectKeySupport" id="service-desk-project-suffix" @@ -216,22 +220,24 @@ export default { </gl-sprintf> </template> <template v-else #description> - <gl-sprintf - :message=" - __( - 'To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}', - ) - " - > - <template #link="{ content }"> - <gl-link - :href="customEmailAddressHelpUrl" - target="_blank" - class="gl-text-blue-600 font-size-inherit" - >{{ content }} - </gl-link> - </template> - </gl-sprintf> + <span class="gl-text-gray-900"> + <gl-sprintf + :message=" + __( + 'To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}', + ) + " + > + <template #link="{ content }"> + <gl-link + :href="customEmailAddressHelpUrl" + target="_blank" + class="gl-text-blue-600 font-size-inherit" + >{{ content }} + </gl-link> + </template> + </gl-sprintf> + </span> </template> <template v-if="hasProjectKeySupport && projectKeyError" #invalid-feedback> @@ -266,7 +272,27 @@ export default { /> <template v-if="hasProjectKeySupport" #description> - {{ __('Emails sent from Service Desk have this name.') }} + {{ __('Name to be used as the sender for emails from Service Desk.') }} + </template> + <template v-else #description> + <span class="gl-text-gray-900"> + <gl-sprintf + :message=" + __( + 'To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}', + ) + " + > + <template #link="{ content }"> + <gl-link + :href="customEmailAddressHelpUrl" + target="_blank" + class="gl-text-blue-600 font-size-inherit" + >{{ content }} + </gl-link> + </template> + </gl-sprintf> + </span> </template> </gl-form-group> diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue index bdd9f940d79..315f0743b53 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue @@ -100,7 +100,7 @@ export default { <gl-dropdown-item v-for="template in item" :key="template.key" - :is-check-item="true" + is-check-item :is-checked=" template.project_id === selectedFileTemplateProjectId && template.name === selectedTemplate diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js index e14cdee17ce..26435a5fac9 100644 --- a/app/assets/javascripts/projects/settings_service_desk/index.js +++ b/app/assets/javascripts/projects/settings_service_desk/index.js @@ -20,6 +20,7 @@ export default () => { selectedTemplate, selectedFileTemplateProjectId, templates, + publicProject, } = el.dataset; return new Vue({ @@ -35,6 +36,7 @@ export default () => { selectedTemplate, selectedFileTemplateProjectId: parseInt(selectedFileTemplateProjectId, 10) || null, templates: JSON.parse(templates), + publicProject: parseBoolean(publicProject), }, render: (createElement) => createElement(ServiceDeskRoot), }); diff --git a/app/assets/javascripts/projects/star.js b/app/assets/javascripts/projects/star.js index 5bbace11b15..e063064663b 100644 --- a/app/assets/javascripts/projects/star.js +++ b/app/assets/javascripts/projects/star.js @@ -22,11 +22,14 @@ export default class Star { starSpan.classList.remove('starred'); starSpan.textContent = s__('StarProject|Star'); starIcon.remove(); + // eslint-disable-next-line no-unsanitized/method starSpan.insertAdjacentHTML('beforebegin', spriteIcon('star-o', iconClasses)); } else { starSpan.classList.add('starred'); starSpan.textContent = __('Unstar'); starIcon.remove(); + + // eslint-disable-next-line no-unsanitized/method starSpan.insertAdjacentHTML('beforebegin', spriteIcon('star', iconClasses)); } }) diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue index a79da00de43..6b14ebadacc 100644 --- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue +++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue @@ -4,7 +4,7 @@ import Visibility from 'visibilityjs'; import createFlash from '~/flash'; import Poll from '~/lib/utils/poll'; import { __, s__, sprintf } from '~/locale'; -import ciIcon from '~/vue_shared/components/ci_icon.vue'; +import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CommitPipelineService from '../services/commit_pipeline_service'; export default { @@ -12,7 +12,7 @@ export default { GlTooltip: GlTooltipDirective, }, components: { - ciIcon, + CiIcon, GlLoadingIcon, }, props: { |