summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components')
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_modal.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/deployment_instance.vue91
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue121
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_container.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/editor_lite.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js11
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js69
-rw-r--r--app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue30
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/navigation_tabs.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/ordered_layout.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue57
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/metadata_item.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/title_area.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js16
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/select2_select.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/split_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/tabs/tabs.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/timezone_dropdown.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue2
74 files changed, 463 insertions, 379 deletions
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
index cb4c5f20377..2dc2c27f7ea 100644
--- a/app/assets/javascripts/vue_shared/components/actions_button.vue
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -43,7 +43,7 @@ export default {
return this.actions.length > 1;
},
selectedAction() {
- return this.actions.find(x => x.key === this.selectedKey) || this.actions[0];
+ return this.actions.find((x) => x.key === this.selectedKey) || this.actions[0];
},
},
methods: {
diff --git a/app/assets/javascripts/vue_shared/components/alert_details_table.vue b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
index 3e2b4cd35ab..655b867574d 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -49,7 +49,8 @@ export default {
label: s__('AlertManagement|Key'),
thClass,
tdClass,
- formatter: string => capitalizeFirstCharacter(convertToSentenceCase(splitCamelCase(string))),
+ formatter: (string) =>
+ capitalizeFirstCharacter(convertToSentenceCase(splitCamelCase(string))),
},
{
key: 'value',
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 9a6433963bc..c1da2b8c305 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -48,7 +48,7 @@ export default {
groupedAwards() {
const { thumbsup, thumbsdown, ...rest } = {
...this.groupedDefaultAwards,
- ...groupBy(this.awards, x => x.name),
+ ...groupBy(this.awards, (x) => x.name),
};
return [
@@ -73,7 +73,7 @@ export default {
return false;
}
- return awardList.some(award => award.user.id === this.currentUserId);
+ return awardList.some((award) => award.user.id === this.currentUserId);
},
createAwardList(name, list) {
return {
@@ -95,11 +95,11 @@ export default {
// Filter myself from list if I am awarded.
if (hasReactionByCurrentUser) {
- awardList = awardList.filter(award => award.user.id !== this.currentUserId);
+ awardList = awardList.filter((award) => award.user.id !== this.currentUserId);
}
// Get only 9-10 usernames to show in tooltip text.
- const namesToShow = awardList.slice(0, TOOLTIP_NAME_COUNT).map(award => award.user.name);
+ const namesToShow = awardList.slice(0, TOOLTIP_NAME_COUNT).map((award) => award.user.name);
// Get the remaining list to use in `and x more` text.
const remainingAwardList = awardList.slice(TOOLTIP_NAME_COUNT, awardList.length);
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
index f28e49df56e..14e99977a85 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -79,6 +79,8 @@ export default {
:title="tooltipTitle"
:class="{ 'ml-auto': isCentered }"
class="file-changed-icon d-inline-block"
+ data-qa-selector="changed_file_icon_content"
+ :data-qa-title="tooltipTitle"
>
<gl-icon v-if="showIcon" :name="changedIcon" :size="size" :class="changedIconClass" />
</span>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index e01a651806d..deca934e283 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -54,7 +54,7 @@ export default {
type: Object,
required: false,
default: undefined,
- validator: ref =>
+ validator: (ref) =>
ref === undefined || (Number.isFinite(ref.iid) && isString(ref.path) && !isEmpty(ref.path)),
},
@@ -107,7 +107,7 @@ export default {
},
computed: {
/**
- * Determines if we shoud render the ref info section based
+ * Determines if we should render the ref info section based
*/
shouldShowRefInfo() {
return this.showRefInfo && (this.commitRef || this.mergeRequestRef);
diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
index 96f800511d2..7c1d3772acd 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
@@ -30,8 +30,8 @@ export default {
};
},
mounted() {
- document.querySelectorAll(this.selector).forEach(button => {
- button.addEventListener('click', e => {
+ document.querySelectorAll(this.selector).forEach((button) => {
+ button.addEventListener('click', (e) => {
e.preventDefault();
this.path = button.dataset.path;
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
index 5ac30424f98..9ff35132ac9 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
@@ -11,7 +11,7 @@ export default {
},
props: {
content: {
- type: String,
+ type: [String, ArrayBuffer],
default: '',
required: false,
},
@@ -54,7 +54,7 @@ export default {
</script>
<template>
- <div class="preview-container">
+ <div class="preview-container" data-qa-selector="preview_container">
<image-viewer v-if="type === 'image'" :path="path" :file-size="fileSize" />
<markdown-viewer
v-if="type === 'markdown'"
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
index 8d55701f499..af85a2fda06 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
@@ -39,11 +39,16 @@ export default {
<div class="file-content">
<p class="gl-mt-3 file-info">
{{ fileName }}
- <template v-if="fileSize > 0">
- ({{ fileSizeReadable }})
- </template>
+ <template v-if="fileSize > 0"> ({{ fileSizeReadable }}) </template>
</p>
- <a :href="path" class="btn btn-default" rel="nofollow" :download="fileName" target="_blank">
+ <a
+ :href="path"
+ class="btn btn-default"
+ rel="nofollow"
+ :download="fileName"
+ target="_blank"
+ data-qa-selector="download_button"
+ >
<gl-icon :size="16" name="download" class="float-left gl-mr-3" />
{{ __('Download') }}
</a>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
index eb7e24734ce..9ece6a52805 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
@@ -82,7 +82,7 @@ export default {
</script>
<template>
- <div data-testid="image-viewer">
+ <div data-testid="image-viewer" data-qa-selector="image_viewer_container">
<div :class="innerCssClasses" class="position-relative">
<img ref="contentImg" :src="path" @load="onImgLoad" />
<slot
@@ -95,9 +95,7 @@ export default {
<template v-if="hasFileSize">
{{ fileSizeReadable }}
</template>
- <template v-if="hasFileSize && hasDimensions">
- |
- </template>
+ <template v-if="hasFileSize && hasDimensions"> | </template>
<template v-if="hasDimensions">
<strong>{{ s__('ImageViewerDimensions|W') }}</strong
>: {{ width }} | <strong>{{ s__('ImageViewerDimensions|H') }}</strong
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index 67be76604a3..24386c90954 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -111,6 +111,6 @@ export default {
<template>
<div ref="markdownPreview" class="md-previewer" data-testid="md-previewer">
<gl-skeleton-loading v-if="isLoading" />
- <div v-else class="md" v-html="previewContent"></div>
+ <div v-else class="md gl-ml-auto gl-mr-auto" v-html="previewContent"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
index 79cdf308ac5..d0c2672b162 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
@@ -202,7 +202,7 @@ export default {
<template>
<tooltip-on-truncate
:title="timeWindowText"
- :truncate-target="elem => elem.querySelector('.gl-dropdown-toggle-text')"
+ :truncate-target="(elem) => elem.querySelector('.gl-dropdown-toggle-text')"
placement="top"
class="d-inline-block"
>
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
index 32a24844d71..39c1caf928e 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
@@ -20,12 +20,12 @@ export default {
state: {
default: null,
required: true,
- validator: prop => typeof prop === 'boolean' || prop === null,
+ validator: (prop) => typeof prop === 'boolean' || prop === null,
},
value: {
default: null,
required: false,
- validator: prop => typeof prop === 'string' || prop === null,
+ validator: (prop) => typeof prop === 'string' || prop === null,
},
label: {
type: String,
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 aaadc9766db..aec67a18a05 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
@@ -25,7 +25,7 @@ export const defaultTimeRanges = [
},
];
-export const defaultTimeRange = defaultTimeRanges.find(tr => tr.default);
+export const defaultTimeRange = defaultTimeRanges.find((tr) => tr.default);
export const dateFormats = {
/**
@@ -49,7 +49,7 @@ export const dateFormats = {
* @param {string} value - Value as typed by the user
* @returns true if the value can be parsed as a valid date, false otherwise
*/
-export const isValidInputString = value => {
+export const isValidInputString = (value) => {
try {
// dateformat throws error that can be caught.
// This is better than using `new Date()`
diff --git a/app/assets/javascripts/vue_shared/components/deployment_instance.vue b/app/assets/javascripts/vue_shared/components/deployment_instance.vue
new file mode 100644
index 00000000000..41b783aa011
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/deployment_instance.vue
@@ -0,0 +1,91 @@
+<script>
+/**
+ * An instance in deploy board is represented by a square in this mockup:
+ * https://gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png
+ *
+ * Each instance has a state and a tooltip.
+ * The state needs to be represented in different colors,
+ * see more information about this in
+ * https://gitlab.com/gitlab-org/gitlab/uploads/f1f00df6293d30f241dbeaa876a1e939/Screen_Shot_2019-11-26_at_3.35.43_PM.png
+ *
+ * An instance can represent a normal deploy or a canary deploy. In the latter we need to provide
+ * this information in the tooltip and the colors.
+ * Mockup is https://gitlab.com/gitlab-org/gitlab/issues/35570
+ */
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+
+ props: {
+ /**
+ * Represents the status of the pod. Each state is represented with a different
+ * color.
+ * It should be one of the following:
+ * succeeded || running || failed || pending || unknown
+ */
+ status: {
+ type: String,
+ required: true,
+ default: 'succeeded',
+ },
+
+ tooltipText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+
+ stable: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+
+ podName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+
+ logsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+
+ computed: {
+ isLink() {
+ return this.logsPath !== '' && this.podName !== '';
+ },
+
+ cssClass() {
+ return {
+ [`deployment-instance-${this.status}`]: true,
+ 'deployment-instance-canary': !this.stable,
+ link: this.isLink,
+ };
+ },
+
+ computedLogPath() {
+ return this.isLink ? mergeUrlParams({ pod_name: this.podName }, this.logsPath) : null;
+ },
+ },
+};
+</script>
+<template>
+ <gl-link
+ v-gl-tooltip
+ :class="cssClass"
+ :title="tooltipText"
+ :href="computedLogPath"
+ class="deployment-instance d-flex justify-content-center align-items-center"
+ />
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue
deleted file mode 100644
index c4bce860ae4..00000000000
--- a/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue
+++ /dev/null
@@ -1,121 +0,0 @@
-<script>
-import $ from 'jquery';
-import { GlButton } from '@gitlab/ui';
-
-const buttonVariants = ['danger', 'primary', 'success', 'warning'];
-const sizeVariants = ['sm', 'md', 'lg', 'xl'];
-
-export default {
- name: 'DeprecatedModal2', // use GlModal instead
-
- components: {
- GlButton,
- },
- props: {
- id: {
- type: String,
- required: false,
- default: null,
- },
- modalSize: {
- type: String,
- required: false,
- default: 'md',
- validator: value => sizeVariants.includes(value),
- },
- headerTitleText: {
- type: String,
- required: false,
- default: '',
- },
- footerPrimaryButtonVariant: {
- type: String,
- required: false,
- default: 'primary',
- validator: value => buttonVariants.includes(value),
- },
- footerPrimaryButtonText: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- modalSizeClass() {
- return this.modalSize === 'md' ? '' : `modal-${this.modalSize}`;
- },
- },
- mounted() {
- $(this.$el)
- .on('shown.bs.modal', this.opened)
- .on('hidden.bs.modal', this.closed);
- },
- beforeDestroy() {
- $(this.$el)
- .off('shown.bs.modal', this.opened)
- .off('hidden.bs.modal', this.closed);
- },
- methods: {
- emitCancel(event) {
- this.$emit('cancel', event);
- },
- emitSubmit(event) {
- this.$emit('submit', event);
- },
- opened() {
- this.$emit('open');
- },
- closed() {
- this.$emit('closed');
- },
- },
-};
-</script>
-
-<template>
- <div :id="id" class="modal fade" tabindex="-1" role="dialog">
- <div :class="modalSizeClass" class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header gl-pr-4">
- <slot name="header">
- <h4 class="modal-title">
- <slot name="title"> {{ headerTitleText }} </slot>
- </h4>
- <gl-button
- :aria-label="s__('Modal|Close')"
- variant="default"
- category="tertiary"
- size="small"
- icon="close"
- class="js-modal-close-action"
- data-dismiss="modal"
- @click="emitCancel($event)"
- />
- </slot>
- </div>
-
- <div class="modal-body"><slot></slot></div>
-
- <div class="modal-footer">
- <slot name="footer">
- <gl-button
- class="js-modal-cancel-action qa-modal-cancel-button"
- data-dismiss="modal"
- @click="emitCancel($event)"
- >
- {{ s__('Modal|Cancel') }}
- </gl-button>
- <gl-button
- :class="`btn-${footerPrimaryButtonVariant}`"
- class="js-modal-primary-action qa-modal-primary-button"
- data-dismiss="modal"
- @click="emitSubmit($event)"
- >
- {{ footerPrimaryButtonText }}
- </gl-button>
- </slot>
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_container.vue b/app/assets/javascripts/vue_shared/components/dismissible_container.vue
index 6d5fd065751..2eaf833a6be 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_container.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_container.vue
@@ -22,7 +22,7 @@ export default {
.post(this.path, {
feature_name: this.featureId,
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line @gitlab/require-i18n-strings, no-console
console.error('Failed to dismiss message.', e);
});
diff --git a/app/assets/javascripts/vue_shared/components/editor_lite.vue b/app/assets/javascripts/vue_shared/components/editor_lite.vue
index cfe3ce0a11c..7218b84cf8a 100644
--- a/app/assets/javascripts/vue_shared/components/editor_lite.vue
+++ b/app/assets/javascripts/vue_shared/components/editor_lite.vue
@@ -84,6 +84,9 @@ export default {
onFileChange() {
this.$emit('input', this.editor.getValue());
},
+ getEditor() {
+ return this.editor;
+ },
},
};
</script>
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/index.vue b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
index 05403b38850..27933f87929 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/index.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -128,7 +128,7 @@ export default {
this.focusedIndex = 0;
}
- Mousetrap.bind(['t', 'mod+p'], e => {
+ Mousetrap.bind(['t', 'mod+p'], (e) => {
if (e.preventDefault) {
e.preventDefault();
}
diff --git a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
index 91a0ac3aa92..f7cfb59be01 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
+++ b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
@@ -593,15 +593,6 @@ const fileNameIcons = {
export default function getIconForFile(name) {
return (
- fileNameIcons[name] ||
- fileExtensionIcons[
- name
- ? name
- .split('.')
- .pop()
- .toLowerCase()
- : ''
- ] ||
- ''
+ fileNameIcons[name] || fileExtensionIcons[name ? name.split('.').pop().toLowerCase() : ''] || ''
);
}
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 4d07d9fcfdd..96567111bbc 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -137,7 +137,11 @@ export default {
@click="clickFile"
@mouseleave="$emit('mouseleave', $event)"
>
- <div class="file-row-name-container">
+ <div
+ class="file-row-name-container"
+ data-qa-selector="file_row_container"
+ :data-qa-file-name="file.name"
+ >
<span
ref="textOutput"
:style="levelIndentation"
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 3988b3814f9..a4c5ca28494 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
@@ -59,7 +59,7 @@ export default {
type: String,
required: false,
default: '',
- validator: value => value === '' || /(_desc)|(_asc)/g.test(value),
+ validator: (value) => value === '' || /(_desc)|(_asc)/g.test(value),
},
showCheckbox: {
type: Boolean,
@@ -89,7 +89,7 @@ export default {
if (this.initialSortBy) {
selectedSortOption = this.sortOptions
.filter(
- sortBy =>
+ (sortBy) =>
sortBy.sortDirection.ascending === this.initialSortBy ||
sortBy.sortDirection.descending === this.initialSortBy,
)
@@ -204,12 +204,12 @@ export default {
this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
- allowedKeys: this.tokens.map(token => token.type),
+ allowedKeys: this.tokens.map((token) => token.type),
});
this.recentSearchesPromise = this.recentSearchesService
.fetch()
- .catch(error => {
+ .catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
createFlash(__('An error occurred while parsing recent searches'));
@@ -217,7 +217,7 @@ export default {
// Gracefully fail to empty array
return [];
})
- .then(searches => {
+ .then((searches) => {
if (!searches) return;
// Put any searches that may have come in before
@@ -250,13 +250,13 @@ export default {
* spaces.
*/
removeQuotesEnclosure(filters = []) {
- return filters.map(filter => {
+ return filters.map((filter) => {
if (typeof filter === 'object') {
const valueString = filter.value.data;
return {
...filter,
value: {
- data: stripQuotes(valueString),
+ data: typeof valueString === 'string' ? stripQuotes(valueString) : valueString,
operator: filter.value.operator,
},
};
@@ -305,8 +305,8 @@ export default {
},
historyTokenOptionTitle(historyToken) {
const tokenOption = this.tokens
- .find(token => token.type === historyToken.type)
- ?.options?.find(option => option.value === historyToken.value.data);
+ .find((token) => token.type === historyToken.type)
+ ?.options?.find((option) => option.value === historyToken.value.data);
if (!tokenOption?.title) {
return historyToken.value.data;
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
index e7d7b7d9f1b..a15cf220ee5 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
@@ -8,7 +8,7 @@ import { queryToObject } from '~/lib/utils/url_utility';
*
* @returns {String} String without any enclosure
*/
-export const stripQuotes = value => value.replace(/^('|")(.*)('|")$/, '$2');
+export const stripQuotes = (value) => value.replace(/^('|")(.*)('|")$/, '$2');
/**
* This method removes duplicate tokens from tokens array.
@@ -17,7 +17,7 @@ export const stripQuotes = value => value.replace(/^('|")(.*)('|")$/, '$2');
*
* @returns {Array} Unique array of tokens
*/
-export const uniqueTokens = tokens => {
+export const uniqueTokens = (tokens) => {
const knownTokens = [];
return tokens.reduce((uniques, token) => {
if (typeof token === 'object' && token.type !== 'filtered-search-term') {
@@ -61,7 +61,7 @@ export function prepareTokens(filters = {}) {
return memo;
}
if (Array.isArray(value)) {
- return [...memo, ...value.map(filterValue => createToken(key, filterValue))];
+ return [...memo, ...value.map((filterValue) => createToken(key, filterValue))];
}
return [...memo, createToken(key, value)];
@@ -99,8 +99,8 @@ export function filterToQueryObject(filters = {}) {
let selected;
let unselected;
if (Array.isArray(filter)) {
- selected = filter.filter(item => item.operator === '=').map(item => item.value);
- unselected = filter.filter(item => item.operator === '!=').map(item => item.value);
+ selected = filter.filter((item) => item.operator === '=').map((item) => item.value);
+ unselected = filter.filter((item) => item.operator === '!=').map((item) => item.value);
} else {
selected = filter?.operator === '=' ? filter.value : null;
unselected = filter?.operator === '!=' ? filter.value : null;
@@ -155,7 +155,7 @@ export function urlQueryToFilter(query = '') {
previousValues = memo[filterName];
}
if (Array.isArray(value)) {
- const newAdditions = value.filter(Boolean).map(item => ({ value: item, operator }));
+ const newAdditions = value.filter(Boolean).map((item) => ({ value: item, operator }));
return { ...memo, [filterName]: [...previousValues, ...newAdditions] };
}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
index 443cb28cf10..411654d15f4 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
@@ -17,7 +17,7 @@ export function fetchBranches({ commit, state }, search = '') {
commit(types.REQUEST_BRANCHES);
return Api.branches(projectEndpoint, search)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_BRANCHES_SUCCESS, response.data);
return response;
})
@@ -34,7 +34,7 @@ export const fetchMilestones = ({ commit, state }, search_title = '') => {
return axios
.get(milestonesEndpoint, { params: { search_title } })
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_MILESTONES_SUCCESS, response.data);
return response;
})
@@ -50,7 +50,7 @@ export const fetchLabels = ({ commit, state }, search = '') => {
return axios
.get(state.labelsEndpoint, { params: { search } })
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_LABELS_SUCCESS, response.data);
return response;
})
@@ -67,13 +67,13 @@ function fetchUser(options = {}) {
let fetchUserPromise;
if (projectEndpoint) {
- fetchUserPromise = Api.projectUsers(projectEndpoint, query).then(data => ({ data }));
+ fetchUserPromise = Api.projectUsers(projectEndpoint, query).then((data) => ({ data }));
} else {
fetchUserPromise = Api.groupMembers(groupEndpoint, { query });
}
return fetchUserPromise
- .then(response => {
+ .then((response) => {
commit(`RECEIVE_${action}_SUCCESS`, response.data);
return response;
})
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
index ee0e00b0f5d..d53c829a48e 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
@@ -43,7 +43,7 @@ export default {
return this.value.data.toLowerCase();
},
activeAuthor() {
- return this.authors.find(author => author.username.toLowerCase() === this.currentValue);
+ return this.authors.find((author) => author.username.toLowerCase() === this.currentValue);
},
},
watch: {
@@ -63,7 +63,7 @@ export default {
: this.config.fetchAuthors(searchTerm);
fetchPromise
- .then(res => {
+ .then((res) => {
// We'd want to avoid doing this check but
// users.json and /groups/:id/members & /projects/:id/users
// return response differently.
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
index c18bdfc5c20..694dcd95b5e 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
@@ -43,7 +43,7 @@ export default {
return this.value.data.toLowerCase();
},
activeBranch() {
- return this.branches.find(branch => branch.name.toLowerCase() === this.currentValue);
+ return this.branches.find((branch) => branch.name.toLowerCase() === this.currentValue);
},
},
watch: {
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
index 7a9c5c277eb..d59e9200e6c 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
@@ -47,7 +47,7 @@ export default {
},
activeLabel() {
return this.labels.find(
- label => label.title.toLowerCase() === stripQuotes(this.currentValue),
+ (label) => label.title.toLowerCase() === stripQuotes(this.currentValue),
);
},
containerStyle() {
@@ -74,7 +74,7 @@ export default {
this.loading = true;
this.config
.fetchLabels(searchTerm)
- .then(res => {
+ .then((res) => {
// We'd want to avoid doing this check but
// labels.json and /groups/:id/labels & /projects/:id/labels
// return response differently.
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
index c24df5e081d..0dd7820073a 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
@@ -43,7 +43,7 @@ export default {
},
activeMilestone() {
return this.milestones.find(
- milestone => milestone.title.toLowerCase() === stripQuotes(this.currentValue),
+ (milestone) => milestone.title.toLowerCase() === stripQuotes(this.currentValue),
);
},
},
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
index 1ad0ca36bf8..9ab91e567e6 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
@@ -4,6 +4,7 @@ import {
GfmAutocompleteType,
tributeConfig,
} from 'ee_else_ce/vue_shared/components/gfm_autocomplete/utils';
+import * as Emoji from '~/emoji';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -27,7 +28,7 @@ export default {
},
computed: {
config() {
- return this.autocompleteTypes.map(type => ({
+ return this.autocompleteTypes.map((type) => ({
...tributeConfig[type].config,
loadingItemTemplate: `<span class="gl-spinner gl-vertical-align-text-bottom gl-ml-3 gl-mr-2"></span>${__(
'Loading',
@@ -55,7 +56,7 @@ export default {
if (!this.assignees || !isAssigneesLengthSame) {
this.assignees =
- SidebarMediator.singleton?.store?.assignees?.map(assignee => assignee.username) || [];
+ SidebarMediator.singleton?.store?.assignees?.map((assignee) => assignee.username) || [];
}
},
filterValues(type) {
@@ -76,10 +77,18 @@ export default {
return (inputText, processValues) => {
if (this.cache[type]) {
processValues(this.filterValues(type));
+ } else if (type === GfmAutocompleteType.Emojis) {
+ Emoji.initEmojiMap()
+ .then(() => {
+ const emojis = Emoji.getValidEmojiNames();
+ this.cache[type] = emojis;
+ processValues(emojis);
+ })
+ .catch(() => createFlash({ message: this.$options.errorMessage }));
} else if (this.dataSources[type]) {
axios
.get(this.dataSources[type])
- .then(response => {
+ .then((response) => {
this.cache[type] = response.data;
processValues(this.filterValues(type));
})
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
index 2581888b504..809932b0f29 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
@@ -1,16 +1,24 @@
import { escape, last } from 'lodash';
+import * as Emoji from '~/emoji';
import { spriteIcon } from '~/lib/utils/common_utils';
const groupType = 'Group'; // eslint-disable-line @gitlab/require-i18n-strings
+// Number of users to show in the autocomplete menu to avoid doing a mass fetch of 100+ avatars
+const memberLimit = 10;
+
const nonWordOrInteger = /\W|^\d+$/;
+export const menuItemLimit = 100;
+
export const GfmAutocompleteType = {
+ Emojis: 'emojis',
Issues: 'issues',
Labels: 'labels',
Members: 'members',
MergeRequests: 'mergeRequests',
Milestones: 'milestones',
+ QuickActions: 'commands',
Snippets: 'snippets',
};
@@ -21,10 +29,21 @@ function doesCurrentLineStartWith(searchString, fullText, selectionStart) {
}
export const tributeConfig = {
+ [GfmAutocompleteType.Emojis]: {
+ config: {
+ trigger: ':',
+ lookup: (value) => value,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => `${original} ${Emoji.glEmojiTag(original)}`,
+ selectTemplate: ({ original }) => `:${original}:`,
+ },
+ },
+
[GfmAutocompleteType.Issues]: {
config: {
trigger: '#',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `#${original.iid}`,
@@ -35,6 +54,7 @@ export const tributeConfig = {
config: {
trigger: '~',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => `
<span class="dropdown-label-box" style="background: ${escape(original.color)};"></span>
${escape(original.title)}`,
@@ -45,11 +65,11 @@ export const tributeConfig = {
},
filterValues({ collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/label', fullText, selectionStart)) {
- return collection.filter(label => !label.set);
+ return collection.filter((label) => !label.set);
}
if (doesCurrentLineStartWith('/unlabel', fullText, selectionStart)) {
- return collection.filter(label => label.set);
+ return collection.filter((label) => label.set);
}
return collection;
@@ -60,8 +80,9 @@ export const tributeConfig = {
config: {
trigger: '@',
fillAttr: 'username',
- lookup: value =>
+ lookup: (value) =>
value.type === groupType ? last(value.name.split(' / ')) : `${value.name}${value.username}`,
+ menuItemLimit: memberLimit,
menuItemTemplate: ({ original }) => {
const commonClasses = 'gl-avatar gl-avatar-s24 gl-flex-shrink-0';
const noAvatarClasses = `${commonClasses} gl-rounded-small
@@ -101,11 +122,11 @@ export const tributeConfig = {
},
filterValues({ assignees, collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/assign', fullText, selectionStart)) {
- return collection.filter(member => !assignees.includes(member.username));
+ return collection.filter((member) => !assignees.includes(member.username));
}
if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
- return collection.filter(member => assignees.includes(member.username));
+ return collection.filter((member) => assignees.includes(member.username));
}
return collection;
@@ -115,7 +136,8 @@ export const tributeConfig = {
[GfmAutocompleteType.MergeRequests]: {
config: {
trigger: '!',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
@@ -126,16 +148,47 @@ export const tributeConfig = {
config: {
trigger: '%',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => escape(original.title),
selectTemplate: ({ original }) => `%"${escape(original.title)}"`,
},
},
+ [GfmAutocompleteType.QuickActions]: {
+ config: {
+ trigger: '/',
+ fillAttr: 'name',
+ lookup: (value) => `${value.name}${value.aliases.join()}`,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => {
+ const aliases = original.aliases.length
+ ? `<small>(or /${original.aliases.join(', /')})</small>`
+ : '';
+
+ const params = original.params.length ? `<small>${original.params.join(' ')}</small>` : '';
+
+ let description = '';
+
+ if (original.warning) {
+ const confidentialIcon =
+ original.icon === 'confidential' ? spriteIcon('eye-slash', 's16 gl-mr-2') : '';
+ description = `<small>${confidentialIcon}<em>${original.warning}</em></small>`;
+ } else if (original.description) {
+ description = `<small><em>${original.description}</em></small>`;
+ }
+
+ return `<div>/${original.name} ${aliases} ${params}</div>
+ <div>${description}</div>`;
+ },
+ },
+ },
+
[GfmAutocompleteType.Snippets]: {
config: {
trigger: '$',
fillAttr: 'id',
- lookup: value => `${value.id}${value.title}`,
+ lookup: (value) => `${value.id}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) => `<small>${original.id}</small> ${escape(original.title)}`,
},
},
diff --git a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
index 221c4f5b8a8..0a6b50674f0 100644
--- a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
+++ b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
@@ -15,5 +15,5 @@ function cleanSuggestionLine(line = {}) {
}
export function selectDiffLines(lines) {
- return lines.filter(line => line.type !== 'match').map(line => cleanSuggestionLine(line));
+ return lines.filter((line) => line.type !== 'match').map((line) => cleanSuggestionLine(line));
}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index b9729a3dc5c..10887aee689 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -1,6 +1,5 @@
<script>
import { GlDropdown, GlDropdownForm, GlFormTextarea, GlButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
export default {
components: { GlDropdown, GlDropdownForm, GlFormTextarea, GlButton },
@@ -10,7 +9,7 @@ export default {
required: false,
default: false,
},
- fileName: {
+ defaultCommitMessage: {
type: String,
required: true,
},
@@ -18,18 +17,11 @@ export default {
data() {
return {
message: null,
- buttonText: __('Apply suggestion'),
- headerText: __('Apply suggestion commit message'),
};
},
- computed: {
- placeholderText() {
- return sprintf(__('Apply suggestion on %{fileName}'), { fileName: this.fileName });
- },
- },
methods: {
onApply() {
- this.$emit('apply', this.message || this.placeholderText);
+ this.$emit('apply', this.message);
},
},
};
@@ -37,18 +29,26 @@ export default {
<template>
<gl-dropdown
- :text="buttonText"
- :header-text="headerText"
+ :text="__('Apply suggestion')"
:disabled="disabled"
boundary="window"
right
- menu-class="gl-w-full! gl-pb-0!"
+ menu-class="gl-w-full!"
+ @shown="$refs.commitMessage.$el.focus()"
>
- <gl-dropdown-form class="gl-m-3!">
- <gl-form-textarea v-model="message" :placeholder="placeholderText" />
+ <gl-dropdown-form class="gl-px-4! gl-m-0!">
+ <label for="commit-message">{{ __('Commit message') }}</label>
+ <gl-form-textarea
+ id="commit-message"
+ ref="commitMessage"
+ v-model="message"
+ :placeholder="defaultCommitMessage"
+ submit-on-enter
+ @submit="onApply"
+ />
<gl-button
- class="gl-w-quarter! gl-mt-3 gl-text-center! float-right"
- category="secondary"
+ class="gl-w-auto! gl-mt-3 gl-text-center! gl-hover-text-white! gl-transition-medium! float-right"
+ category="primary"
variant="success"
@click="onApply"
>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 232a3054cd0..b6e167524aa 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -158,7 +158,7 @@ export default {
const mediaInPreview = this.$refs['markdown-preview'].querySelectorAll('video, audio');
if (mediaInPreview) {
- mediaInPreview.forEach(media => {
+ mediaInPreview.forEach((media) => {
media.pause();
});
}
@@ -169,7 +169,7 @@ export default {
return new GLForm(
$(this.$refs['gl-form']),
{
- emojis: this.enableAutocomplete,
+ emojis: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
members: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
@@ -199,7 +199,7 @@ export default {
this.markdownPreview = __('Loading…');
axios
.post(this.markdownPreviewPath, { text: this.textareaValue })
- .then(response => this.renderMarkdown(response.data))
+ .then((response) => this.renderMarkdown(response.data))
.catch(() => new Flash(__('Error loading markdown preview')));
} else {
this.renderMarkdown();
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index d0a0560846a..173d192dab0 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -110,7 +110,7 @@ export default {
const area = this.$el.parentNode.querySelector('textarea');
CopyAsGFM.nodeToGFM(transformed)
- .then(gfm => {
+ .then((gfm) => {
CopyAsGFM.insertPastedText(area, documentFragment.textContent, CopyAsGFM.quoted(gfm));
})
.catch(() => {});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
index 13ec7a6ada9..93a270b8a97 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -27,6 +27,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
suggestionsCount: {
type: Number,
required: false,
@@ -47,8 +51,8 @@ export default {
},
},
methods: {
- applySuggestion(callback) {
- this.$emit('apply', { suggestionId: this.suggestion.id, callback });
+ applySuggestion(callback, message) {
+ this.$emit('apply', { suggestionId: this.suggestion.id, callback, message });
},
applySuggestionBatch() {
this.$emit('applyBatch');
@@ -74,6 +78,7 @@ export default {
:is-applying-batch="suggestion.is_applying_batch"
:batch-suggestions-count="batchSuggestionsCount"
:help-page-path="helpPagePath"
+ :default-commit-message="defaultCommitMessage"
:inapplicable-reason="suggestion.inapplicable_reason"
@apply="applySuggestion"
@applyBatch="applySuggestionBatch"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index fb51840b689..63341b433e0 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -2,9 +2,10 @@
import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import ApplySuggestion from './apply_suggestion.vue';
export default {
- components: { GlIcon, GlButton, GlLoadingIcon },
+ components: { GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
directives: { 'gl-tooltip': GlTooltipDirective },
mixins: [glFeatureFlagsMixin()],
props: {
@@ -37,6 +38,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
inapplicableReason: {
type: String,
required: false,
@@ -57,6 +62,9 @@ export default {
canBeBatched() {
return Boolean(this.glFeatures.batchSuggestions);
},
+ canAddCustomCommitMessage() {
+ return this.glFeatures.suggestionsCustomCommit;
+ },
isApplying() {
return this.isApplyingSingle || this.isApplyingBatch;
},
@@ -77,10 +85,10 @@ export default {
},
},
methods: {
- applySuggestion() {
+ applySuggestion(message) {
if (!this.canApply) return;
this.isApplyingSingle = true;
- this.$emit('apply', this.applySuggestionCallback);
+ this.$emit('apply', this.applySuggestionCallback, message);
},
applySuggestionCallback() {
this.isApplyingSingle = false;
@@ -142,7 +150,14 @@ export default {
>
{{ __('Add suggestion to batch') }}
</gl-button>
- <span v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
+ <apply-suggestion
+ v-if="canAddCustomCommitMessage"
+ :disabled="isDisableButton"
+ :default-commit-message="defaultCommitMessage"
+ class="gl-ml-3"
+ @apply="applySuggestion"
+ />
+ <span v-else v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
<gl-button
v-if="isLoggedIn"
class="btn-inverted js-apply-btn btn-grouped"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 927a93487e6..5ee51764555 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -38,6 +38,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
suggestionsCount: {
type: Number,
required: false,
@@ -82,27 +86,41 @@ export default {
this.isRendered = true;
},
generateDiff(suggestionIndex) {
- const { suggestions, disabled, batchSuggestionsInfo, helpPagePath, suggestionsCount } = this;
+ const {
+ suggestions,
+ disabled,
+ batchSuggestionsInfo,
+ helpPagePath,
+ defaultCommitMessage,
+ suggestionsCount,
+ } = this;
const suggestion =
suggestions && suggestions[suggestionIndex] ? suggestions[suggestionIndex] : {};
const SuggestionDiffComponent = Vue.extend(SuggestionDiff);
const suggestionDiff = new SuggestionDiffComponent({
- propsData: { disabled, suggestion, batchSuggestionsInfo, helpPagePath, suggestionsCount },
+ propsData: {
+ disabled,
+ suggestion,
+ batchSuggestionsInfo,
+ helpPagePath,
+ defaultCommitMessage,
+ suggestionsCount,
+ },
});
- suggestionDiff.$on('apply', ({ suggestionId, callback }) => {
- this.$emit('apply', { suggestionId, callback, flashContainer: this.$el });
+ suggestionDiff.$on('apply', ({ suggestionId, callback, message }) => {
+ this.$emit('apply', { suggestionId, callback, flashContainer: this.$el, message });
});
suggestionDiff.$on('applyBatch', () => {
this.$emit('applyBatch', { flashContainer: this.$el });
});
- suggestionDiff.$on('addToBatch', suggestionId => {
+ suggestionDiff.$on('addToBatch', (suggestionId) => {
this.$emit('addToBatch', suggestionId);
});
- suggestionDiff.$on('removeFromBatch', suggestionId => {
+ suggestionDiff.$on('removeFromBatch', (suggestionId) => {
this.$emit('removeFromBatch', suggestionId);
});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 5824cb9438f..15c5b9d6733 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -49,10 +49,10 @@ export default {
)
"
>
- <template #markdownDocsLink="{content}">
+ <template #markdownDocsLink="{ content }">
<gl-link :href="markdownDocsPath" target="_blank">{{ content }}</gl-link>
</template>
- <template #quickActionsDocsLink="{content}">
+ <template #quickActionsDocsLink="{ content }">
<gl-link :href="quickActionsDocsPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
@@ -81,7 +81,7 @@ export default {
)
"
>
- <template #retryButton="{content}">
+ <template #retryButton="{ content }">
<gl-button
variant="link"
category="primary"
@@ -90,7 +90,7 @@ export default {
{{ content }}
</gl-button>
</template>
- <template #newFileButton="{content}">
+ <template #newFileButton="{ content }">
<gl-button
variant="link"
category="primary"
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
index de9c84dd157..e3a7f144321 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -55,6 +55,11 @@ export default {
required: false,
default: null,
},
+ category: {
+ type: String,
+ required: false,
+ default: 'primary',
+ },
},
computed: {
modalDomId() {
@@ -70,14 +75,14 @@ export default {
document.body,
});
this.clipboard
- .on('success', e => {
+ .on('success', (e) => {
this.$root.$emit('bv::hide::tooltip', this.id);
this.$emit('success', e);
// Clear the selection and blur the trigger so it loses its border
e.clearSelection();
e.trigger.blur();
})
- .on('error', e => this.$emit('error', e));
+ .on('error', (e) => this.$emit('error', e));
});
},
destroyed() {
@@ -95,6 +100,7 @@ export default {
:data-clipboard-target="target"
:data-clipboard-text="text"
:title="title"
+ :category="category"
icon="copy-to-clipboard"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
index 3749888ee36..653ee7f20e9 100644
--- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { GlBadge, GlTabs, GlTab } from '@gitlab/ui';
/**
* Given an array of tabs, renders non linked bootstrap tabs.
@@ -23,6 +24,11 @@ import $ from 'jquery';
*/
export default {
name: 'NavigationTabs',
+ components: {
+ GlBadge,
+ GlTabs,
+ GlTab,
+ },
props: {
tabs: {
type: Array,
@@ -50,24 +56,21 @@ export default {
};
</script>
<template>
- <ul class="nav-links scrolling-tabs separator">
- <li
+ <gl-tabs class="gl-display-flex gl-w-full" nav-class="gl-border-0!">
+ <gl-tab
v-for="(tab, i) in tabs"
:key="i"
- :class="{
- active: tab.isActive,
- }"
+ :title-link-class="`js-${scope}-tab-${tab.scope} gl-display-inline-flex`"
+ :title-link-attributes="{ 'data-testid': `${scope}-tab-${tab.scope}` }"
+ :active="tab.isActive"
+ @click="onTabClick(tab)"
>
- <a
- :class="`js-${scope}-tab-${tab.scope}`"
- :data-testid="`${scope}-tab-${tab.scope}`"
- role="button"
- @click="onTabClick(tab)"
- >
- {{ tab.name }}
-
- <span v-if="shouldRenderBadge(tab.count)" class="badge badge-pill"> {{ tab.count }} </span>
- </a>
- </li>
- </ul>
+ <template #title>
+ <span class="gl-mr-2"> {{ tab.name }} </span>
+ <gl-badge v-if="shouldRenderBadge(tab.count)" size="sm" class="gl-tab-counter-badge">{{
+ tab.count
+ }}</gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
</template>
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 f30676e8ef3..cc1203f83f0 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -78,16 +78,10 @@ export default {
},
// following 2 methods taken from code in `collapseLongCommitList` of notes.js:
actionTextHtml() {
- return $(this.note.note_html)
- .unwrap()
- .html();
+ return $(this.note.note_html).unwrap().html();
},
hasMoreCommits() {
- return (
- $(this.note.note_html)
- .filter('ul')
- .children().length > MAX_VISIBLE_COMMIT_LIST_COUNT
- );
+ return $(this.note.note_html).filter('ul').children().length > MAX_VISIBLE_COMMIT_LIST_COUNT;
},
descriptionVersion() {
return this.descriptionVersions[this.note.description_version_id];
diff --git a/app/assets/javascripts/vue_shared/components/ordered_layout.vue b/app/assets/javascripts/vue_shared/components/ordered_layout.vue
index 117e79ca39f..a57ff10de71 100644
--- a/app/assets/javascripts/vue_shared/components/ordered_layout.vue
+++ b/app/assets/javascripts/vue_shared/components/ordered_layout.vue
@@ -4,7 +4,7 @@ export default {
render(h, context) {
const { slotKeys } = context.props;
const slots = context.slots();
- const children = slotKeys.map(key => slots[key]).filter(x => x);
+ const children = slotKeys.map((key) => slots[key]).filter((x) => x);
return children;
},
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
index 1fc39c7cb8e..d03987bbbe0 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
@@ -203,7 +203,7 @@ export default {
this.resetPagination();
const filterParams = { authorUsername: '', assigneeUsername: '', search: '' };
- filters.forEach(filter => {
+ filters.forEach((filter) => {
if (typeof filter === 'object') {
switch (filter.type) {
case 'author_username':
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
index 7de4263acbb..7855c7ea6cb 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
@@ -6,6 +6,6 @@ import { __ } from '~/locale';
* @param {String} value
* @returns {String}
*/
-export const isAny = value => {
+export const isAny = (value) => {
return value === __('Any') ? '' : value;
};
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
index 85481f3f7b4..3c0ac32e512 100644
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ b/app/assets/javascripts/vue_shared/components/pikaday.vue
@@ -1,20 +1,13 @@
<script>
-import Pikaday from 'pikaday';
-import { GlIcon } from '@gitlab/ui';
-import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
+import { GlDatepicker } from '@gitlab/ui';
+import { pikadayToString } from '~/lib/utils/datetime_utility';
export default {
name: 'DatePicker',
components: {
- GlIcon,
+ GlDatepicker,
},
props: {
- label: {
- type: String,
- required: false,
- default: __('Date picker'),
- },
selectedDate: {
type: Date,
required: false,
@@ -31,32 +24,9 @@ export default {
default: null,
},
},
- mounted() {
- this.calendar = new Pikaday({
- field: this.$el.querySelector('.dropdown-menu-toggle'),
- theme: 'gitlab-theme animate-picker',
- format: 'yyyy-mm-dd',
- container: this.$el,
- defaultDate: this.selectedDate,
- setDefaultDate: Boolean(this.selectedDate),
- minDate: this.minDate,
- maxDate: this.maxDate,
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
- onSelect: this.selected.bind(this),
- onClose: this.toggled.bind(this),
- firstDay: gon.first_day_of_week,
- });
-
- this.$el.append(this.calendar.el);
- this.calendar.show();
- },
- beforeDestroy() {
- this.calendar.destroy();
- },
methods: {
- selected(dateText) {
- this.$emit('newDateSelected', this.calendar.toString(dateText));
+ selected(date) {
+ this.$emit('newDateSelected', pikadayToString(date));
},
toggled() {
this.$emit('hidePicker');
@@ -66,12 +36,13 @@ export default {
</script>
<template>
- <div class="pikaday-container">
- <div class="dropdown open">
- <button type="button" class="dropdown-menu-toggle" data-toggle="dropdown" @click="toggled">
- <span class="dropdown-toggle-text"> {{ label }} </span>
- <gl-icon name="chevron-down" class="gl-absolute gl-right-3 gl-top-3 gl-text-gray-500" />
- </button>
- </div>
- </div>
+ <gl-datepicker
+ :value="selectedDate"
+ :min-date="minDate"
+ :max-date="maxDate"
+ start-opened
+ @close="toggled"
+ @click="toggled"
+ @input="selected"
+ />
</template>
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 154671fe9fa..65bd4e4382d 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -13,7 +13,7 @@ export default {
project: {
type: Object,
required: true,
- validator: p =>
+ validator: (p) =>
(Number.isFinite(p.id) || isString(p.id)) &&
isString(p.name) &&
(isString(p.name_with_namespace) || isString(p.nameWithNamespace)),
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
index 4e2029cd74f..e659e2155fb 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
@@ -48,10 +48,14 @@ export default {
data() {
return {
searchQuery: '',
+ hasSearched: false,
};
},
computed: {
legendText() {
+ if (!this.hasSearched) {
+ return '';
+ }
const count = this.projectSearchResults.length;
const total = this.totalResults;
@@ -75,6 +79,9 @@ export default {
return this.selectedProjects.some(({ id }) => project.id === id);
},
onInput: debounce(function debouncedOnInput() {
+ if (!this.hasSearched) {
+ this.hasSearched = true;
+ }
this.$emit('searched', this.searchQuery);
}, SEARCH_INPUT_TIMEOUT_MS),
},
@@ -115,7 +122,7 @@ export default {
</template>
<template #default>
- {{ legendText }}
+ <span data-testid="legend-text">{{ legendText }}</span>
</template>
</gl-infinite-scroll>
<div v-if="showNoResultsMessage" class="text-muted ml-2 js-no-results-message">
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
index 7046ac5be03..8965dba3e83 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -39,7 +39,7 @@ export default {
},
},
mounted() {
- this.detailsSlots = Object.keys(this.$slots).filter(k => k.startsWith('details-'));
+ this.detailsSlots = Object.keys(this.$slots).filter((k) => k.startsWith('details-'));
},
methods: {
toggleDetails() {
diff --git a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
index 8ef623b68eb..93396219a54 100644
--- a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon, GlLink } from '@gitlab/ui';
+import { GlIcon, GlLink, GlTooltipDirective } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
export default {
@@ -9,6 +9,9 @@ export default {
GlLink,
TooltipOnTruncate,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
icon: {
type: String,
@@ -32,6 +35,11 @@ export default {
return !value || ['xs', 's', 'm', 'l', 'xl'].includes(value);
},
},
+ textTooltip: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
sizeClass() {
@@ -55,9 +63,12 @@ export default {
class="gl-font-weight-bold gl-display-inline-flex"
:class="sizeClass"
>
- <tooltip-on-truncate :title="text" class="gl-text-truncate">
+ <tooltip-on-truncate v-if="!textTooltip" :title="text" class="gl-text-truncate">
{{ text }}
</tooltip-on-truncate>
+ <span v-else v-gl-tooltip="{ title: textTooltip }" data-testid="text-tooltip-container">
+ {{ text }}</span
+ >
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/title_area.vue b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
index 4d47a34c9a3..c63d91b78d3 100644
--- a/app/assets/javascripts/vue_shared/components/registry/title_area.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAvatar, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
export default {
name: 'TitleArea',
@@ -7,6 +7,7 @@ export default {
GlAvatar,
GlSprintf,
GlLink,
+ GlSkeletonLoader,
},
props: {
avatar: {
@@ -24,6 +25,11 @@ export default {
default: () => [],
required: false,
},
+ metadataLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -32,11 +38,11 @@ export default {
},
async mounted() {
const METADATA_PREFIX = 'metadata-';
- this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
+ this.metadataSlots = Object.keys(this.$slots).filter((k) => k.startsWith(METADATA_PREFIX));
// we need to wait for next tick to ensure that dynamic names slots are picked up
await this.$nextTick();
- this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
+ this.metadataSlots = Object.keys(this.$slots).filter((k) => k.startsWith(METADATA_PREFIX));
},
};
</script>
@@ -44,7 +50,7 @@ export default {
<template>
<div class="gl-display-flex gl-flex-direction-column">
<div class="gl-display-flex gl-justify-content-space-between gl-py-3">
- <div class="gl-flex-direction-column">
+ <div class="gl-flex-direction-column gl-flex-grow-1">
<div class="gl-display-flex">
<gl-avatar
v-if="avatar"
@@ -68,13 +74,23 @@ export default {
</div>
<div class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3">
- <div
- v-for="(row, metadataIndex) in metadataSlots"
- :key="metadataIndex"
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <slot :name="row"></slot>
- </div>
+ <template v-if="!metadataLoading">
+ <div
+ v-for="(row, metadataIndex) in metadataSlots"
+ :key="metadataIndex"
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <slot :name="row"></slot>
+ </div>
+ </template>
+ <template v-else>
+ <div class="gl-w-full">
+ <gl-skeleton-loader :width="960" :height="16" preserve-aspect-ratio="xMinYMax meet">
+ <circle cx="6" cy="8" r="6" />
+ <rect x="16" y="4" width="200" height="8" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ </template>
</div>
</div>
<div v-if="$slots['right-actions']" class="gl-mt-3">
@@ -89,7 +105,7 @@ export default {
data-testid="info-message"
>
<gl-sprintf :message="message.text">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="message.link" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
index fe50a459e52..5d4c192c78f 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
@@ -20,7 +20,7 @@ export default {
components: {
ToastEditor: () =>
import(/* webpackChunkName: 'toast_editor' */ '@toast-ui/vue-editor').then(
- toast => toast.Editor,
+ (toast) => toast.Editor,
),
AddImageModal,
InsertVideoModal,
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
index 108c60c3edb..624b5b09b38 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
@@ -17,12 +17,12 @@ const listItemRenderers = [renderListItem];
const softbreakRenderers = [renderSoftbreak];
const executeRenderer = (renderers, node, context) => {
- const availableRenderer = renderers.find(renderer => renderer.canRender(node, context));
+ const availableRenderer = renderers.find((renderer) => renderer.canRender(node, context));
return availableRenderer ? availableRenderer.render(node, context) : context.origin();
};
-const buildCustomHTMLRenderer = customRenderers => {
+const buildCustomHTMLRenderer = (customRenderers) => {
const renderersByType = {
...customRenderers,
htmlBlock: union(htmlBlockRenderers, customRenderers?.htmlBlock),
@@ -34,7 +34,7 @@ const buildCustomHTMLRenderer = customRenderers => {
softbreak: union(softbreakRenderers, customRenderers?.softbreak),
};
- return mapValues(renderersByType, renderers => {
+ return mapValues(renderersByType, (renderers) => {
return (node, context) => executeRenderer(renderers, node, context);
});
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
index 9744e25a8e1..273e0a59963 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
@@ -9,7 +9,7 @@ const DEFAULTS = {
emphasis: '_',
};
-const countIndentSpaces = text => {
+const countIndentSpaces = (text) => {
const matches = text.match(/^\s+/m);
return matches ? matches[0].length : 0;
@@ -52,7 +52,7 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
const firstLevelIndentSpacesCount = countIndentSpaces(baseResult) || 1;
const reindentedList = baseResult
.split('\n')
- .map(line => {
+ .map((line) => {
const itemIndentSpacesCount = countIndentSpaces(line);
const nestingLevel = Math.ceil(itemIndentSpacesCount / firstLevelIndentSpacesCount);
const indentSpaces = repeat(' ', subListIndentSpaces * nestingLevel);
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
index 463e64b4936..be78651d38d 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
@@ -6,7 +6,7 @@ import buildCustomHTMLRenderer from './build_custom_renderer';
import { TOOLBAR_ITEM_CONFIGS, VIDEO_ATTRIBUTES } from '../constants';
import sanitizeHTML from './sanitize_html';
-const buildWrapper = propsData => {
+const buildWrapper = (propsData) => {
const instance = new Vue({
render(createElement) {
return createElement(ToolbarItem, propsData);
@@ -17,7 +17,7 @@ const buildWrapper = propsData => {
return instance.$el;
};
-const buildVideoIframe = src => {
+const buildVideoIframe = (src) => {
const wrapper = document.createElement('figure');
const iframe = document.createElement('iframe');
const videoAttributes = { ...VIDEO_ATTRIBUTES, src };
@@ -48,7 +48,7 @@ const buildImg = (alt, originalSrc, file) => {
return img;
};
-export const generateToolbarItem = config => {
+export const generateToolbarItem = (config) => {
const { icon, classes, event, command, tooltip, isDivider } = config;
if (isDivider) {
@@ -92,14 +92,14 @@ export const insertVideo = ({ editor }, url) => {
}
};
-export const getMarkdown = editorInstance => editorInstance.invoke('getMarkdown');
+export const getMarkdown = (editorInstance) => editorInstance.invoke('getMarkdown');
/**
* This function allow us to extend Toast UI HTML to Markdown renderer. It is
* a temporary measure because Toast UI does not provide an API
* to achieve this goal.
*/
-export const registerHTMLToMarkdownRenderer = editorApi => {
+export const registerHTMLToMarkdownRenderer = (editorApi) => {
const { renderer } = editorApi.toMarkOptions;
Object.assign(editorApi.toMarkOptions, {
@@ -107,10 +107,10 @@ export const registerHTMLToMarkdownRenderer = editorApi => {
});
};
-export const getEditorOptions = externalOptions => {
+export const getEditorOptions = (externalOptions) => {
return defaults({
customHTMLRenderer: buildCustomHTMLRenderer(externalOptions?.customRenderers),
- toolbarItems: TOOLBAR_ITEM_CONFIGS.map(toolbarItem => generateToolbarItem(toolbarItem)),
- customHTMLSanitizer: html => sanitizeHTML(html),
+ toolbarItems: TOOLBAR_ITEM_CONFIGS.map((toolbarItem) => generateToolbarItem(toolbarItem)),
+ customHTMLSanitizer: (html) => sanitizeHTML(html),
});
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
index 1dcecd5fb8c..638e5fd6f60 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
@@ -32,20 +32,20 @@ export const buildUneditableCloseTokens = (token, tagType = TAG_TYPES.block) =>
// Complete helpers (open plus close)
-export const buildTextToken = content => buildToken('text', null, { content });
+export const buildTextToken = (content) => buildToken('text', null, { content });
-export const buildUneditableBlockTokens = token => {
+export const buildUneditableBlockTokens = (token) => {
return [...buildUneditableOpenTokens(token), buildUneditableCloseToken()];
};
-export const buildUneditableInlineTokens = token => {
+export const buildUneditableInlineTokens = (token) => {
return [
...buildUneditableOpenTokens(token, TAG_TYPES.inline),
buildUneditableCloseToken(TAG_TYPES.inline),
];
};
-export const buildUneditableHtmlAsTextTokens = node => {
+export const buildUneditableHtmlAsTextTokens = (node) => {
/*
Toast UI internally appends ' data-tomark-pass ' attribute flags so it can target certain
nested nodes for internal use during Markdown <=> WYSIWYG conversions. In our case, we want
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
index 18bd17d43d9..30012c1123f 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
@@ -2,7 +2,7 @@ import { buildUneditableHtmlAsTextTokens } from './build_uneditable_token';
import { ALLOWED_VIDEO_ORIGINS } from '../../constants';
import { getURLOrigin } from '~/lib/utils/url_utility';
-const isVideoFrame = html => {
+const isVideoFrame = (html) => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const {
@@ -18,6 +18,6 @@ const canRender = ({ type, literal }) => {
return type === 'htmlBlock' && !isVideoFrame(literal);
};
-const render = node => buildUneditableHtmlAsTextTokens(node);
+const render = (node) => buildUneditableHtmlAsTextTokens(node);
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
index a9c3dfcd728..d7716543b53 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
@@ -17,7 +17,7 @@ Regexp notes:
*/
const identifierInstanceRegex = /((?:\[.+?\]){1}(?:\[\]|\[.+?\])?(?!:))/g;
-const isIdentifierInstance = literal => {
+const isIdentifierInstance = (literal) => {
// Reset lastIndex as global flag in regexp are stateful (https://stackoverflow.com/a/11477448)
identifierInstanceRegex.lastIndex = 0;
return identifierInstanceRegex.test(literal);
@@ -25,9 +25,9 @@ const isIdentifierInstance = literal => {
const canRender = ({ literal }) => isIdentifierInstance(literal);
-const tokenize = text => {
+const tokenize = (text) => {
const matches = text.split(identifierInstanceRegex);
- const tokens = matches.map(match => {
+ const tokens = matches.map((match) => {
const token = buildTextToken(match);
return isIdentifierInstance(match) ? buildUneditableInlineTokens(token) : token;
});
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
index 3f9c6291d1b..4829f0f2243 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
@@ -1,6 +1,6 @@
const identifierRegex = /(^\[.+\]: .+)/;
-const isIdentifier = text => {
+const isIdentifier = (text) => {
return identifierRegex.test(text);
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
index 389ade5f27a..c004e839821 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
@@ -1,4 +1,4 @@
-const canRender = node => ['emph', 'strong'].includes(node.parent?.type);
+const canRender = (node) => ['emph', 'strong'].includes(node.parent?.type);
const render = () => ({
type: 'text',
content: ' ',
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
index 4cba2c70486..eff5dbf59f2 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
@@ -11,9 +11,9 @@ export const renderUneditableBranch = (_, { entering, origin }) =>
const attributeDefinitionRegexp = /(^{:.+}$)/;
-export const isAttributeDefinition = text => attributeDefinitionRegexp.test(text);
+export const isAttributeDefinition = (text) => attributeDefinitionRegexp.test(text);
-const findAttributeDefinition = node => {
+const findAttributeDefinition = (node) => {
const literal =
node?.next?.firstChild?.literal || node?.firstChild?.firstChild?.next?.next?.literal; // for headings // for list items;
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
index eae2e0335c1..cb0f1d51cb1 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
@@ -5,7 +5,7 @@ import { getURLOrigin } from '~/lib/utils/url_utility';
const sanitizer = createSanitizer(window);
const ADD_TAGS = ['iframe'];
-sanitizer.addHook('uponSanitizeElement', node => {
+sanitizer.addHook('uponSanitizeElement', (node) => {
if (node.tagName !== 'IFRAME') {
return;
}
@@ -17,6 +17,6 @@ sanitizer.addHook('uponSanitizeElement', node => {
}
});
-const sanitize = content => sanitizer.sanitize(content, { ADD_TAGS });
+const sanitize = (content) => sanitizer.sanitize(content, { ADD_TAGS });
export default sanitize;
diff --git a/app/assets/javascripts/vue_shared/components/select2_select.vue b/app/assets/javascripts/vue_shared/components/select2_select.vue
index 3dbf0ccdfa9..6574a5ddfde 100644
--- a/app/assets/javascripts/vue_shared/components/select2_select.vue
+++ b/app/assets/javascripts/vue_shared/components/select2_select.vue
@@ -26,7 +26,7 @@ export default {
$(this.$refs.dropdownInput)
.val(this.value)
.select2(this.options)
- .on('change', event => this.$emit('input', event.target.value));
+ .on('change', (event) => this.$emit('input', event.target.value));
})
.catch(() => {});
},
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index 1ef3d5627ae..22d86ee25d1 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -143,7 +143,7 @@ export default {
>
<slot></slot>
</dropdown-value>
- <div v-if="canEdit" class="selectbox js-selectbox" style="display: none;">
+ <div v-if="canEdit" class="selectbox js-selectbox" style="display: none">
<dropdown-hidden-input
v-for="label in context.labels"
:key="label.id"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
index 434aabc3df9..795f16f4efc 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
@@ -18,7 +18,7 @@ export default {
},
created() {
const rawLabelsColors = gon.suggested_label_colors;
- this.suggestedColors = Object.keys(rawLabelsColors).map(colorCode => ({
+ this.suggestedColors = Object.keys(rawLabelsColors).map((colorCode) => ({
colorCode,
title: rawLabelsColors[colorCode],
}));
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index 973cc314ee3..122250d1ce7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
@@ -20,7 +20,7 @@ export default {
const labelsString = this.labels.length
? this.labels
.slice(0, 5)
- .map(label => label.title)
+ .map((label) => label.title)
.join(', ')
: s__('LabelSelect|Labels');
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
index 55e2fb68275..41308e352e3 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
@@ -25,7 +25,7 @@ export default {
},
suggestedColors() {
const colorsMap = gon.suggested_label_colors;
- return Object.keys(colorsMap).map(color => ({ [color]: colorsMap[color] }));
+ return Object.keys(colorsMap).map((color) => ({ [color]: colorsMap[color] }));
},
},
methods: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index 8ce624aa303..683889b8611 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -182,9 +182,9 @@ export default {
!state.showDropdownButton &&
!state.showDropdownContents
) {
- let filterFn = label => label.touched;
+ let filterFn = (label) => label.touched;
if (this.isDropdownVariantEmbedded) {
- filterFn = label => label.set;
+ filterFn = (label) => label.set;
}
this.handleDropdownClose(state.labels.filter(filterFn));
}
@@ -204,13 +204,13 @@ export default {
'js-btn-cancel-create',
'js-sidebar-dropdown-toggle',
].some(
- className =>
+ (className) =>
target?.classList.contains(className) ||
target?.parentElement?.classList.contains(className),
);
const hadExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
- className => $(target).parents(className).length,
+ (className) => $(target).parents(className).length,
);
if (
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
index 5a30e29cad3..d14f96720b7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
@@ -9,7 +9,7 @@ import { DropdownVariant } from '../constants';
*/
export const dropdownButtonText = (state, getters) => {
const selectedLabels = getters.isDropdownVariantSidebar
- ? state.labels.filter(label => label.set)
+ ? state.labels.filter((label) => label.set)
: state.selectedLabels;
if (!selectedLabels.length) {
@@ -28,25 +28,25 @@ export const dropdownButtonText = (state, getters) => {
* selectedLabels array.
* @param {object} state
*/
-export const selectedLabelsList = state => state.selectedLabels.map(label => label.id);
+export const selectedLabelsList = (state) => state.selectedLabels.map((label) => label.id);
/**
* Returns boolean representing whether dropdown variant
* is `sidebar`
* @param {object} state
*/
-export const isDropdownVariantSidebar = state => state.variant === DropdownVariant.Sidebar;
+export const isDropdownVariantSidebar = (state) => state.variant === DropdownVariant.Sidebar;
/**
* Returns boolean representing whether dropdown variant
* is `standalone`
* @param {object} state
*/
-export const isDropdownVariantStandalone = state => state.variant === DropdownVariant.Standalone;
+export const isDropdownVariantStandalone = (state) => state.variant === DropdownVariant.Standalone;
/**
* Returns boolean representing whether dropdown variant
* is `embedded`
* @param {object} state
*/
-export const isDropdownVariantEmbedded = state => state.variant === DropdownVariant.Embedded;
+export const isDropdownVariantEmbedded = (state) => state.variant === DropdownVariant.Embedded;
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
index 54f8c78b4e1..6de436ffd13 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
@@ -33,7 +33,7 @@ export default {
// Iterate over every label and add a `set` prop
// to determine whether it is already a part of
// selectedLabels array.
- const selectedLabelIds = state.selectedLabels.map(label => label.id);
+ const selectedLabelIds = state.selectedLabels.map((label) => label.id);
state.labelsFetchInProgress = false;
state.labels = labels.reduce((allLabels, label) => {
allLabels.push({
@@ -61,7 +61,7 @@ export default {
// Find the label to update from all the labels
// and change `set` prop value to represent their current state.
const labelId = labels.pop()?.id;
- const candidateLabel = state.labels.find(label => labelId === label.id);
+ const candidateLabel = state.labels.find((label) => labelId === label.id);
if (candidateLabel) {
candidateLabel.touched = true;
candidateLabel.set = !candidateLabel.set;
diff --git a/app/assets/javascripts/vue_shared/components/split_button.vue b/app/assets/javascripts/vue_shared/components/split_button.vue
index 11049028ff6..61b317d0d1d 100644
--- a/app/assets/javascripts/vue_shared/components/split_button.vue
+++ b/app/assets/javascripts/vue_shared/components/split_button.vue
@@ -2,7 +2,7 @@
import { isString } from 'lodash';
import { GlDropdown, GlDropdownDivider, GlDropdownItem } from '@gitlab/ui';
-const isValidItem = item =>
+const isValidItem = (item) =>
isString(item.eventName) && isString(item.title) && isString(item.description);
export default {
diff --git a/app/assets/javascripts/vue_shared/components/tabs/tabs.js b/app/assets/javascripts/vue_shared/components/tabs/tabs.js
index 9b9e4bb47bd..233df96a520 100644
--- a/app/assets/javascripts/vue_shared/components/tabs/tabs.js
+++ b/app/assets/javascripts/vue_shared/components/tabs/tabs.js
@@ -17,8 +17,8 @@ export default {
},
methods: {
updateTabs() {
- this.tabs = this.$children.filter(child => child.isTab);
- this.currentIndex = this.tabs.findIndex(tab => tab.localActive);
+ this.tabs = this.$children.filter((child) => child.isTab);
+ this.currentIndex = this.tabs.findIndex((tab) => tab.localActive);
},
setTab(e, index) {
if (this.stopPropagation) {
@@ -48,7 +48,7 @@ export default {
href: '#',
},
on: {
- click: e => this.setTab(e, i),
+ click: (e) => this.setTab(e, i),
},
},
tab.$slots.title || tab.title,
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
index 3fa8efcd145..f1db26ff4fc 100644
--- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
@@ -36,14 +36,14 @@ export default {
},
computed: {
timezones() {
- return this.timezoneData.map(timezone => ({
+ return this.timezoneData.map((timezone) => ({
formattedTimezone: this.formatTimezone(timezone),
identifier: timezone.identifier,
}));
},
filteredResults() {
const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.timezones.filter(timezone =>
+ return this.timezones.filter((timezone) =>
timezone.formattedTimezone.toLowerCase().includes(lowerCasedSearchTerm),
);
},
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 b645758d891..01ba2cf5c39 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
@@ -62,7 +62,9 @@ export default {
return files.every(this.isFileValid);
},
isValidDragDataType({ dataTransfer }) {
- return Boolean(dataTransfer && dataTransfer.types.some(t => t === VALID_DATA_TRANSFER_TYPE));
+ return Boolean(
+ dataTransfer && dataTransfer.types.some((t) => t === VALID_DATA_TRANSFER_TYPE),
+ );
},
ondrop({ dataTransfer = {} }) {
this.dragCounter = 0;
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
index ea483416c46..efb99eb0d94 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
@@ -104,7 +104,7 @@ export default {
:target="() => $refs.userAvatarImage"
:placement="tooltipPlacement"
boundary="window"
- class="js-user-avatar-image-toolip"
+ class="js-user-avatar-image-tooltip"
>
<slot> {{ tooltipText }} </slot>
</gl-tooltip>
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index dbb1a075e76..c957876f8ab 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -72,7 +72,7 @@ export default {
},
computed: {
actions() {
- return [this.webIdeAction, this.editAction, this.gitpodAction].filter(action => action);
+ return [this.webIdeAction, this.editAction, this.gitpodAction].filter((action) => action);
},
editAction() {
if (!this.showEditButton) {