summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/markdown
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/markdown')
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue119
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue21
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue72
6 files changed, 205 insertions, 47 deletions
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 8007ccb91d5..0e05f4a4622 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -134,7 +134,7 @@ export default {
addMultipleToDiscussionWarning() {
return sprintf(
__(
- '%{icon}You are about to add %{usersTag} people to the discussion. Proceed with caution.',
+ '%{icon}You are about to add %{usersTag} people to the discussion. They will all receive a notification.',
),
{
icon: '<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>',
@@ -245,11 +245,11 @@ export default {
<div class="zen-backdrop">
<slot name="textarea"></slot>
<a
- class="zen-control zen-control-leave js-zen-leave"
+ class="zen-control zen-control-leave js-zen-leave gl-text-gray-700"
href="#"
- :aria-label="__('Enter zen mode')"
+ :aria-label="__('Leave zen mode')"
>
- <icon :size="32" name="screen-normal" />
+ <icon :size="16" name="screen-normal" />
</a>
<markdown-toolbar
:markdown-docs-path="markdownDocsPath"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 665637f3b9e..aa1abb5adb6 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -158,7 +158,7 @@ export default {
<div class="d-inline-block ml-md-2 ml-0">
<toolbar-button
:prepend="true"
- tag="* "
+ tag="- "
:button-title="__('Add a bullet list')"
icon="list-bulleted"
/>
@@ -170,7 +170,7 @@ export default {
/>
<toolbar-button
:prepend="true"
- tag="* [ ] "
+ tag="- [ ] "
:button-title="__('Add a task list')"
icon="list-task"
/>
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 a7cd292e01d..6dac448d5de 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -13,6 +13,11 @@ export default {
type: Object,
required: true,
},
+ batchSuggestionsInfo: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
disabled: {
type: Boolean,
required: false,
@@ -24,6 +29,14 @@ export default {
},
},
computed: {
+ batchSuggestionsCount() {
+ return this.batchSuggestionsInfo.length;
+ },
+ isBatched() {
+ return Boolean(
+ this.batchSuggestionsInfo.find(({ suggestionId }) => suggestionId === this.suggestion.id),
+ );
+ },
lines() {
return selectDiffLines(this.suggestion.diff_lines);
},
@@ -32,6 +45,15 @@ export default {
applySuggestion(callback) {
this.$emit('apply', { suggestionId: this.suggestion.id, callback });
},
+ applySuggestionBatch() {
+ this.$emit('applyBatch');
+ },
+ addSuggestionToBatch() {
+ this.$emit('addToBatch', this.suggestion.id);
+ },
+ removeSuggestionFromBatch() {
+ this.$emit('removeFromBatch', this.suggestion.id);
+ },
},
};
</script>
@@ -42,8 +64,14 @@ export default {
class="qa-suggestion-diff-header js-suggestion-diff-header"
:can-apply="suggestion.appliable && suggestion.current_user.can_apply && !disabled"
:is-applied="suggestion.applied"
+ :is-batched="isBatched"
+ :is-applying-batch="suggestion.is_applying_batch"
+ :batch-suggestions-count="batchSuggestionsCount"
:help-page-path="helpPagePath"
@apply="applySuggestion"
+ @applyBatch="applySuggestionBatch"
+ @addToBatch="addSuggestionToBatch"
+ @removeFromBatch="removeSuggestionFromBatch"
/>
<table class="mb-3 md-suggestion-diff js-syntax-highlight code">
<tbody>
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 af438ce5619..e26ff51e01e 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
@@ -1,11 +1,19 @@
<script>
import { GlDeprecatedButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
+import { __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: { Icon, GlDeprecatedButton, GlLoadingIcon },
directives: { 'gl-tooltip': GlTooltipDirective },
+ mixins: [glFeatureFlagsMixin()],
props: {
+ batchSuggestionsCount: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
canApply: {
type: Boolean,
required: false,
@@ -16,6 +24,16 @@ export default {
required: true,
default: false,
},
+ isBatched: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isApplyingBatch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
helpPagePath: {
type: String,
required: true,
@@ -23,17 +41,54 @@ export default {
},
data() {
return {
- isApplying: false,
+ isApplyingSingle: false,
};
},
+ computed: {
+ canBeBatched() {
+ return Boolean(this.glFeatures.batchSuggestions);
+ },
+ isApplying() {
+ return this.isApplyingSingle || this.isApplyingBatch;
+ },
+ tooltipMessage() {
+ return this.canApply
+ ? __('This also resolves the discussion')
+ : __("Can't apply as this line has changed or the suggestion already matches its content.");
+ },
+ tooltipMessageBatch() {
+ return !this.canBeBatched
+ ? __("Suggestions that change line count can't be added to batches, yet.")
+ : this.tooltipMessage;
+ },
+ isDisableButton() {
+ return this.isApplying || !this.canApply;
+ },
+ applyingSuggestionsMessage() {
+ if (this.isApplyingSingle || this.batchSuggestionsCount < 2) {
+ return __('Applying suggestion...');
+ }
+ return __('Applying suggestions...');
+ },
+ },
methods: {
applySuggestion() {
if (!this.canApply) return;
- this.isApplying = true;
+ this.isApplyingSingle = true;
this.$emit('apply', this.applySuggestionCallback);
},
applySuggestionCallback() {
- this.isApplying = false;
+ this.isApplyingSingle = false;
+ },
+ applySuggestionBatch() {
+ if (!this.canApply) return;
+ this.$emit('applyBatch');
+ },
+ addSuggestionToBatch() {
+ this.$emit('addToBatch');
+ },
+ removeSuggestionFromBatch() {
+ this.$emit('removeFromBatch');
},
},
};
@@ -47,20 +102,52 @@ export default {
<icon name="question-o" css-classes="link-highlight" />
</a>
</div>
- <span v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</span>
- <div v-if="isApplying" class="d-flex align-items-center text-secondary">
+ <div v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</div>
+ <div v-else-if="isApplying" class="d-flex align-items-center text-secondary">
<gl-loading-icon class="d-flex-center mr-2" />
- <span>{{ __('Applying suggestion') }}</span>
+ <span>{{ applyingSuggestionsMessage }}</span>
+ </div>
+ <div v-else-if="canApply && canBeBatched && isBatched" class="d-flex align-items-center">
+ <gl-deprecated-button
+ class="btn-inverted js-remove-from-batch-btn btn-grouped"
+ :disabled="isApplying"
+ @click="removeSuggestionFromBatch"
+ >
+ {{ __('Remove from batch') }}
+ </gl-deprecated-button>
+ <gl-deprecated-button
+ v-gl-tooltip.viewport="__('This also resolves all related threads')"
+ class="btn-inverted js-apply-batch-btn btn-grouped"
+ :disabled="isApplying"
+ variant="success"
+ @click="applySuggestionBatch"
+ >
+ {{ __('Apply suggestions') }}
+ <span class="badge badge-pill badge-pill-success">
+ {{ batchSuggestionsCount }}
+ </span>
+ </gl-deprecated-button>
+ </div>
+ <div v-else class="d-flex align-items-center">
+ <span v-if="canBeBatched" v-gl-tooltip.viewport="tooltipMessageBatch" tabindex="0">
+ <gl-deprecated-button
+ class="btn-inverted js-add-to-batch-btn btn-grouped"
+ :disabled="isDisableButton"
+ @click="addSuggestionToBatch"
+ >
+ {{ __('Add suggestion to batch') }}
+ </gl-deprecated-button>
+ </span>
+ <span v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
+ <gl-deprecated-button
+ class="btn-inverted js-apply-btn btn-grouped"
+ :disabled="isDisableButton"
+ variant="success"
+ @click="applySuggestion"
+ >
+ {{ __('Apply suggestion') }}
+ </gl-deprecated-button>
+ </span>
</div>
- <gl-deprecated-button
- v-else-if="canApply"
- v-gl-tooltip.viewport="__('This also resolves the discussion')"
- class="btn-inverted js-apply-btn"
- :disabled="isApplying"
- variant="success"
- @click="applySuggestion"
- >
- {{ __('Apply suggestion') }}
- </gl-deprecated-button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 20a14d78f9b..9527c5114f2 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -16,6 +16,11 @@ export default {
required: false,
default: () => [],
},
+ batchSuggestionsInfo: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
noteHtml: {
type: String,
required: true,
@@ -68,18 +73,30 @@ export default {
this.isRendered = true;
},
generateDiff(suggestionIndex) {
- const { suggestions, disabled, helpPagePath } = this;
+ const { suggestions, disabled, batchSuggestionsInfo, helpPagePath } = this;
const suggestion =
suggestions && suggestions[suggestionIndex] ? suggestions[suggestionIndex] : {};
const SuggestionDiffComponent = Vue.extend(SuggestionDiff);
const suggestionDiff = new SuggestionDiffComponent({
- propsData: { disabled, suggestion, helpPagePath },
+ propsData: { disabled, suggestion, batchSuggestionsInfo, helpPagePath },
});
suggestionDiff.$on('apply', ({ suggestionId, callback }) => {
this.$emit('apply', { suggestionId, callback, flashContainer: this.$el });
});
+ suggestionDiff.$on('applyBatch', () => {
+ this.$emit('applyBatch', { flashContainer: this.$el });
+ });
+
+ suggestionDiff.$on('addToBatch', suggestionId => {
+ this.$emit('addToBatch', suggestionId);
+ });
+
+ suggestionDiff.$on('removeFromBatch', suggestionId => {
+ this.$emit('removeFromBatch', suggestionId);
+ });
+
return suggestionDiff;
},
reset() {
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 486d4f6b609..330785c9319 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,11 +1,13 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlLink, GlLoadingIcon, GlSprintf, GlIcon } from '@gitlab/ui';
export default {
components: {
+ GlButton,
GlLink,
GlLoadingIcon,
+ GlSprintf,
+ GlIcon,
},
props: {
markdownDocsPath: {
@@ -35,45 +37,69 @@ export default {
<div class="comment-toolbar clearfix">
<div class="toolbar-text">
<template v-if="!hasQuickActionsDocsPath && markdownDocsPath">
- <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1">{{
+ <gl-link :href="markdownDocsPath" target="_blank">{{
__('Markdown is supported')
}}</gl-link>
</template>
<template v-if="hasQuickActionsDocsPath && markdownDocsPath">
- <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1">{{
- __('Markdown')
- }}</gl-link>
- and
- <gl-link :href="quickActionsDocsPath" target="_blank" tabindex="-1">{{
- __('quick actions')
- }}</gl-link>
- are supported
+ <gl-sprintf
+ :message="
+ __(
+ '%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported',
+ )
+ "
+ >
+ <template #markdownDocsLink="{content}">
+ <gl-link :href="markdownDocsPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ <template #quickActionsDocsLink="{content}">
+ <gl-link :href="quickActionsDocsPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
</template>
</div>
<span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i>
+ <template>
+ <gl-icon name="media" :size="16" />
+ </template>
<span class="attaching-file-message"></span>
+ <!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
<span class="uploading-progress">0%</span>
<gl-loading-icon inline class="align-text-bottom" />
</span>
<span class="uploading-error-container hide">
<span class="uploading-error-icon">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i>
+ <template>
+ <gl-icon name="media" :size="16" />
+ </template>
</span>
<span class="uploading-error-message"></span>
- <button class="retry-uploading-link" type="button">{{ __('Try again') }}</button> or
- <button class="attach-new-file markdown-selector" type="button">
- {{ __('attach a new file') }}
- </button>
+
+ <gl-sprintf
+ :message="
+ __(
+ '%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}',
+ )
+ "
+ >
+ <template #retryButton="{content}">
+ <button class="retry-uploading-link" type="button">{{ content }}</button>
+ </template>
+ <template #newFileButton="{content}">
+ <button class="attach-new-file markdown-selector" type="button">{{ content }}</button>
+ </template>
+ </gl-sprintf>
</span>
- <button class="markdown-selector button-attach-file btn-link" tabindex="-1" type="button">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i
- ><span class="text-attach-file">{{ __('Attach a file') }}</span>
- </button>
- <button class="btn btn-default btn-sm hide button-cancel-uploading-files" type="button">
+ <gl-button class="markdown-selector button-attach-file" variant="link">
+ <template>
+ <gl-icon name="media" :size="16" />
+ </template>
+ <span class="text-attach-file">{{ __('Attach a file') }}</span>
+ </gl-button>
+ <gl-button class="btn btn-default btn-sm hide button-cancel-uploading-files" variant="link">
{{ __('Cancel') }}
- </button>
+ </gl-button>
</span>
</div>
</template>