diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared')
4 files changed, 180 insertions, 46 deletions
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue index 262584769e0..50d14282cad 100644 --- a/app/assets/javascripts/vue_shared/components/commit.vue +++ b/app/assets/javascripts/vue_shared/components/commit.vue @@ -1,6 +1,7 @@ <script> import commitIconSvg from 'icons/_icon_commit.svg'; import userAvatarLink from './user_avatar/user_avatar_link.vue'; + import tooltip from '../directives/tooltip'; export default { props: { @@ -100,17 +101,22 @@ this.author.username ? `${this.author.username}'s avatar` : null; }, }, - data() { - return { commitIconSvg }; + directives: { + tooltip, }, components: { userAvatarLink, }, + created() { + this.commitIconSvg = commitIconSvg; + }, }; </script> <template> <div class="branch-commit"> - <div v-if="hasCommitRef" class="icon-container hidden-xs"> + <div + v-if="hasCommitRef" + class="icon-container hidden-xs"> <i v-if="tag" class="fa fa-tag" @@ -126,7 +132,10 @@ <a v-if="hasCommitRef" class="ref-name hidden-xs" - :href="commitRef.ref_url"> + :href="commitRef.ref_url" + v-tooltip + data-container="body" + :title="commitRef.name"> {{commitRef.name}} </a> @@ -153,7 +162,8 @@ :img-alt="userImageAltDescription" :tooltip-text="author.username" /> - <a class="commit-row-message" + <a + class="commit-row-message" :href="commitUrl"> {{title}} </a> diff --git a/app/assets/javascripts/vue_shared/components/issue/confidential_issue_warning.vue b/app/assets/javascripts/vue_shared/components/issue/confidential_issue_warning.vue new file mode 100644 index 00000000000..397d16331d5 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/issue/confidential_issue_warning.vue @@ -0,0 +1,16 @@ +<script> + export default { + name: 'confidentialIssueWarning', + }; +</script> +<template> + <div class="confidential-issue-warning"> + <i + aria-hidden="true" + class="fa fa-eye-slash"> + </i> + <span> + This is a confidential issue. Your comment will not be visible to the public. + </span> + </div> +</template> diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 4e10bbc7408..759d30c9c7c 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -5,19 +5,30 @@ export default { props: { - markdownPreviewUrl: { + markdownPreviewPath: { type: String, required: false, default: '', }, - markdownDocs: { + markdownDocsPath: { type: String, required: true, }, + addSpacingClasses: { + type: Boolean, + required: false, + default: true, + }, + quickActionsDocsPath: { + type: String, + required: false, + }, }, data() { return { markdownPreview: '', + referencedCommands: '', + referencedUsers: '', markdownPreviewLoading: false, previewMarkdown: false, }; @@ -26,35 +37,48 @@ markdownHeader, markdownToolbar, }, + computed: { + shouldShowReferencedUsers() { + const referencedUsersThreshold = 10; + return this.referencedUsers.length >= referencedUsersThreshold; + }, + }, methods: { toggleMarkdownPreview() { this.previewMarkdown = !this.previewMarkdown; + /* + Can't use `$refs` as the component is technically in the parent component + so we access the VNode & then get the element + */ + const text = this.$slots.textarea[0].elm.value; + if (!this.previewMarkdown) { this.markdownPreview = ''; - } else { + } else if (text) { this.markdownPreviewLoading = true; - this.$http.post( - this.markdownPreviewUrl, - { - /* - Can't use `$refs` as the component is technically in the parent component - so we access the VNode & then get the element - */ - text: this.$slots.textarea[0].elm.value, - }, - ) - .then(resp => resp.json()) - .then((data) => { - this.markdownPreviewLoading = false; - this.markdownPreview = data.body; + this.$http.post(this.markdownPreviewPath, { text }) + .then(resp => resp.json()) + .then((data) => { + this.renderMarkdown(data); + }) + .catch(() => new Flash('Error loading markdown preview')); + } else { + this.renderMarkdown(); + } + }, + renderMarkdown(data = {}) { + this.markdownPreviewLoading = false; + this.markdownPreview = data.body || 'Nothing to preview.'; - this.$nextTick(() => { - $(this.$refs['markdown-preview']).renderGFM(); - }); - }) - .catch(() => new Flash('Error loading markdown preview')); + if (data.references) { + this.referencedCommands = data.references.commands; + this.referencedUsers = data.references.users; } + + this.$nextTick(() => { + $(this.$refs['markdown-preview']).renderGFM(); + }); }, }, mounted() { @@ -74,7 +98,8 @@ <template> <div - class="md-area prepend-top-default append-bottom-default js-vue-markdown-field" + class="md-area js-vue-markdown-field" + :class="{ 'prepend-top-default append-bottom-default': addSpacingClasses }" ref="gl-form"> <markdown-header :preview-markdown="previewMarkdown" @@ -94,7 +119,9 @@ </i> </a> <markdown-toolbar - :markdown-docs="markdownDocs" /> + :markdown-docs-path="markdownDocsPath" + :quick-actions-docs-path="quickActionsDocsPath" + /> </div> </div> <div @@ -108,5 +135,27 @@ Loading... </span> </div> + <template v-if="previewMarkdown && !markdownPreviewLoading"> + <div + v-if="referencedCommands" + v-html="referencedCommands" + class="referenced-commands"></div> + <div + v-if="shouldShowReferencedUsers" + class="referenced-users"> + <span> + <i + class="fa fa-exclamation-triangle" + aria-hidden="true"> + </i> + You are about to add + <strong> + <span class="js-referenced-users-count"> + {{referencedUsers.length}} + </span> + </strong> people to the discussion. Proceed with caution. + </span> + </div> + </template> </div> </template> diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue index 93252293ba6..65fe7bbd94e 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue @@ -1,10 +1,14 @@ <script> export default { props: { - markdownDocs: { + markdownDocsPath: { type: String, required: true, }, + quickActionsDocsPath: { + type: String, + required: false, + }, }, }; </script> @@ -12,22 +16,77 @@ <template> <div class="comment-toolbar clearfix"> <div class="toolbar-text"> - <a - :href="markdownDocs" - target="_blank" - tabindex="-1"> - Markdown is supported - </a> + <template v-if="!quickActionsDocsPath && markdownDocsPath"> + <a + :href="markdownDocsPath" + target="_blank" + tabindex="-1"> + Markdown is supported + </a> + </template> + <template v-if="quickActionsDocsPath && markdownDocsPath"> + <a + :href="markdownDocsPath" + target="_blank" + tabindex="-1"> + Markdown + </a> + and + <a + :href="quickActionsDocsPath" + target="_blank" + tabindex="-1"> + quick actions + </a> + are supported + </template> </div> - <button - class="toolbar-button markdown-selector" - type="button" - tabindex="-1"> - <i - class="fa fa-file-image-o toolbar-button-icon" - aria-hidden="true"> - </i> - Attach a file - </button> + <span class="uploading-container"> + <span class="uploading-progress-container hide"> + <i + class="fa fa-file-image-o toolbar-button-icon" + aria-hidden="true"></i> + <span class="attaching-file-message"></span> + <span class="uploading-progress">0%</span> + <span class="uploading-spinner"> + <i + class="fa fa-spinner fa-spin toolbar-button-icon" + aria-hidden="true"></i> + </span> + </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> + </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> + </span> + <button + class="markdown-selector button-attach-file" + tabindex="-1" + type="button"> + <i + class="fa fa-file-image-o toolbar-button-icon" + aria-hidden="true"></i> + Attach a file + </button> + <button + class="btn btn-default btn-xs hide button-cancel-uploading-files" + type="button"> + Cancel + </button> + </span> </div> </template> |