summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar/components/copy
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/sidebar/components/copy')
-rw-r--r--app/assets/javascripts/sidebar/components/copy/copy_email_to_clipboard.vue24
-rw-r--r--app/assets/javascripts/sidebar/components/copy/copyable_field.vue86
-rw-r--r--app/assets/javascripts/sidebar/components/copy/sidebar_reference_widget.vue59
3 files changed, 169 insertions, 0 deletions
diff --git a/app/assets/javascripts/sidebar/components/copy/copy_email_to_clipboard.vue b/app/assets/javascripts/sidebar/components/copy/copy_email_to_clipboard.vue
new file mode 100644
index 00000000000..96ecdc84ef5
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/copy/copy_email_to_clipboard.vue
@@ -0,0 +1,24 @@
+<script>
+import CopyableField from './copyable_field.vue';
+
+export default {
+ components: {
+ CopyableField,
+ },
+ props: {
+ issueEmailAddress: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <copyable-field
+ data-testid="copy-forward-email"
+ :name="s__('RightSidebar|Issue email')"
+ :clipboard-tooltip-text="s__('RightSidebar|Copy email address')"
+ :value="issueEmailAddress"
+ />
+</template>
diff --git a/app/assets/javascripts/sidebar/components/copy/copyable_field.vue b/app/assets/javascripts/sidebar/components/copy/copyable_field.vue
new file mode 100644
index 00000000000..6538de085b0
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/copy/copyable_field.vue
@@ -0,0 +1,86 @@
+<script>
+import { GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import { s__, __, sprintf } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+
+/**
+ * Renders an inline field, whose value can be copied to the clipboard,
+ * for use in the GitLab sidebar (issues, MRs, etc.).
+ */
+export default {
+ name: 'CopyableField',
+ components: {
+ ClipboardButton,
+ GlLoadingIcon,
+ GlSprintf,
+ },
+ props: {
+ value: {
+ type: String,
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ clipboardTooltipText: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ },
+ computed: {
+ clipboardProps() {
+ return {
+ category: 'tertiary',
+ tooltipBoundary: 'viewport',
+ tooltipPlacement: 'left',
+ text: this.value,
+ title:
+ this.clipboardTooltipText ||
+ sprintf(this.$options.i18n.clipboardTooltip, { name: this.name }),
+ };
+ },
+ loadingIconLabel() {
+ return sprintf(this.$options.i18n.loadingIconLabel, { name: this.name });
+ },
+ },
+ i18n: {
+ loadingIconLabel: __('Loading %{name}'),
+ clipboardTooltip: __('Copy %{name}'),
+ templateText: s__('Sidebar|%{name}: %{value}'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <clipboard-button
+ v-if="!isLoading"
+ css-class="sidebar-collapsed-icon js-dont-change-state gl-rounded-0! gl-hover-bg-transparent"
+ v-bind="clipboardProps"
+ />
+
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-space-between hide-collapsed"
+ >
+ <span
+ class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap"
+ :title="value"
+ >
+ <gl-sprintf :message="$options.i18n.templateText">
+ <template #name>{{ name }}</template>
+ <template #value>{{ value }}</template>
+ </gl-sprintf>
+ </span>
+
+ <gl-loading-icon v-if="isLoading" size="sm" inline :label="loadingIconLabel" />
+ <clipboard-button v-else size="small" v-bind="clipboardProps" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/copy/sidebar_reference_widget.vue b/app/assets/javascripts/sidebar/components/copy/sidebar_reference_widget.vue
new file mode 100644
index 00000000000..b7922c63c36
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/copy/sidebar_reference_widget.vue
@@ -0,0 +1,59 @@
+<script>
+import { __ } from '~/locale';
+import { referenceQueries } from '~/sidebar/constants';
+import CopyableField from './copyable_field.vue';
+
+export default {
+ components: {
+ CopyableField,
+ },
+ inject: ['fullPath', 'iid'],
+ props: {
+ issuableType: {
+ required: true,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ reference: '',
+ };
+ },
+ apollo: {
+ reference: {
+ query() {
+ return referenceQueries[this.issuableType].query;
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update(data) {
+ return data.workspace?.issuable?.reference || '';
+ },
+ error(error) {
+ this.$emit('fetch-error', {
+ message: __('An error occurred while fetching reference'),
+ error,
+ });
+ },
+ },
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.reference.loading;
+ },
+ },
+};
+</script>
+
+<template>
+ <copyable-field
+ class="sub-block"
+ :is-loading="isLoading"
+ :name="__('Reference')"
+ :value="reference"
+ />
+</template>