diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/markdown')
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> |