diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared')
44 files changed, 260 insertions, 94 deletions
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue index 6db18afe51c..c6c22f9c61f 100644 --- a/app/assets/javascripts/vue_shared/components/actions_button.vue +++ b/app/assets/javascripts/vue_shared/components/actions_button.vue @@ -77,7 +77,7 @@ export default { <template v-for="(action, index) in actions"> <gl-dropdown-item :key="action.key" - :is-check-item="true" + is-check-item :is-checked="action.key === selectedAction.key" :secondary-text="action.secondaryText" :data-qa-selector="`${action.key}_menu_item`" diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue index 5de71c35be9..84bd6bca601 100644 --- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue +++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue @@ -1,5 +1,6 @@ <script> import { GlTooltipDirective } from '@gitlab/ui'; +import { visitUrl } from '~/lib/utils/url_utility'; import CiIcon from './ci_icon.vue'; /** * Renders CI Badge link with CI icon and status text based on @@ -57,13 +58,28 @@ export default { }, cssClass() { const className = this.status.group; - return className ? `ci-status ci-${className} qa-status-badge` : 'ci-status qa-status-badge'; + return className ? `ci-status ci-${className}` : 'ci-status'; + }, + }, + methods: { + navigateToPipeline() { + visitUrl(this.detailsPath); + + // event used for tracking + this.$emit('ciStatusBadgeClick'); }, }, }; </script> <template> - <a v-gl-tooltip :href="detailsPath" :class="cssClass" :title="title"> + <a + v-gl-tooltip + :class="cssClass" + class="gl-cursor-pointer" + :title="title" + data-qa-selector="status_badge_link" + @click="navigateToPipeline" + > <ci-icon :status="status" :css-classes="iconClasses" /> <template v-if="showText"> diff --git a/app/assets/javascripts/vue_shared/components/code_block.stories.js b/app/assets/javascripts/vue_shared/components/code_block.stories.js new file mode 100644 index 00000000000..e02a346c1de --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/code_block.stories.js @@ -0,0 +1,18 @@ +import CodeBlock from './code_block.vue'; + +export default { + component: CodeBlock, + title: 'vue_shared/code_block', +}; + +const Template = (args, { argTypes }) => ({ + components: { CodeBlock }, + props: Object.keys(argTypes), + template: '<code-block v-bind="$props" />', +}); + +export const Default = Template.bind({}); +Default.args = { + // eslint-disable-next-line @gitlab/require-i18n-strings + code: `git commit -a "Message"\ngit push`, +}; diff --git a/app/assets/javascripts/vue_shared/components/code_block.vue b/app/assets/javascripts/vue_shared/components/code_block.vue index 9856f35c7f6..4a69845d3a4 100644 --- a/app/assets/javascripts/vue_shared/components/code_block.vue +++ b/app/assets/javascripts/vue_shared/components/code_block.vue @@ -4,7 +4,8 @@ export default { props: { code: { type: String, - required: true, + required: false, + default: '', }, maxHeight: { type: String, @@ -32,5 +33,5 @@ export default { class="code-block rounded code" :class="$options.userColorScheme" :style="styleObject" - ><code class="d-block">{{ code }}</code></pre> + ><slot><code class="d-block">{{ code }}</code></slot></pre> </template> diff --git a/app/assets/javascripts/vue_shared/components/code_block_highlighted.stories.js b/app/assets/javascripts/vue_shared/components/code_block_highlighted.stories.js new file mode 100644 index 00000000000..bf81a811d16 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/code_block_highlighted.stories.js @@ -0,0 +1,18 @@ +import CodeBlockHighlighted from './code_block_highlighted.vue'; + +export default { + component: CodeBlockHighlighted, + title: 'vue_shared/code_block_highlighted', +}; + +const Template = (args, { argTypes }) => ({ + components: { CodeBlockHighlighted }, + props: Object.keys(argTypes), + template: '<code-block-highlighted v-bind="$props" />', +}); + +export const Default = Template.bind({}); +Default.args = { + code: `const foo = 1;\nconsole.log(foo + ' yay')`, + language: 'javascript', +}; diff --git a/app/assets/javascripts/vue_shared/components/code_block_highlighted.vue b/app/assets/javascripts/vue_shared/components/code_block_highlighted.vue new file mode 100644 index 00000000000..65b08b608e8 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/code_block_highlighted.vue @@ -0,0 +1,72 @@ +<script> +import { GlSafeHtmlDirective } from '@gitlab/ui'; + +import languageLoader from '~/content_editor/services/highlight_js_language_loader'; +import CodeBlock from './code_block.vue'; + +export default { + name: 'CodeBlockHighlighted', + directives: { + SafeHtml: GlSafeHtmlDirective, + }, + components: { + CodeBlock, + }, + props: { + code: { + type: String, + required: true, + }, + language: { + type: String, + required: true, + }, + maxHeight: { + type: String, + required: false, + default: 'initial', + }, + }, + data() { + return { + hljs: null, + languageLoaded: false, + }; + }, + computed: { + highlighted() { + if (this.hljs && this.languageLoaded) { + return this.hljs.highlight(this.code, { language: this.language }).value; + } + + return this.code; + }, + }, + async mounted() { + this.hljs = await this.loadHighlightJS(); + if (this.language) { + await this.loadLanguage(); + } + }, + methods: { + async loadLanguage() { + try { + const { default: languageDefinition } = await languageLoader[this.language](); + + this.hljs.registerLanguage(this.language, languageDefinition); + this.languageLoaded = true; + } catch (e) { + this.$emit('error', e); + } + }, + loadHighlightJS() { + return import('highlight.js/lib/core'); + }, + }, +}; +</script> +<template> + <code-block :max-height="maxHeight" class="highlight"> + <span v-safe-html="highlighted"></span> + </code-block> +</template> diff --git a/app/assets/javascripts/vue_shared/components/color_select_dropdown/dropdown_contents_color_view.vue b/app/assets/javascripts/vue_shared/components/color_select_dropdown/dropdown_contents_color_view.vue index 91906388049..22f3c35b9c3 100644 --- a/app/assets/javascripts/vue_shared/components/color_select_dropdown/dropdown_contents_color_view.vue +++ b/app/assets/javascripts/vue_shared/components/color_select_dropdown/dropdown_contents_color_view.vue @@ -42,8 +42,8 @@ export default { v-for="color in colors" :key="color.color" :is-checked="isColorSelected(color)" - :is-check-centered="true" - :is-check-item="true" + is-check-centered + is-check-item @click.native.capture.stop="handleColorClick(color)" > <color-item :color="color.color" :title="color.title" /> diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js index 8481280f25f..7ecc309db52 100644 --- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js +++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js @@ -3,7 +3,7 @@ import ConfirmDanger from './confirm_danger.vue'; export default { component: ConfirmDanger, - title: 'vue_shared/components/modals/confirm_danger_modal', + title: 'vue_shared/modals/confirm_danger_modal', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js index aec67a18a05..38b1a587b34 100644 --- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js +++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js @@ -1,4 +1,4 @@ -import dateformat from 'dateformat'; +import dateformat from '~/lib/dateformat'; import { __ } from '~/locale'; /** diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js index eeed5e9dc3a..8256d953466 100644 --- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js +++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js @@ -5,7 +5,7 @@ import DropdownWidget from './dropdown_widget.vue'; export default { component: DropdownWidget, - title: 'vue_shared/components/dropdown/dropdown_widget/dropdown_widget', + title: 'vue_shared/dropdown/dropdown_widget/dropdown_widget', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue index 840911dc99c..faa50a50c69 100644 --- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue +++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue @@ -149,8 +149,8 @@ export default { v-for="option in presetOptions" :key="option.id" :is-checked="isSelected(option)" - :is-check-centered="true" - :is-check-item="true" + is-check-centered + is-check-item @click.native.capture.stop="selectOption(option)" > <slot name="preset-item" :item="option"> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js index 5d7f4ae2a01..ffe09634a3b 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js @@ -46,7 +46,7 @@ export const SortDirection = { export const FILTERED_SEARCH_LABELS = 'labels'; export const FILTERED_SEARCH_TERM = 'filtered-search-term'; -export const TOKEN_TITLE_ASSIGNEE = __('Assignee'); +export const TOKEN_TITLE_ASSIGNEE = s__('SearchToken|Assignee'); export const TOKEN_TITLE_AUTHOR = __('Author'); export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential'); export const TOKEN_TITLE_CONTACT = s__('Crm|Contact'); diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue index 33d507dad57..e311df6e66f 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue @@ -369,7 +369,7 @@ export default { <gl-dropdown-item v-for="sortBy in sortOptions" :key="sortBy.id" - :is-check-item="true" + is-check-item :is-checked="sortBy.id === selectedSortOption.id" @click="handleSortOptionClick(sortBy)" >{{ sortBy.title }}</gl-dropdown-item diff --git a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js index cdd7a074f34..377f1e7c136 100644 --- a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js +++ b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js @@ -2,7 +2,7 @@ import InputCopyToggleVisibility from './input_copy_toggle_visibility.vue'; export default { component: InputCopyToggleVisibility, - title: 'vue_shared/components/form/input_copy_toggle_visibility', + title: 'vue_shared/form/input_copy_toggle_visibility', }; const defaultProps = { diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue index 1d1b65aa1af..458dfe0ed23 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/header.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue @@ -182,7 +182,7 @@ export default { <div class="md-header"> <gl-tabs content-class="gl-display-none"> <gl-tab - title-link-class="gl-pt-3 gl-px-3 js-md-write-button" + title-link-class="gl-py-4 gl-px-3 js-md-write-button" :title="$options.i18n.writeTabTitle" :active="!previewMarkdown" data-testid="write-tab" @@ -190,7 +190,7 @@ export default { /> <gl-tab v-if="enablePreview" - title-link-class="gl-pt-3 gl-px-3 js-md-preview-button" + title-link-class="gl-py-4 gl-px-3 js-md-preview-button" :title="$options.i18n.previewTabTitle" :active="previewMarkdown" data-testid="preview-tab" @@ -201,7 +201,7 @@ export default { <div data-testid="md-header-toolbar" :class="{ 'gl-display-none!': previewMarkdown }" - class="md-header-toolbar gl-ml-auto gl-pb-3 gl-justify-content-center" + class="md-header-toolbar gl-ml-auto gl-py-2 gl-justify-content-center" > <template v-if="canSuggest"> <toolbar-button diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue index de3eda6b04f..9b81444fc04 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue @@ -163,6 +163,7 @@ export default { // resets the container HTML (replaces it with the updated noteHTML) // calls `renderSuggestions` once the updated noteHTML is added to the DOM + // eslint-disable-next-line no-unsanitized/property this.$refs.container.innerHTML = this.noteHtml; this.isRendered = false; this.renderSuggestions(); diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue index aa325862f06..b5640e12541 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue @@ -72,7 +72,7 @@ export default { </gl-sprintf> </template> </div> - <span v-if="canAttachFile" class="uploading-container"> + <span v-if="canAttachFile" class="uploading-container gl-line-height-32"> <span class="uploading-progress-container hide"> <gl-icon name="paperclip" /> <span class="attaching-file-message"></span> diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue index 3593ea16968..7e99f1b01b2 100644 --- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue @@ -29,7 +29,7 @@ import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_ import '~/behaviors/markdown/render_gfm'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; -import noteHeader from '~/notes/components/note_header.vue'; +import NoteHeader from '~/notes/components/note_header.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { spriteIcon } from '~/lib/utils/common_utils'; import TimelineEntryItem from './timeline_entry_item.vue'; @@ -43,7 +43,7 @@ export default { name: 'SystemNote', components: { GlIcon, - noteHeader, + NoteHeader, TimelineEntryItem, GlButton, GlSkeletonLoader, diff --git a/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js index e31446f4bb8..f16afc77164 100644 --- a/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js +++ b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js @@ -3,7 +3,7 @@ import PaginationBar from './pagination_bar.vue'; export default { component: PaginationBar, - title: 'vue_shared/components/pagination_bar/pagination_bar', + title: 'vue_shared/pagination_bar/pagination_bar', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/project_avatar.stories.js b/app/assets/javascripts/vue_shared/components/project_avatar.stories.js index 110c6c73bad..bfb30c74cb8 100644 --- a/app/assets/javascripts/vue_shared/components/project_avatar.stories.js +++ b/app/assets/javascripts/vue_shared/components/project_avatar.stories.js @@ -2,7 +2,7 @@ import ProjectAvatar from './project_avatar.vue'; export default { component: ProjectAvatar, - title: 'vue_shared/components/project_avatar', + title: 'vue_shared/project_avatar', }; const Template = (args, { argTypes }) => ({ @@ -13,8 +13,7 @@ const Template = (args, { argTypes }) => ({ export const Default = Template.bind({}); Default.args = { - projectAvatarUrl: - 'https://gitlab.com/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64', + projectAvatarUrl: 'https://gitlab.com/uploads/-/system/project/avatar/278964/project_avatar.png', projectName: 'GitLab', }; diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.stories.js b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.stories.js index 9700117a3da..4021e23a3f6 100644 --- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.stories.js +++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.stories.js @@ -2,7 +2,7 @@ import ProjectListItem from './project_list_item.vue'; export default { component: ProjectListItem, - title: 'vue_shared/components/project_selector/project_list_item', + title: 'vue_shared/project_selector/project_list_item', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/registry/persisted_dropdown_selection.vue b/app/assets/javascripts/vue_shared/components/registry/persisted_dropdown_selection.vue index 43a8e241d77..32d7cdad568 100644 --- a/app/assets/javascripts/vue_shared/components/registry/persisted_dropdown_selection.vue +++ b/app/assets/javascripts/vue_shared/components/registry/persisted_dropdown_selection.vue @@ -49,7 +49,7 @@ export default { v-for="option in parsedOptions" :key="option.value" :is-checked="option.selected" - :is-check-item="true" + is-check-item @click="setSelected(option.value)" > {{ option.label }} diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue index bfaf3b92c34..c5d3704ead9 100644 --- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue @@ -253,7 +253,7 @@ export default { <gl-dropdown-item v-for="architecture in architectures" :key="architecture.name" - :is-check-item="true" + is-check-item :is-checked="selectedArchitecture === architecture.name" data-testid="architecture-dropdown-item" @click="selectArchitecture(architecture.name)" diff --git a/app/assets/javascripts/vue_shared/components/settings/settings_block.stories.js b/app/assets/javascripts/vue_shared/components/settings/settings_block.stories.js index 5242743ad30..53e4a08e486 100644 --- a/app/assets/javascripts/vue_shared/components/settings/settings_block.stories.js +++ b/app/assets/javascripts/vue_shared/components/settings/settings_block.stories.js @@ -2,7 +2,7 @@ import SettingsBlock from './settings_block.vue'; export default { component: SettingsBlock, - title: 'vue_shared/components/settings/settings_block', + title: 'vue_shared/settings/settings_block', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue index dfa2ca2d20c..0f5560ff628 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue @@ -180,7 +180,7 @@ export default { <gl-dropdown-item v-for="project in projects" :key="project.id" - :is-check-item="true" + is-check-item :is-checked="isSelectedProject(project)" @click.stop.prevent="handleProjectSelect(project)" >{{ project.name_with_namespace }}</gl-dropdown-item diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue index f595e635f2c..8d3d4d5f86a 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue @@ -154,8 +154,8 @@ export default { v-for="(label, index) in visibleLabels" :key="label.id" :is-checked="isLabelSelected(label)" - :is-check-centered="true" - :is-check-item="true" + is-check-centered + is-check-item :active="shouldHighlightFirstItem && index === 0" active-class="is-focused" data-testid="labels-list" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue index aaddab43e2a..154a8e866d0 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue @@ -80,6 +80,7 @@ export default { v-if="!showDropdownContentsCreateView" ref="searchInput" :value="searchKey" + :placeholder="__('Search labels')" :disabled="labelsFetchInProgress" data-qa-selector="dropdown_input_field" data-testid="dropdown-input-field" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.stories.js b/app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.stories.js index 294e5bd9f90..8a2bab4cb9a 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.stories.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.stories.js @@ -4,7 +4,7 @@ import TodoButton from './todo_button.vue'; export default { component: TodoButton, - title: 'vue_shared/components/sidebar/todo_toggle/todo_button', + title: 'vue_shared/sidebar/todo_toggle/todo_button', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js index cc930d67fa4..30f57f506a6 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js +++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js @@ -81,6 +81,7 @@ export const ROUGE_TO_HLJS_LANGUAGE_MAP = { protobuf: 'protobuf', puppet: 'puppet', python: 'python', + python3: 'python', q: 'q', qml: 'qml', r: 'r', diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js index 5be92af5b55..8b52df83fdf 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js +++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js @@ -3,6 +3,8 @@ import { HLJS_COMMENT_SELECTOR } from '../constants'; const createWrapper = (content) => { const span = document.createElement('span'); span.className = HLJS_COMMENT_SELECTOR; + + // eslint-disable-next-line no-unsanitized/property span.innerHTML = content; return span.outerHTML; }; diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue index f471db24889..9c6c12eac7d 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue @@ -42,7 +42,7 @@ export default { return { languageDefinition: null, content: this.blob.rawTextBlob, - language: ROUGE_TO_HLJS_LANGUAGE_MAP[this.blob.language], + language: ROUGE_TO_HLJS_LANGUAGE_MAP[this.blob.language?.toLowerCase()], hljs: null, firstChunk: null, chunks: {}, @@ -62,7 +62,7 @@ export default { const supportedLanguages = Object.keys(languageLoader); return ( !supportedLanguages.includes(this.language) && - !supportedLanguages.includes(this.blob.language) + !supportedLanguages.includes(this.blob.language?.toLowerCase()) ); }, }, diff --git a/app/assets/javascripts/vue_shared/components/split_button.vue b/app/assets/javascripts/vue_shared/components/split_button.vue index 994fa68fb1a..c0aef42b0f2 100644 --- a/app/assets/javascripts/vue_shared/components/split_button.vue +++ b/app/assets/javascripts/vue_shared/components/split_button.vue @@ -68,7 +68,7 @@ export default { <template v-for="(item, itemIndex) in actionItems"> <gl-dropdown-item :key="item.eventName" - :is-check-item="true" + is-check-item :is-checked="selectedItem === item" @click="changeSelectedItem(item)" > diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue index 42334d80eec..ce65266cbc9 100644 --- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue +++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue @@ -72,7 +72,7 @@ export default { v-for="timezone in filteredResults" :key="timezone.formattedTimezone" :is-checked="isSelected(timezone)" - :is-check-item="true" + is-check-item @click="selectTimezone(timezone)" > {{ timezone.formattedTimezone }} diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js index f27901a30a9..e621442e601 100644 --- a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js +++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js @@ -5,7 +5,7 @@ const defaultWidth = '250px'; export default { component: TooltipOnTruncate, - title: 'vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue', + title: 'vue_shared/tooltip_on_truncate/tooltip_on_truncate.vue', }; const createStory = ({ ...options }) => { diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue index 424cab20c7e..a001b6bdf24 100644 --- a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue +++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue @@ -149,7 +149,7 @@ export default { > <slot> <button - class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4" + class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0" type="button" @click="openFileUpload" > diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue index cd610314292..6bd66981860 100644 --- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue +++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue @@ -90,9 +90,8 @@ export default { </script> <template> - <span> + <span ref="userAvatar"> <gl-avatar - ref="userAvatar" :class="{ lazy: lazy, [cssClasses]: true, @@ -108,7 +107,7 @@ export default { tooltipText || $slots.default /* eslint-disable-line @gitlab/vue-prefer-dollar-scopedslots */ " - :target="() => $refs.userAvatar.$el" + :target="() => $refs.userAvatar" :placement="tooltipPlacement" boundary="window" > diff --git a/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.stories.js b/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.stories.js index d2030c14029..1f0f4cde234 100644 --- a/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.stories.js +++ b/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.stories.js @@ -5,7 +5,7 @@ import UserDeletionObstaclesList from './user_deletion_obstacles_list.vue'; export default { component: UserDeletionObstaclesList, - title: 'vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list', + title: 'vue_shared/user_deletion_obstacles/user_deletion_obstacles_list', }; const Template = (args, { argTypes }) => ({ diff --git a/app/assets/javascripts/vue_shared/components/user_popover/constants.js b/app/assets/javascripts/vue_shared/components/user_popover/constants.js index 1d49aefd297..bcbe72b4b4f 100644 --- a/app/assets/javascripts/vue_shared/components/user_popover/constants.js +++ b/app/assets/javascripts/vue_shared/components/user_popover/constants.js @@ -1 +1,14 @@ +import { __ } from '~/locale'; + export const USER_POPOVER_DELAY = 200; +export const I18N_ERROR_FOLLOW = __( + 'An error occurred while trying to follow this user, please try again.', +); +export const I18N_ERROR_UNFOLLOW = __( + 'An error occurred while trying to unfollow this user, please try again.', +); +export const I18N_USER_BLOCKED = __('User is blocked'); +export const I18N_USER_BUSY = __('Busy'); +export const I18N_USER_LEARN = __('Learn more about %{name}'); +export const I18N_USER_FOLLOW = __('Follow'); +export const I18N_USER_UNFOLLOW = __('Unfollow'); diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue index 2b9804796ae..4b39a8e45bb 100644 --- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue +++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue @@ -9,23 +9,31 @@ import { GlButton, GlAvatarLabeled, } from '@gitlab/ui'; -import { __ } from '~/locale'; import { glEmojiTag } from '~/emoji'; import createFlash from '~/flash'; import { followUser, unfollowUser } from '~/rest_api'; import { isUserBusy } from '~/set_status_modal/utils'; import Tracking from '~/tracking'; -import { USER_POPOVER_DELAY } from './constants'; +import { + I18N_ERROR_FOLLOW, + I18N_ERROR_UNFOLLOW, + I18N_USER_BLOCKED, + I18N_USER_BUSY, + I18N_USER_LEARN, + I18N_USER_FOLLOW, + I18N_USER_UNFOLLOW, + USER_POPOVER_DELAY, +} from './constants'; const MAX_SKELETON_LINES = 4; export default { name: 'UserPopover', maxSkeletonLines: MAX_SKELETON_LINES, + I18N_USER_BLOCKED, + I18N_USER_BUSY, + I18N_USER_LEARN, USER_POPOVER_DELAY, - i18n: { - busy: __('Busy'), - }, components: { GlIcon, GlLink, @@ -94,7 +102,7 @@ export default { toggleFollowButtonText() { if (this.toggleFollowLoading) return null; - return this.user?.isFollowed ? __('Unfollow') : __('Follow'); + return this.user?.isFollowed ? I18N_USER_UNFOLLOW : I18N_USER_FOLLOW; }, toggleFollowButtonVariant() { return this.user?.isFollowed ? 'default' : 'confirm'; @@ -102,6 +110,9 @@ export default { hasPronouns() { return Boolean(this.user?.pronouns?.trim()); }, + isBlocked() { + return this.user?.state === 'blocked'; + }, isBusy() { return isUserBusy(this.availabilityStatus); }, @@ -129,7 +140,7 @@ export default { this.$emit('follow'); } catch (error) { createFlash({ - message: __('An error occurred while trying to follow this user, please try again.'), + message: I18N_ERROR_FOLLOW, error, captureError: true, }); @@ -149,7 +160,7 @@ export default { this.$emit('unfollow'); } catch (error) { createFlash({ - message: __('An error occurred while trying to unfollow this user, please try again.'), + message: I18N_ERROR_UNFOLLOW, error, captureError: true, }); @@ -189,16 +200,21 @@ export default { :label="user.name" :sub-label="username" > - <gl-button - v-if="shouldRenderToggleFollowButton" - class="gl-mt-3 gl-align-self-start" - :variant="toggleFollowButtonVariant" - :loading="toggleFollowLoading" - size="small" - data-testid="toggle-follow-button" - @click="toggleFollow" - >{{ toggleFollowButtonText }}</gl-button - > + <template v-if="isBlocked"> + <span class="gl-mt-4 gl-font-style-italic">{{ $options.I18N_USER_BLOCKED }}</span> + </template> + <template v-else> + <gl-button + v-if="shouldRenderToggleFollowButton" + class="gl-mt-3 gl-align-self-start" + :variant="toggleFollowButtonVariant" + :loading="toggleFollowLoading" + size="small" + data-testid="toggle-follow-button" + @click="toggleFollow" + >{{ toggleFollowButtonText }}</gl-button + > + </template> <template #meta> <span @@ -208,7 +224,7 @@ export default { >({{ user.pronouns }})</span > <span v-if="isBusy" class="gl-text-gray-500 gl-font-sm gl-font-weight-normal gl-p-1" - >({{ $options.i18n.busy }})</span + >({{ $options.I18N_USER_BUSY }})</span > </template> </gl-avatar-labeled> @@ -223,39 +239,41 @@ export default { /> </template> <template v-else> - <div class="gl-text-gray-500"> - <div v-if="user.bio" class="gl-display-flex gl-mb-2"> - <gl-icon name="profile" class="gl-flex-shrink-0" /> - <span ref="bio" class="gl-ml-2">{{ user.bio }}</span> + <template v-if="!isBlocked"> + <div class="gl-text-gray-500"> + <div v-if="user.bio" class="gl-display-flex gl-mb-2"> + <gl-icon name="profile" class="gl-flex-shrink-0" /> + <span ref="bio" class="gl-ml-2">{{ user.bio }}</span> + </div> + <div v-if="user.workInformation" class="gl-display-flex gl-mb-2"> + <gl-icon name="work" class="gl-flex-shrink-0" /> + <span ref="workInformation" class="gl-ml-2">{{ user.workInformation }}</span> + </div> + <div v-if="user.location" class="gl-display-flex gl-mb-2"> + <gl-icon name="location" class="gl-flex-shrink-0" /> + <span class="gl-ml-2">{{ user.location }}</span> + </div> + <div + v-if="user.localTime && !user.bot" + class="gl-display-flex gl-mb-2" + data-testid="user-popover-local-time" + > + <gl-icon name="clock" class="gl-flex-shrink-0" /> + <span class="gl-ml-2">{{ user.localTime }}</span> + </div> </div> - <div v-if="user.workInformation" class="gl-display-flex gl-mb-2"> - <gl-icon name="work" class="gl-flex-shrink-0" /> - <span ref="workInformation" class="gl-ml-2">{{ user.workInformation }}</span> + <div v-if="statusHtml" class="gl-mb-2" data-testid="user-popover-status"> + <span v-safe-html:[$options.safeHtmlConfig]="statusHtml"></span> </div> - <div v-if="user.location" class="gl-display-flex gl-mb-2"> - <gl-icon name="location" class="gl-flex-shrink-0" /> - <span class="gl-ml-2">{{ user.location }}</span> + <div v-if="user.bot && user.websiteUrl" class="gl-text-blue-500"> + <gl-icon name="question" /> + <gl-link data-testid="user-popover-bot-docs-link" :href="user.websiteUrl"> + <gl-sprintf :message="$options.I18N_USER_LEARN"> + <template #name>{{ user.name }}</template> + </gl-sprintf> + </gl-link> </div> - <div - v-if="user.localTime && !user.bot" - class="gl-display-flex gl-mb-2" - data-testid="user-popover-local-time" - > - <gl-icon name="clock" class="gl-flex-shrink-0" /> - <span class="gl-ml-2">{{ user.localTime }}</span> - </div> - </div> - <div v-if="statusHtml" class="gl-mb-2" data-testid="user-popover-status"> - <span v-safe-html:[$options.safeHtmlConfig]="statusHtml"></span> - </div> - <div v-if="user.bot && user.websiteUrl" class="gl-text-blue-500"> - <gl-icon name="question" /> - <gl-link data-testid="user-popover-bot-docs-link" :href="user.websiteUrl"> - <gl-sprintf :message="__('Learn more about %{username}')"> - <template #username>{{ user.name }}</template> - </gl-sprintf> - </gl-link> - </div> + </template> </template> </div> </gl-popover> diff --git a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue index 43a590c2367..3180bd0d283 100644 --- a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue +++ b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue @@ -320,7 +320,7 @@ export default { <gl-dropdown-item v-if="isSearchEmpty" :is-checked="selectedIsEmpty" - :is-check-centered="true" + is-check-centered data-testid="unassign" @click.native.capture.stop="$emit('input', [])" > diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue index 38083327593..7e735f358eb 100644 --- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue +++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue @@ -232,7 +232,11 @@ export default { </span> </div> <div class="issuable-info"> - <work-item-type-icon v-if="showWorkItemTypeIcon" :work-item-type="issuable.type" /> + <work-item-type-icon + v-if="showWorkItemTypeIcon" + :work-item-type="issuable.type" + show-tooltip-on-hover + /> <slot v-if="hasSlotContents('reference')" name="reference"></slot> <span v-else data-testid="issuable-reference" class="issuable-reference"> {{ reference }} diff --git a/app/assets/javascripts/vue_shared/new_namespace/components/legacy_container.vue b/app/assets/javascripts/vue_shared/new_namespace/components/legacy_container.vue index d2fc2c66924..e42720bf1db 100644 --- a/app/assets/javascripts/vue_shared/new_namespace/components/legacy_container.vue +++ b/app/assets/javascripts/vue_shared/new_namespace/components/legacy_container.vue @@ -10,6 +10,7 @@ export default { mounted() { const legacyEntry = document.querySelector(this.selector); if (legacyEntry.tagName === 'TEMPLATE') { + // eslint-disable-next-line no-unsanitized/property this.$el.innerHTML = legacyEntry.innerHTML; } else { this.source = legacyEntry.parentNode; diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql index 2e80db30e9a..6a83669d206 100644 --- a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql +++ b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql @@ -14,6 +14,7 @@ query securityReportDownloadPaths( id name artifacts { + # eslint-disable-next-line @graphql-eslint/require-id-when-available nodes { downloadPath fileType diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql index e4f0c392b91..1f1e56a5876 100644 --- a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql +++ b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql @@ -4,6 +4,7 @@ query getPipelineCorpuses($projectPath: ID!, $iid: ID, $reportTypes: [SecurityRe project(fullPath: $projectPath) { id pipeline(iid: $iid) { + # eslint-disable-next-line @graphql-eslint/require-id-when-available ...JobArtifacts } } |