summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared')
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/confidential_issue_warning.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue97
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue93
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>