debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

182 lines
4.6 KiB
Vue
Raw Normal View History

2019-02-15 15:39:39 +05:30
<script>
2021-03-11 19:13:27 +05:30
import Vue from 'vue';
2023-03-04 22:38:38 +05:30
import SafeHtml from '~/vue_shared/directives/safe_html';
2022-11-25 23:54:43 +05:30
import { createAlert } from '~/flash';
2019-09-30 21:07:59 +05:30
import { __ } from '~/locale';
2019-02-15 15:39:39 +05:30
import SuggestionDiff from './suggestion_diff.vue';
export default {
2020-11-24 15:15:51 +05:30
directives: {
SafeHtml,
},
2019-02-15 15:39:39 +05:30
props: {
lineType: {
type: String,
required: false,
default: '',
},
suggestions: {
type: Array,
required: false,
default: () => [],
},
2020-06-23 00:09:42 +05:30
batchSuggestionsInfo: {
type: Array,
required: false,
default: () => [],
},
2019-02-15 15:39:39 +05:30
noteHtml: {
type: String,
required: true,
},
disabled: {
type: Boolean,
required: false,
default: false,
},
helpPagePath: {
type: String,
required: true,
},
2021-03-08 18:12:59 +05:30
defaultCommitMessage: {
type: String,
required: true,
},
2021-01-03 14:25:43 +05:30
suggestionsCount: {
type: Number,
required: false,
default: 0,
},
2022-06-21 17:19:12 +05:30
failedToLoadMetadata: {
type: Boolean,
required: false,
default: false,
},
2019-02-15 15:39:39 +05:30
},
data() {
return {
isRendered: false,
};
},
watch: {
suggestions() {
this.reset();
},
noteHtml() {
this.reset();
},
2022-06-21 17:19:12 +05:30
failedToLoadMetadata() {
this.reset();
},
2019-02-15 15:39:39 +05:30
},
mounted() {
this.renderSuggestions();
},
2021-03-11 19:13:27 +05:30
beforeDestroy() {
if (this.suggestionsWatch) {
this.suggestionsWatch();
}
2021-11-18 22:05:49 +05:30
if (this.defaultCommitMessageWatch) {
this.defaultCommitMessageWatch();
}
2021-03-11 19:13:27 +05:30
},
2019-02-15 15:39:39 +05:30
methods: {
renderSuggestions() {
// swaps out suggestion(s) markdown with rich diff components
// (while still keeping non-suggestion markdown in place)
if (!this.noteHtml) return;
const { container } = this.$refs;
const suggestionElements = container.querySelectorAll('.js-render-suggestion');
if (this.lineType === 'old') {
2022-11-25 23:54:43 +05:30
createAlert({
2021-09-30 23:02:18 +05:30
message: __('Unable to apply suggestions to a deleted line.'),
parent: this.$el,
});
2019-02-15 15:39:39 +05:30
}
suggestionElements.forEach((suggestionEl, i) => {
const suggestionParentEl = suggestionEl.parentElement;
2019-07-07 11:18:12 +05:30
const diffComponent = this.generateDiff(i);
2019-02-15 15:39:39 +05:30
diffComponent.$mount(suggestionParentEl);
});
this.isRendered = true;
},
2019-07-07 11:18:12 +05:30
generateDiff(suggestionIndex) {
2021-03-08 18:12:59 +05:30
const {
suggestions,
disabled,
batchSuggestionsInfo,
helpPagePath,
defaultCommitMessage,
suggestionsCount,
2022-06-21 17:19:12 +05:30
failedToLoadMetadata,
2021-03-08 18:12:59 +05:30
} = this;
2019-02-15 15:39:39 +05:30
const suggestion =
suggestions && suggestions[suggestionIndex] ? suggestions[suggestionIndex] : {};
const SuggestionDiffComponent = Vue.extend(SuggestionDiff);
const suggestionDiff = new SuggestionDiffComponent({
2021-03-08 18:12:59 +05:30
propsData: {
disabled,
suggestion,
batchSuggestionsInfo,
helpPagePath,
defaultCommitMessage,
suggestionsCount,
2022-06-21 17:19:12 +05:30
failedToLoadMetadata,
2021-03-08 18:12:59 +05:30
},
2019-02-15 15:39:39 +05:30
});
2021-03-11 19:13:27 +05:30
// We're using `$watch` as `suggestionsCount` updates do not
// propagate to this component for some unknown reason while
// using a traditional prop watcher.
this.suggestionsWatch = this.$watch('suggestionsCount', () => {
suggestionDiff.suggestionsCount = this.suggestionsCount;
});
2021-11-18 22:05:49 +05:30
this.defaultCommitMessageWatch = this.$watch('defaultCommitMessage', () => {
suggestionDiff.defaultCommitMessage = this.defaultCommitMessage;
});
2021-03-08 18:12:59 +05:30
suggestionDiff.$on('apply', ({ suggestionId, callback, message }) => {
this.$emit('apply', { suggestionId, callback, flashContainer: this.$el, message });
2019-02-15 15:39:39 +05:30
});
2021-11-18 22:05:49 +05:30
suggestionDiff.$on('applyBatch', (message) => {
this.$emit('applyBatch', { message, flashContainer: this.$el });
2020-06-23 00:09:42 +05:30
});
2021-03-08 18:12:59 +05:30
suggestionDiff.$on('addToBatch', (suggestionId) => {
2020-06-23 00:09:42 +05:30
this.$emit('addToBatch', suggestionId);
});
2021-03-08 18:12:59 +05:30
suggestionDiff.$on('removeFromBatch', (suggestionId) => {
2020-06-23 00:09:42 +05:30
this.$emit('removeFromBatch', suggestionId);
});
2019-02-15 15:39:39 +05:30
return suggestionDiff;
},
reset() {
// resets the container HTML (replaces it with the updated noteHTML)
// calls `renderSuggestions` once the updated noteHTML is added to the DOM
2022-10-11 01:57:18 +05:30
// eslint-disable-next-line no-unsanitized/property
2019-02-15 15:39:39 +05:30
this.$refs.container.innerHTML = this.noteHtml;
this.isRendered = false;
this.renderSuggestions();
this.$nextTick(() => this.renderSuggestions());
},
},
};
</script>
<template>
<div>
2019-03-02 22:35:43 +05:30
<div class="flash-container js-suggestions-flash"></div>
2022-01-26 12:08:38 +05:30
<div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md suggestions"></div>
2019-02-15 15:39:39 +05:30
</div>
</template>