diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-20 23:50:22 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-20 23:50:22 +0000 |
commit | 9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch) | |
tree | 70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/pages/projects | |
parent | 4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff) | |
download | gitlab-ce-9dc93a4519d9d5d7be48ff274127136236a3adb3.tar.gz |
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/pages/projects')
31 files changed, 405 insertions, 79 deletions
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js index 10bac6d60c2..fc2702b8c37 100644 --- a/app/assets/javascripts/pages/projects/blob/show/index.js +++ b/app/assets/javascripts/pages/projects/blob/show/index.js @@ -5,10 +5,29 @@ import GpgBadges from '~/gpg_badges'; import initBlob from '~/pages/projects/init_blob'; import initWebIdeLink from '~/pages/projects/shared/web_ide_link'; import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue'; +import BlobContentViewer from '~/repository/components/blob_content_viewer.vue'; import '~/sourcegraph/load'; -new BlobViewer(); // eslint-disable-line no-new -initBlob(); +const viewBlobEl = document.querySelector('#js-view-blob-app'); + +if (viewBlobEl) { + const { blobPath } = viewBlobEl.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el: viewBlobEl, + render(createElement) { + return createElement(BlobContentViewer, { + props: { + path: blobPath, + }, + }); + }, + }); +} else { + new BlobViewer(); // eslint-disable-line no-new + initBlob(); +} const CommitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status'); const statusLink = document.querySelector('.commit-actions .ci-status-link'); diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js index 72861855c5a..27ec746ad02 100644 --- a/app/assets/javascripts/pages/projects/branches/index/index.js +++ b/app/assets/javascripts/pages/projects/branches/index/index.js @@ -1,7 +1,16 @@ +import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior'; import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner'; +import BranchSortDropdown from '~/branches/branch_sort_dropdown'; import DeleteModal from '~/branches/branches_delete_modal'; import initDiverganceGraph from '~/branches/divergence_graph'; AjaxLoadingSpinner.init(); new DeleteModal(); // eslint-disable-line no-new -initDiverganceGraph(document.querySelector('.js-branch-list').dataset.divergingCountsEndpoint); + +const { divergingCountsEndpoint, defaultBranch } = document.querySelector( + '.js-branch-list', +).dataset; + +initDiverganceGraph(divergingCountsEndpoint, defaultBranch); +BranchSortDropdown(); +initDeprecatedRemoveRowBehavior(); diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue index 7112b23775d..288d6711682 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue @@ -13,6 +13,7 @@ import { GlFormRadioGroup, GlFormSelect, } from '@gitlab/ui'; +import { kebabCase } from 'lodash'; import { buildApiUrl } from '~/api/api_utils'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; @@ -145,6 +146,10 @@ export default { this.fork.visibility = visibility; } }, + // eslint-disable-next-line func-names + 'fork.name': function (newVal) { + this.fork.slug = kebabCase(newVal); + }, }, mounted() { this.fetchNamespaces(); @@ -213,6 +218,7 @@ export default { id="fork-url" v-model="selectedNamespace" data-testid="fork-url-input" + data-qa-selector="fork_namespace_dropdown" required > <template slot="first"> @@ -286,6 +292,7 @@ export default { category="primary" variant="confirm" data-testid="submit-button" + data-qa-selector="fork_project_button" :loading="isSaving" > {{ s__('ForkProject|Fork project') }} diff --git a/app/assets/javascripts/pages/projects/hooks/index.js b/app/assets/javascripts/pages/projects/hooks/index.js new file mode 100644 index 00000000000..2a120a690ef --- /dev/null +++ b/app/assets/javascripts/pages/projects/hooks/index.js @@ -0,0 +1,3 @@ +import initSearchSettings from '~/search_settings'; + +initSearchSettings(); diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js index 4e35f28ab06..c0da0069a99 100644 --- a/app/assets/javascripts/pages/projects/issues/form.js +++ b/app/assets/javascripts/pages/projects/issues/form.js @@ -5,6 +5,7 @@ import IssuableForm from 'ee_else_ce/issuable_form'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import GLForm from '~/gl_form'; import initSuggestions from '~/issuable_suggestions'; +import initIssuableTypeSelector from '~/issuable_type_selector'; import LabelsSelect from '~/labels_select'; import MilestoneSelect from '~/milestone_select'; import IssuableTemplateSelectors from '~/templates/issuable_template_selectors'; @@ -20,4 +21,5 @@ export default () => { }); initSuggestions(); + initIssuableTypeSelector(); }; diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js index 366f8dc61bc..85489ae8687 100644 --- a/app/assets/javascripts/pages/projects/issues/index/index.js +++ b/app/assets/javascripts/pages/projects/issues/index/index.js @@ -20,7 +20,12 @@ initFilteredSearch({ useDefaultState: true, }); -new IssuableIndex(ISSUABLE_INDEX.ISSUE); +if (gon.features?.vueIssuesList) { + new IssuableIndex(); +} else { + new IssuableIndex(ISSUABLE_INDEX.ISSUE); +} + new ShortcutsNavigation(); new UsersSelect(); diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js index 992bf3c54ff..2b679a83eac 100644 --- a/app/assets/javascripts/pages/projects/issues/show.js +++ b/app/assets/javascripts/pages/projects/issues/show.js @@ -3,6 +3,8 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; import initIssuableSidebar from '~/init_issuable_sidebar'; import initInviteMemberModal from '~/invite_member/init_invite_member_modal'; import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger'; +import initInviteMembersModal from '~/invite_members/init_invite_members_modal'; +import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger'; import { IssuableType } from '~/issuable_show/constants'; import Issue from '~/issue'; import '~/notes/index'; @@ -34,6 +36,8 @@ export default function initShowIssue() { initIssueHeaderActions(store); initSentryErrorStackTraceApp(); initRelatedMergeRequestsApp(); + initInviteMembersModal(); + initInviteMembersTrigger(); import(/* webpackChunkName: 'design_management' */ '~/design_management') .then((module) => module.default()) @@ -42,10 +46,18 @@ export default function initShowIssue() { new ZenMode(); // eslint-disable-line no-new if (issueType !== IssuableType.TestCase) { + const awardEmojiEl = document.getElementById('js-vue-awards-block'); + new Issue(); // eslint-disable-line no-new new ShortcutsIssuable(); // eslint-disable-line no-new initIssuableSidebar(); - loadAwardsHandler(); + if (awardEmojiEl) { + import('~/emoji/awards_app') + .then((m) => m.default(awardEmojiEl)) + .catch(() => {}); + } else { + loadAwardsHandler(); + } initInviteMemberModal(); initInviteMemberTrigger(); } diff --git a/app/assets/javascripts/pages/projects/jobs/index/index.js b/app/assets/javascripts/pages/projects/jobs/index/index.js index 681d151b77f..75194499a7f 100644 --- a/app/assets/javascripts/pages/projects/jobs/index/index.js +++ b/app/assets/javascripts/pages/projects/jobs/index/index.js @@ -1,17 +1,23 @@ import Vue from 'vue'; +import initJobsTable from '~/jobs/components/table'; import GlCountdown from '~/vue_shared/components/gl_countdown.vue'; -const remainingTimeElements = document.querySelectorAll('.js-remaining-time'); -remainingTimeElements.forEach( - (el) => - new Vue({ - el, - render(h) { - return h(GlCountdown, { - props: { - endDateString: el.dateTime, - }, - }); - }, - }), -); +if (gon.features?.jobsTableVue) { + initJobsTable(); +} else { + const remainingTimeElements = document.querySelectorAll('.js-remaining-time'); + + remainingTimeElements.forEach( + (el) => + new Vue({ + el, + render(h) { + return h(GlCountdown, { + props: { + endDateString: el.dateTime, + }, + }); + }, + }), + ); +} diff --git a/app/assets/javascripts/pages/projects/jobs/show/index.js b/app/assets/javascripts/pages/projects/jobs/show/index.js index d57dbeb1242..6fef057dee0 100644 --- a/app/assets/javascripts/pages/projects/jobs/show/index.js +++ b/app/assets/javascripts/pages/projects/jobs/show/index.js @@ -1,3 +1,3 @@ import initJobDetails from '~/jobs'; -document.addEventListener('DOMContentLoaded', initJobDetails); +initJobDetails(); diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js index 9f782c07101..94ab0d64de4 100644 --- a/app/assets/javascripts/pages/projects/labels/index/index.js +++ b/app/assets/javascripts/pages/projects/labels/index/index.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +import initDeleteLabelModal from '~/delete_label_modal'; import initLabels from '~/init_labels'; import { BV_SHOW_MODAL } from '~/lib/utils/constants'; import Translate from '~/vue_shared/translate'; @@ -9,6 +10,7 @@ Vue.use(Translate); const initLabelIndex = () => { initLabels(); + initDeleteLabelModal(); const onRequestFinished = ({ labelUrl, successful }) => { const button = document.querySelector( diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue index 32ca623ca45..ef9e13f7ccf 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue @@ -1,11 +1,17 @@ <script> -import { GlLink } from '@gitlab/ui'; -import { ACTION_LABELS } from '../constants'; +import { GlProgressBar, GlSprintf } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { ACTION_LABELS, ACTION_SECTIONS } from '../constants'; +import LearnGitlabSectionCard from './learn_gitlab_section_card.vue'; export default { - components: { GlLink }, + components: { GlProgressBar, GlSprintf, LearnGitlabSectionCard }, i18n: { - ACTION_LABELS, + title: s__('LearnGitLab|Learn GitLab'), + description: s__( + 'LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project.', + ), + percentageCompleted: s__(`LearnGitLab|%{percentage}%{percentSymbol} completed`), }, props: { actions: { @@ -13,15 +19,49 @@ export default { type: Object, }, }, + maxValue: Object.keys(ACTION_LABELS).length, + sections: Object.keys(ACTION_SECTIONS), + computed: { + progressValue() { + return Object.values(this.actions).filter((a) => a.completed).length; + }, + progressPercentage() { + return Math.round((this.progressValue / this.$options.maxValue) * 100); + }, + }, + methods: { + actionsFor(section) { + const actions = Object.fromEntries( + Object.entries(this.actions).filter( + ([action]) => ACTION_LABELS[action].section === section, + ), + ); + return actions; + }, + }, }; </script> <template> - <ul> - <li v-for="(value, action) in actions" :key="action"> - <span v-if="value.completed">{{ $options.i18n.ACTION_LABELS[action].title }}</span> - <span v-else> - <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link> - </span> - </li> - </ul> + <div> + <div class="row"> + <div class="gl-mb-7 gl-ml-5"> + <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1> + <p class="gl-text-gray-700 gl-mb-0">{{ $options.i18n.description }}</p> + </div> + </div> + <div class="gl-mb-3"> + <p class="gl-text-gray-500 gl-mb-2" data-testid="completion-percentage"> + <gl-sprintf :message="$options.i18n.percentageCompleted"> + <template #percentage>{{ progressPercentage }}</template> + <template #percentSymbol>%</template> + </gl-sprintf> + </p> + <gl-progress-bar :value="progressValue" :max="$options.maxValue" /> + </div> + <div class="row row-cols-1 row-cols-md-3 gl-mt-5"> + <div v-for="section in $options.sections" :key="section" class="col gl-mb-6"> + <learn-gitlab-section-card :section="section" :actions="actionsFor(section)" /> + </div> + </div> + </div> </template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue index 230054ff76e..8f92ce95dbf 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue @@ -1,5 +1,6 @@ <script> import { GlProgressBar, GlSprintf } from '@gitlab/ui'; +import { pick } from 'lodash'; import { s__ } from '~/locale'; import { ACTION_LABELS } from '../constants'; import LearnGitlabInfoCard from './learn_gitlab_info_card.vue'; @@ -42,7 +43,7 @@ export default { infoProps(action) { return { ...this.actions[action], - ...ACTION_LABELS[action], + ...pick(ACTION_LABELS[action], ['title', 'actionLabel', 'description', 'trialRequired']), }; }, progressValue() { @@ -96,6 +97,9 @@ export default { <div class="row row-cols-2 row-cols-md-3 row-cols-lg-4"> <div class="col gl-mb-6"> + <learn-gitlab-info-card v-bind="infoProps('issueCreated')" /> + </div> + <div class="col gl-mb-6"> <learn-gitlab-info-card v-bind="infoProps('mergeRequestCreated')" /> </div> </div> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue index 3d2a8eed9d4..6cd3bbc359b 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue @@ -61,7 +61,7 @@ export default { <div class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content" > - <img :src="svg" /> + <img :src="svg" :alt="actionLabel" /> <h6>{{ title }}</h6> <p class="gl-font-sm gl-text-gray-700">{{ description }}</p> <gl-link :href="url" target="_blank">{{ actionLabel }}</gl-link> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue new file mode 100644 index 00000000000..db694a66afd --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue @@ -0,0 +1,52 @@ +<script> +import { GlCard } from '@gitlab/ui'; +import { imagePath } from '~/lib/utils/common_utils'; +import { ACTION_LABELS, ACTION_SECTIONS } from '../constants'; + +import LearnGitlabSectionLink from './learn_gitlab_section_link.vue'; + +export default { + name: 'LearnGitlabSectionCard', + components: { GlCard, LearnGitlabSectionLink }, + i18n: { + ...ACTION_SECTIONS, + }, + props: { + section: { + required: true, + type: String, + }, + actions: { + required: true, + type: Object, + }, + }, + computed: { + sortedActions() { + return Object.entries(this.actions).sort( + (a1, a2) => ACTION_LABELS[a1[0]].position - ACTION_LABELS[a2[0]].position, + ); + }, + }, + methods: { + svg(section) { + return imagePath(`learn_gitlab/section_${section}.svg`); + }, + }, +}; +</script> +<template> + <gl-card class="gl-pt-0 learn-gitlab-section-card"> + <div class="learn-gitlab-section-card-header"> + <img :src="svg(section)" /> + <h2 class="gl-font-lg gl-mb-3">{{ $options.i18n[section].title }}</h2> + <p class="gl-text-gray-700 gl-mb-6">{{ $options.i18n[section].description }}</p> + </div> + <learn-gitlab-section-link + v-for="[action, value] in sortedActions" + :key="action" + :action="action" + :value="value" + /> + </gl-card> +</template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue new file mode 100644 index 00000000000..6f51c7372fd --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue @@ -0,0 +1,43 @@ +<script> +import { GlLink, GlIcon } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { ACTION_LABELS } from '../constants'; + +export default { + name: 'LearnGitlabSectionLink', + components: { GlLink, GlIcon }, + i18n: { + ACTION_LABELS, + trialOnly: s__('LearnGitlab|Trial only'), + }, + props: { + action: { + required: true, + type: String, + }, + value: { + required: true, + type: Object, + }, + }, + computed: { + trialOnly() { + return ACTION_LABELS[this.action].trialRequired; + }, + }, +}; +</script> +<template> + <div class="gl-mb-4"> + <span v-if="value.completed" class="gl-text-green-500"> + <gl-icon name="check-circle-filled" :size="16" data-testid="completed-icon" /> + {{ $options.i18n.ACTION_LABELS[action].title }} + </span> + <span v-else> + <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link> + </span> + <span v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only"> + - {{ $options.i18n.trialOnly }} + </span> + </div> +</template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js index 80f04b0cf44..9e204aa6746 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js +++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js @@ -5,6 +5,8 @@ export const ACTION_LABELS = { title: s__('LearnGitLab|Create or import a repository'), actionLabel: s__('LearnGitLab|Create or import a repository'), description: s__('LearnGitLab|Create or import your first repository into your new project.'), + section: 'workspace', + position: 1, }, userAdded: { title: s__('LearnGitLab|Invite your colleagues'), @@ -12,16 +14,22 @@ export const ACTION_LABELS = { description: s__( 'LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features.', ), + section: 'workspace', + position: 0, }, pipelineCreated: { title: s__('LearnGitLab|Set up CI/CD'), actionLabel: s__('LearnGitLab|Set-up CI/CD'), description: s__('LearnGitLab|Save time by automating your integration and deployment tasks.'), + section: 'workspace', + position: 2, }, trialStarted: { title: s__('LearnGitLab|Start a free Ultimate trial'), actionLabel: s__('LearnGitLab|Try GitLab Ultimate for free'), description: s__('LearnGitLab|Try all GitLab features for 30 days, no credit card required.'), + section: 'workspace', + position: 3, }, codeOwnersEnabled: { title: s__('LearnGitLab|Add code owners'), @@ -30,21 +38,59 @@ export const ACTION_LABELS = { 'LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths.', ), trialRequired: true, + section: 'workspace', + position: 4, }, requiredMrApprovalsEnabled: { title: s__('LearnGitLab|Add merge request approval'), actionLabel: s__('LearnGitLab|Enable require merge approvals'), description: s__('LearnGitLab|Route code reviews to the right reviewers, every time.'), trialRequired: true, + section: 'workspace', + position: 5, }, mergeRequestCreated: { title: s__('LearnGitLab|Submit a merge request'), actionLabel: s__('LearnGitLab|Submit a merge request (MR)'), description: s__('LearnGitLab|Review and edit proposed changes to source code.'), + section: 'plan', + position: 1, }, securityScanEnabled: { - title: s__('LearnGitLab|Run a security scan'), - actionLabel: s__('LearnGitLab|Run a Security scan'), + title: s__('LearnGitLab|Run a Security scan using CI/CD'), + actionLabel: s__('LearnGitLab|Run a Security scan using CI/CD'), description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'), + section: 'deploy', + position: 1, + }, + issueCreated: { + title: s__('LearnGitLab|Create an issue'), + actionLabel: s__('LearnGitLab|Create an issue'), + description: s__( + 'LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work.', + ), + section: 'plan', + position: 0, + }, +}; + +export const ACTION_SECTIONS = { + workspace: { + title: s__('LearnGitLab|Set up your workspace'), + description: s__( + "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:", + ), + }, + plan: { + title: s__('LearnGitLab|Plan and execute'), + description: s__( + 'LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:', + ), + }, + deploy: { + title: s__('LearnGitLab|Deploy'), + description: s__( + 'LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:', + ), }, }; diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js index d4d5e9f2711..a5118e3529a 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js @@ -5,21 +5,33 @@ import initPipelines from '~/commit/pipelines/pipelines_bundle'; import initIssuableSidebar from '~/init_issuable_sidebar'; import initInviteMemberModal from '~/invite_member/init_invite_member_modal'; import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger'; +import initInviteMembersModal from '~/invite_members/init_invite_members_modal'; +import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger'; import { handleLocationHash } from '~/lib/utils/common_utils'; import StatusBox from '~/merge_request/components/status_box.vue'; import initSourcegraph from '~/sourcegraph'; import ZenMode from '~/zen_mode'; export default function initMergeRequestShow() { + const awardEmojiEl = document.getElementById('js-vue-awards-block'); + new ZenMode(); // eslint-disable-line no-new initIssuableSidebar(); initPipelines(); new ShortcutsIssuable(true); // eslint-disable-line no-new handleLocationHash(); initSourcegraph(); - loadAwardsHandler(); + if (awardEmojiEl) { + import('~/emoji/awards_app') + .then((m) => m.default(awardEmojiEl)) + .catch(() => {}); + } else { + loadAwardsHandler(); + } initInviteMemberModal(); initInviteMemberTrigger(); + initInviteMembersModal(); + initInviteMembersTrigger(); const el = document.querySelector('.js-mr-status-box'); // eslint-disable-next-line no-new diff --git a/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js new file mode 100644 index 00000000000..dfb750eca41 --- /dev/null +++ b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js @@ -0,0 +1,3 @@ +import initList from '~/packages_and_registries/infrastructure_registry/list_app_bundle'; + +initList(); diff --git a/app/assets/javascripts/pages/projects/pages/index.js b/app/assets/javascripts/pages/projects/pages/index.js new file mode 100644 index 00000000000..2a120a690ef --- /dev/null +++ b/app/assets/javascripts/pages/projects/pages/index.js @@ -0,0 +1,3 @@ +import initSearchSettings from '~/search_settings'; + +initSearchSettings(); diff --git a/app/assets/javascripts/pages/projects/path_locks/index.js b/app/assets/javascripts/pages/projects/path_locks/index.js new file mode 100644 index 00000000000..e5ab5d43bbf --- /dev/null +++ b/app/assets/javascripts/pages/projects/path_locks/index.js @@ -0,0 +1,3 @@ +import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior'; + +document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior); diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue index 3b19231720a..159c619e16c 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue @@ -139,7 +139,7 @@ export default { v-model="cronInterval" :placeholder="__('Define a custom pattern with cron syntax')" :name="inputNameAttribute" - class="form-control inline cron-interval-input" + class="form-control inline cron-interval-input gl-form-input" type="text" required="true" @input="onCustomInput" diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index da8dc527d79..91f376060f8 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -123,10 +123,19 @@ export default class Project { const loc = window.location.href; if (loc.includes('/-/')) { - const refs = this.fullData.Branches.concat(this.fullData.Tags); - const currentRef = refs.find((ref) => loc.indexOf(ref) > -1); - if (currentRef) { - const targetPath = loc.split(currentRef)[1].slice(1).split('#')[0]; + // Since the current ref in renderRow is outdated on page changes + // (To be addressed in: https://gitlab.com/gitlab-org/gitlab/-/issues/327085) + // We are deciphering the current ref from the dropdown data instead + const currentRef = $dropdown.data('ref'); + // The split and startWith is to ensure an exact word match + // and avoid partial match ie. currentRef is "dev" and loc is "development" + const splitPathAfterRefPortion = loc.split(currentRef)[1]; + const doesPathContainRef = splitPathAfterRefPortion?.startsWith('/'); + + if (doesPathContainRef) { + // We are ignoring the url containing the ref portion + // and plucking the thereafter portion to reconstructure the url that is correct + const targetPath = splitPathAfterRefPortion?.slice(1).split('#')[0]; selectedUrl.searchParams.set('path', targetPath); selectedUrl.hash = window.location.hash; } diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js index 4aea5614bfb..471798d2931 100644 --- a/app/assets/javascripts/pages/projects/project_members/index.js +++ b/app/assets/javascripts/pages/projects/project_members/index.js @@ -7,6 +7,7 @@ import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigg import { s__ } from '~/locale'; import memberExpirationDate from '~/member_expiration_date'; import { initMembersApp } from '~/members'; +import { MEMBER_TYPES } from '~/members/constants'; import { groupLinkRequestFormatter } from '~/members/utils'; import { projectMemberRequestFormatter } from '~/projects/members/utils'; import UsersSelect from '~/users_select'; @@ -42,6 +43,7 @@ new UsersSelect(); // eslint-disable-line no-new const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions']; initMembersApp(document.querySelector('.js-project-members-list'), { + namespace: MEMBER_TYPES.user, tableFields: SHARED_FIELDS.concat(['source', 'granted']), tableAttrs: { tr: { 'data-qa-selector': 'member_row' } }, tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'], @@ -56,6 +58,7 @@ initMembersApp(document.querySelector('.js-project-members-list'), { }); initMembersApp(document.querySelector('.js-project-group-links-list'), { + namespace: MEMBER_TYPES.group, tableFields: SHARED_FIELDS.concat('granted'), tableAttrs: { table: { 'data-qa-selector': 'groups_list' }, @@ -72,11 +75,13 @@ initMembersApp(document.querySelector('.js-project-group-links-list'), { }); initMembersApp(document.querySelector('.js-project-invited-members-list'), { + namespace: MEMBER_TYPES.invite, tableFields: SHARED_FIELDS.concat('invited'), requestFormatter: projectMemberRequestFormatter, }); initMembersApp(document.querySelector('.js-project-access-requests-list'), { + namespace: MEMBER_TYPES.accessRequest, tableFields: SHARED_FIELDS.concat('requested'), requestFormatter: projectMemberRequestFormatter, }); diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js index b7e8d4b03ac..be9259ec3ca 100644 --- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js @@ -6,7 +6,6 @@ import initDeployFreeze from '~/deploy_freeze'; import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle'; import registrySettingsApp from '~/registry/settings/registry_settings_bundle'; -import initSearchSettings from '~/search_settings'; import initSettingsPanels from '~/settings_panels'; document.addEventListener('DOMContentLoaded', () => { @@ -43,6 +42,4 @@ document.addEventListener('DOMContentLoaded', () => { } initInstallRunner(); - - initSearchSettings(); }); diff --git a/app/assets/javascripts/pages/projects/settings/index.js b/app/assets/javascripts/pages/projects/settings/index.js new file mode 100644 index 00000000000..cb787c60002 --- /dev/null +++ b/app/assets/javascripts/pages/projects/settings/index.js @@ -0,0 +1,5 @@ +import initRevokeButton from '~/deploy_tokens/init_revoke_button'; +import initSearchSettings from '~/search_settings'; + +initSearchSettings(); +initRevokeButton(); diff --git a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js index bf9ccdbf9a8..01ad87160c5 100644 --- a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js @@ -1,4 +1,7 @@ +import initIntegrationsList from '~/integrations/index'; import PersistentUserCallout from '~/persistent_user_callout'; const callout = document.querySelector('.js-webhooks-moved-alert'); PersistentUserCallout.factory(callout); + +initIntegrationsList(); diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js index 4a800ab150d..3a46241e2eb 100644 --- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js @@ -3,7 +3,6 @@ import mountErrorTrackingForm from '~/error_tracking_settings'; import mountGrafanaIntegration from '~/grafana_integration'; import initIncidentsSettings from '~/incidents_settings'; import mountOperationSettings from '~/operation_settings'; -import initSearchSettings from '~/search_settings'; import initSettingsPanels from '~/settings_panels'; initIncidentsSettings(); @@ -14,7 +13,3 @@ if (!IS_EE) { initSettingsPanels(); } mountAlertsSettings(document.querySelector('.js-alerts-settings')); - -document.addEventListener('DOMContentLoaded', () => { - initSearchSettings(); -}); diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js index c7bcbb83051..e90954c14c5 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js @@ -1,5 +1,4 @@ import MirrorRepos from '~/mirrors/mirror_repos'; -import initSearchSettings from '~/search_settings'; import initForm from '../form'; document.addEventListener('DOMContentLoaded', () => { @@ -7,6 +6,4 @@ document.addEventListener('DOMContentLoaded', () => { const mirrorReposContainer = document.querySelector('.js-mirror-settings'); if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init(); - - initSearchSettings(); }); diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue index d62df77ad2c..c110c1d4d62 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue @@ -12,6 +12,11 @@ export default { event: 'change', }, props: { + label: { + type: String, + required: false, + default: '', + }, name: { type: String, required: false, @@ -82,6 +87,8 @@ export default { class="gl-mr-3" :value="featureEnabled" :disabled="disabledInput" + :label="label" + label-position="hidden" @change="toggleFeature" /> <div class="select-wrapper gl-flex-fill-1"> diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index 0b58cb4731d..0b7b4c0ded1 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -22,6 +22,21 @@ const PAGE_FEATURE_ACCESS_LEVEL = s__('ProjectSettings|Everyone'); export default { i18n: { ...CVE_ID_REQUEST_BUTTON_I18N, + analyticsLabel: s__('ProjectSettings|Analytics'), + containerRegistryLabel: s__('ProjectSettings|Container registry'), + forksLabel: s__('ProjectSettings|Forks'), + issuesLabel: s__('ProjectSettings|Issues'), + lfsLabel: s__('ProjectSettings|Git Large File Storage (LFS)'), + mergeRequestsLabel: s__('ProjectSettings|Merge requests'), + operationsLabel: s__('ProjectSettings|Operations'), + packagesLabel: s__('ProjectSettings|Packages'), + pagesLabel: s__('ProjectSettings|Pages'), + ciCdLabel: s__('CI/CD'), + repositoryLabel: s__('ProjectSettings|Repository'), + requirementsLabel: s__('ProjectSettings|Requirements'), + securityAndComplianceLabel: s__('ProjectSettings|Security & Compliance'), + snippetsLabel: s__('ProjectSettings|Snippets'), + wikiLabel: s__('ProjectSettings|Wiki'), }, components: { @@ -423,11 +438,12 @@ export default { > <project-setting-row ref="issues-settings" - :label="s__('ProjectSettings|Issues')" + :label="$options.i18n.issuesLabel" :help-text="s__('ProjectSettings|Lightweight issue tracking system.')" > <project-feature-setting v-model="issuesAccessLevel" + :label="$options.i18n.issuesLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][issues_access_level]" /> @@ -440,6 +456,8 @@ export default { v-model="cveIdRequestEnabled" class="gl-my-2" :disabled="cveIdRequestIsDisabled" + :label="$options.i18n.cve_request_toggle_label" + label-position="hidden" name="project[project_setting_attributes][cve_id_request_enabled]" data-testid="cve_id_request_toggle" /> @@ -447,11 +465,12 @@ export default { </project-setting-row> <project-setting-row ref="repository-settings" - :label="s__('ProjectSettings|Repository')" + :label="$options.i18n.repositoryLabel" :help-text="repositoryHelpText" > <project-feature-setting v-model="repositoryAccessLevel" + :label="$options.i18n.repositoryLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][repository_access_level]" /> @@ -459,11 +478,12 @@ export default { <div class="project-feature-setting-group gl-pl-7 gl-sm-pl-5"> <project-setting-row ref="merge-request-settings" - :label="s__('ProjectSettings|Merge requests')" + :label="$options.i18n.mergeRequestsLabel" :help-text="s__('ProjectSettings|Submit changes to be merged upstream.')" > <project-feature-setting v-model="mergeRequestsAccessLevel" + :label="$options.i18n.mergeRequestsLabel" :options="repoFeatureAccessLevelOptions" :disabled-input="!repositoryEnabled" name="project[project_feature_attributes][merge_requests_access_level]" @@ -471,33 +491,22 @@ export default { </project-setting-row> <project-setting-row ref="fork-settings" - :label="s__('ProjectSettings|Forks')" + :label="$options.i18n.forksLabel" :help-text="s__('ProjectSettings|Users can copy the repository to a new project.')" > <project-feature-setting v-model="forkingAccessLevel" + :label="$options.i18n.forksLabel" :options="featureAccessLevelOptions" :disabled-input="!repositoryEnabled" name="project[project_feature_attributes][forking_access_level]" /> </project-setting-row> <project-setting-row - ref="pipeline-settings" - :label="s__('ProjectSettings|Pipelines')" - :help-text="s__('ProjectSettings|Build, test, and deploy your changes.')" - > - <project-feature-setting - v-model="buildsAccessLevel" - :options="repoFeatureAccessLevelOptions" - :disabled-input="!repositoryEnabled" - name="project[project_feature_attributes][builds_access_level]" - /> - </project-setting-row> - <project-setting-row v-if="registryAvailable" ref="container-registry-settings" :help-path="registryHelpPath" - :label="s__('ProjectSettings|Container registry')" + :label="$options.i18n.containerRegistryLabel" :help-text=" s__('ProjectSettings|Every project can have its own space to store its Docker images') " @@ -513,6 +522,8 @@ export default { v-model="containerRegistryEnabled" class="gl-my-2" :disabled="!repositoryEnabled" + :label="$options.i18n.containerRegistryLabel" + label-position="hidden" name="project[container_registry_enabled]" /> </project-setting-row> @@ -520,7 +531,7 @@ export default { v-if="lfsAvailable" ref="git-lfs-settings" :help-path="lfsHelpPath" - :label="s__('ProjectSettings|Git Large File Storage (LFS)')" + :label="$options.i18n.lfsLabel" :help-text=" s__('ProjectSettings|Manages large files such as audio, video, and graphics files.') " @@ -529,6 +540,8 @@ export default { v-model="lfsEnabled" class="gl-my-2" :disabled="!repositoryEnabled" + :label="$options.i18n.lfsLabel" + label-position="hidden" name="project[lfs_enabled]" /> <p v-if="!lfsEnabled && lfsObjectsExist"> @@ -553,7 +566,7 @@ export default { v-if="packagesAvailable" ref="package-settings" :help-path="packagesHelpPath" - :label="s__('ProjectSettings|Packages')" + :label="$options.i18n.packagesLabel" :help-text=" s__('ProjectSettings|Every project can have its own space to store its packages.') " @@ -562,17 +575,33 @@ export default { v-model="packagesEnabled" class="gl-my-2" :disabled="!repositoryEnabled" + :label="$options.i18n.packagesLabel" + label-position="hidden" name="project[packages_enabled]" /> </project-setting-row> </div> <project-setting-row + ref="pipeline-settings" + :label="$options.i18n.ciCdLabel" + :help-text="s__('ProjectSettings|Build, test, and deploy your changes.')" + > + <project-feature-setting + v-model="buildsAccessLevel" + :label="$options.i18n.ciCdLabel" + :options="repoFeatureAccessLevelOptions" + :disabled-input="!repositoryEnabled" + name="project[project_feature_attributes][builds_access_level]" + /> + </project-setting-row> + <project-setting-row ref="analytics-settings" - :label="s__('ProjectSettings|Analytics')" + :label="$options.i18n.analyticsLabel" :help-text="s__('ProjectSettings|View project analytics.')" > <project-feature-setting v-model="analyticsAccessLevel" + :label="$options.i18n.analyticsLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][analytics_access_level]" /> @@ -580,43 +609,47 @@ export default { <project-setting-row v-if="requirementsAvailable" ref="requirements-settings" - :label="s__('ProjectSettings|Requirements')" + :label="$options.i18n.requirementsLabel" :help-text="s__('ProjectSettings|Requirements management system.')" > <project-feature-setting v-model="requirementsAccessLevel" + :label="$options.i18n.requirementsLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][requirements_access_level]" /> </project-setting-row> <project-setting-row - :label="s__('ProjectSettings|Security & Compliance')" + :label="$options.i18n.securityAndComplianceLabel" :help-text="s__('ProjectSettings|Security & Compliance for this project')" > <project-feature-setting v-model="securityAndComplianceAccessLevel" + :label="$options.i18n.securityAndComplianceLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][security_and_compliance_access_level]" /> </project-setting-row> <project-setting-row ref="wiki-settings" - :label="s__('ProjectSettings|Wiki')" + :label="$options.i18n.wikiLabel" :help-text="s__('ProjectSettings|Pages for project documentation.')" > <project-feature-setting v-model="wikiAccessLevel" + :label="$options.i18n.wikiLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][wiki_access_level]" /> </project-setting-row> <project-setting-row ref="snippet-settings" - :label="s__('ProjectSettings|Snippets')" + :label="$options.i18n.snippetsLabel" :help-text="s__('ProjectSettings|Share code with others outside the project.')" > <project-feature-setting v-model="snippetsAccessLevel" + :label="$options.i18n.snippetsLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][snippets_access_level]" /> @@ -625,26 +658,28 @@ export default { v-if="pagesAvailable && pagesAccessControlEnabled" ref="pages-settings" :help-path="pagesHelpPath" - :label="s__('ProjectSettings|Pages')" + :label="$options.i18n.pagesLabel" :help-text=" s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab.') " > <project-feature-setting v-model="pagesAccessLevel" + :label="$options.i18n.pagesLabel" :options="pagesFeatureAccessLevelOptions" name="project[project_feature_attributes][pages_access_level]" /> </project-setting-row> <project-setting-row ref="operations-settings" - :label="s__('ProjectSettings|Operations')" + :label="$options.i18n.operationsLabel" :help-text=" s__('ProjectSettings|Configure your project resources and monitor their health.') " > <project-feature-setting v-model="operationsAccessLevel" + :label="$options.i18n.operationsLabel" :options="featureAccessLevelOptions" name="project[project_feature_attributes][operations_access_level]" /> diff --git a/app/assets/javascripts/pages/projects/tags/index/index.js b/app/assets/javascripts/pages/projects/tags/index/index.js index 98560c1193b..9e48dd9e463 100644 --- a/app/assets/javascripts/pages/projects/tags/index/index.js +++ b/app/assets/javascripts/pages/projects/tags/index/index.js @@ -1,3 +1,4 @@ +import TagSortDropdown from '~/tags'; import { initRemoveTag } from '../remove_tag'; initRemoveTag({ @@ -5,3 +6,4 @@ initRemoveTag({ document.querySelector(`[data-path="${path}"]`).closest('.js-tag-list').remove(); }, }); +TagSortDropdown(); |