Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /app/assets/javascripts/snippets
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'app/assets/javascripts/snippets')
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue36
-rw-r--r--app/assets/javascripts/snippets/components/embed_dropdown.vue78
-rw-r--r--app/assets/javascripts/snippets/components/show.vue12
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue7
-rw-r--r--app/assets/javascripts/snippets/components/snippet_description_view.vue1
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue7
-rw-r--r--app/assets/javascripts/snippets/components/snippet_visibility_edit.vue50
-rw-r--r--app/assets/javascripts/snippets/constants.js12
-rw-r--r--app/assets/javascripts/snippets/index.js18
-rw-r--r--app/assets/javascripts/snippets/mixins/snippets.js1
-rw-r--r--app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql5
-rw-r--r--app/assets/javascripts/snippets/utils/blob.js15
12 files changed, 201 insertions, 41 deletions
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index 0978fcc7f93..1a539aa0876 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -4,21 +4,23 @@ import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { deprecatedCreateFlash as Flash } from '~/flash';
import { __, sprintf } from '~/locale';
import TitleField from '~/vue_shared/components/form/title.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo, joinPaths } from '~/lib/utils/url_utility';
import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import { SNIPPET_MARK_EDIT_APP_START } from '~/performance_constants';
import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
import { getSnippetMixin } from '../mixins/snippets';
import {
- SNIPPET_VISIBILITY_PRIVATE,
SNIPPET_CREATE_MUTATION_ERROR,
SNIPPET_UPDATE_MUTATION_ERROR,
+ SNIPPET_VISIBILITY_PRIVATE,
} from '../constants';
+import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
+
import SnippetBlobActionsEdit from './snippet_blob_actions_edit.vue';
import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
import SnippetDescriptionEdit from './snippet_description_edit.vue';
-import { SNIPPET_MARK_EDIT_APP_START } from '~/performance_constants';
export default {
components: {
@@ -31,6 +33,15 @@ export default {
GlLoadingIcon,
},
mixins: [getSnippetMixin],
+ apollo: {
+ defaultVisibility: {
+ query: defaultVisibilityQuery,
+ manual: true,
+ result({ data: { selectedLevel } }) {
+ this.selectedLevelDefault = selectedLevel;
+ },
+ },
+ },
props: {
markdownPreviewPath: {
type: String,
@@ -56,6 +67,7 @@ export default {
isUpdating: false,
newSnippet: false,
actions: [],
+ selectedLevelDefault: SNIPPET_VISIBILITY_PRIVATE,
};
},
computed: {
@@ -88,7 +100,7 @@ export default {
},
cancelButtonHref() {
if (this.newSnippet) {
- return this.projectPath ? `/${this.projectPath}/-/snippets` : `/-/snippets`;
+ return joinPaths('/', gon.relative_url_root, this.projectPath, '-/snippets');
}
return this.snippet.webUrl;
},
@@ -98,6 +110,13 @@ export default {
descriptionFieldId() {
return `${this.isProjectSnippet ? 'project' : 'personal'}_snippet_description`;
},
+ newSnippetSchema() {
+ return {
+ title: '',
+ description: '',
+ visibilityLevel: this.selectedLevelDefault,
+ };
+ },
},
beforeCreate() {
performance.mark(SNIPPET_MARK_EDIT_APP_START);
@@ -126,7 +145,7 @@ export default {
},
onNewSnippetFetched() {
this.newSnippet = true;
- this.snippet = this.$options.newSnippetSchema;
+ this.snippet = this.newSnippetSchema;
},
onExistingSnippetFetched() {
this.newSnippet = false;
@@ -184,11 +203,6 @@ export default {
this.actions = actions;
},
},
- newSnippetSchema: {
- title: '',
- description: '',
- visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
- },
};
</script>
<template>
@@ -202,7 +216,7 @@ export default {
v-if="isLoading"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
<title-field
diff --git a/app/assets/javascripts/snippets/components/embed_dropdown.vue b/app/assets/javascripts/snippets/components/embed_dropdown.vue
new file mode 100644
index 00000000000..589754a8b19
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/embed_dropdown.vue
@@ -0,0 +1,78 @@
+<script>
+import { escape as esc } from 'lodash';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownText,
+ GlFormInputGroup,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { __ } from '~/locale';
+
+const MSG_EMBED = __('Embed');
+const MSG_SHARE = __('Share');
+const MSG_COPY = __('Copy');
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownText,
+ GlFormInputGroup,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ sections() {
+ return [
+ // eslint-disable-next-line no-useless-escape
+ { name: MSG_EMBED, value: `<script src="${esc(this.url)}.js"><\/script>` },
+ { name: MSG_SHARE, value: this.url },
+ ];
+ },
+ },
+ MSG_EMBED,
+ MSG_COPY,
+};
+</script>
+<template>
+ <gl-dropdown
+ right
+ :text="$options.MSG_EMBED"
+ menu-class="gl-px-1! gl-pb-5! gl-dropdown-menu-wide"
+ >
+ <template v-for="{ name, value } in sections">
+ <gl-dropdown-section-header :key="`header_${name}`" data-testid="header">{{
+ name
+ }}</gl-dropdown-section-header>
+ <gl-dropdown-text
+ :key="`input_${name}`"
+ tag="div"
+ class="gl-dropdown-text-py-0 gl-dropdown-text-block"
+ data-testid="input"
+ >
+ <gl-form-input-group :value="value" readonly select-on-click>
+ <template #append>
+ <gl-button
+ v-gl-tooltip.hover
+ :title="$options.MSG_COPY"
+ :data-clipboard-text="value"
+ icon="copy-to-clipboard"
+ data-qa-selector="copy_button"
+ :data-qa-action="name"
+ />
+ </template>
+ </gl-form-input-group>
+ </gl-dropdown-text>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/snippets/components/show.vue b/app/assets/javascripts/snippets/components/show.vue
index ca41fd0a2b1..43be2cb7ed8 100644
--- a/app/assets/javascripts/snippets/components/show.vue
+++ b/app/assets/javascripts/snippets/components/show.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
+import EmbedDropdown from './embed_dropdown.vue';
import SnippetHeader from './snippet_header.vue';
import SnippetTitle from './snippet_title.vue';
import SnippetBlob from './snippet_blob_view.vue';
@@ -13,7 +13,7 @@ import { SNIPPET_MARK_VIEW_APP_START } from '~/performance_constants';
export default {
components: {
- BlobEmbeddable,
+ EmbedDropdown,
SnippetHeader,
SnippetTitle,
GlLoadingIcon,
@@ -40,13 +40,17 @@ export default {
v-if="isLoading"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
<snippet-header :snippet="snippet" />
<snippet-title :snippet="snippet" />
<div class="gl-display-flex gl-justify-content-end gl-mb-5">
- <blob-embeddable v-if="embeddable" class="gl-flex-fill-1" :url="snippet.webUrl" />
+ <embed-dropdown
+ v-if="embeddable"
+ :url="snippet.webUrl"
+ data-qa-selector="snippet_embed_dropdown"
+ />
<clone-dropdown-button
v-if="canBeCloned"
class="gl-ml-3"
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index ff03432f942..f3f894ed649 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -53,7 +53,10 @@ export default {
const url = joinPaths(baseUrl, this.blob.rawPath);
axios
- .get(url)
+ .get(url, {
+ // This prevents axios from automatically JSON.parse response
+ transformResponse: [f => f],
+ })
.then(res => {
this.notifyAboutUpdates({ content: res.data });
})
@@ -80,7 +83,7 @@ export default {
v-if="!blob.isLoaded"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<blob-content-edit
v-else
diff --git a/app/assets/javascripts/snippets/components/snippet_description_view.vue b/app/assets/javascripts/snippets/components/snippet_description_view.vue
index a5107f09fc7..e462f20535b 100644
--- a/app/assets/javascripts/snippets/components/snippet_description_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_description_view.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
export default {
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index ed087dcfaf9..0ca69f3161a 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -17,6 +17,7 @@ import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DeleteSnippetMutation from '../mutations/deleteSnippet.mutation.graphql';
import CanCreatePersonalSnippet from '../queries/userPermissions.query.graphql';
import CanCreateProjectSnippet from '../queries/projectPermissions.query.graphql';
+import { joinPaths } from '~/lib/utils/url_utility';
export default {
components: {
@@ -96,8 +97,8 @@ export default {
condition: this.canCreateSnippet,
text: __('New snippet'),
href: this.snippet.project
- ? `${this.snippet.project.webUrl}/-/snippets/new`
- : '/-/snippets/new',
+ ? joinPaths(this.snippet.project.webUrl, '-/snippets/new')
+ : joinPaths('/', gon.relative_url_root, '/-/snippets/new'),
variant: 'success',
category: 'secondary',
cssClass: 'ml-2',
@@ -137,7 +138,7 @@ export default {
redirectToSnippets() {
window.location.pathname = this.snippet.project
? `${this.snippet.project.fullPath}/-/snippets`
- : 'dashboard/snippets';
+ : `${gon.relative_url_root}dashboard/snippets`;
},
closeDeleteModal() {
this.$refs.deleteModal.hide();
diff --git a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
index 299bb8fcfad..25ad7c214b2 100644
--- a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
@@ -1,11 +1,8 @@
<script>
import { GlIcon, GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
-import {
- SNIPPET_VISIBILITY,
- SNIPPET_VISIBILITY_PRIVATE,
- SNIPPET_VISIBILITY_INTERNAL,
- SNIPPET_VISIBILITY_PUBLIC,
-} from '~/snippets/constants';
+import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
+import { defaultSnippetVisibilityLevels } from '../utils/blob';
+import { SNIPPET_LEVELS_RESTRICTED, SNIPPET_LEVELS_DISABLED } from '~/snippets/constants';
export default {
components: {
@@ -15,6 +12,16 @@ export default {
GlFormRadioGroup,
GlLink,
},
+ apollo: {
+ defaultVisibility: {
+ query: defaultVisibilityQuery,
+ manual: true,
+ result({ data: { visibilityLevels, multipleLevelsRestricted } }) {
+ this.visibilityLevels = defaultSnippetVisibilityLevels(visibilityLevels);
+ this.multipleLevelsRestricted = multipleLevelsRestricted;
+ },
+ },
+ },
props: {
helpLink: {
type: String,
@@ -28,19 +35,17 @@ export default {
},
value: {
type: String,
- required: false,
- default: SNIPPET_VISIBILITY_PRIVATE,
+ required: true,
},
},
- computed: {
- visibilityOptions() {
- return [
- SNIPPET_VISIBILITY_PRIVATE,
- SNIPPET_VISIBILITY_INTERNAL,
- SNIPPET_VISIBILITY_PUBLIC,
- ].map(key => ({ value: key, ...SNIPPET_VISIBILITY[key] }));
- },
+ data() {
+ return {
+ visibilityLevels: [],
+ multipleLevelsRestricted: false,
+ };
},
+ SNIPPET_LEVELS_DISABLED,
+ SNIPPET_LEVELS_RESTRICTED,
};
</script>
<template>
@@ -51,10 +56,10 @@ export default {
><gl-icon :size="12" name="question"
/></gl-link>
</label>
- <gl-form-group id="visibility-level-setting">
- <gl-form-radio-group v-bind="$attrs" :checked="value" stacked v-on="$listeners">
+ <gl-form-group id="visibility-level-setting" class="gl-mb-0">
+ <gl-form-radio-group :checked="value" stacked v-bind="$attrs" v-on="$listeners">
<gl-form-radio
- v-for="option in visibilityOptions"
+ v-for="option in visibilityLevels"
:key="option.value"
:value="option.value"
class="mb-3"
@@ -71,5 +76,12 @@ export default {
</gl-form-radio>
</gl-form-radio-group>
</gl-form-group>
+
+ <div class="text-muted" data-testid="restricted-levels-info">
+ <template v-if="!visibilityLevels.length">{{ $options.SNIPPET_LEVELS_DISABLED }}</template>
+ <template v-else-if="multipleLevelsRestricted">{{
+ $options.SNIPPET_LEVELS_RESTRICTED
+ }}</template>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/snippets/constants.js b/app/assets/javascripts/snippets/constants.js
index 12b83525bf7..e75922df15f 100644
--- a/app/assets/javascripts/snippets/constants.js
+++ b/app/assets/javascripts/snippets/constants.js
@@ -33,3 +33,15 @@ export const SNIPPET_BLOB_ACTION_MOVE = 'move';
export const SNIPPET_BLOB_ACTION_DELETE = 'delete';
export const SNIPPET_MAX_BLOBS = 10;
+
+export const SNIPPET_LEVELS_MAP = {
+ 0: SNIPPET_VISIBILITY_PRIVATE,
+ 10: SNIPPET_VISIBILITY_INTERNAL,
+ 20: SNIPPET_VISIBILITY_PUBLIC,
+};
+export const SNIPPET_LEVELS_RESTRICTED = __(
+ 'Other visibility settings have been disabled by the administrator.',
+);
+export const SNIPPET_LEVELS_DISABLED = __(
+ 'Visibility settings have been disabled by the administrator.',
+);
diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js
index bb5e7d6e3f0..c70ad9b95f8 100644
--- a/app/assets/javascripts/snippets/index.js
+++ b/app/assets/javascripts/snippets/index.js
@@ -5,6 +5,7 @@ import createDefaultClient from '~/lib/graphql';
import SnippetsShow from './components/show.vue';
import SnippetsEdit from './components/edit.vue';
+import { SNIPPET_LEVELS_MAP, SNIPPET_VISIBILITY_PRIVATE } from '~/snippets/constants';
Vue.use(VueApollo);
Vue.use(Translate);
@@ -18,13 +19,28 @@ function appFactory(el, Component) {
defaultClient: createDefaultClient(),
});
+ const {
+ visibilityLevels = '[]',
+ selectedLevel,
+ multipleLevelsRestricted,
+ ...restDataset
+ } = el.dataset;
+
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ visibilityLevels: JSON.parse(visibilityLevels),
+ selectedLevel: SNIPPET_LEVELS_MAP[selectedLevel] ?? SNIPPET_VISIBILITY_PRIVATE,
+ multipleLevelsRestricted: 'multipleLevelsRestricted' in el.dataset,
+ },
+ });
+
return new Vue({
el,
apolloProvider,
render(createElement) {
return createElement(Component, {
props: {
- ...el.dataset,
+ ...restDataset,
},
});
},
diff --git a/app/assets/javascripts/snippets/mixins/snippets.js b/app/assets/javascripts/snippets/mixins/snippets.js
index 3f5d64a768f..15daaa8d84a 100644
--- a/app/assets/javascripts/snippets/mixins/snippets.js
+++ b/app/assets/javascripts/snippets/mixins/snippets.js
@@ -2,7 +2,6 @@ import GetSnippetQuery from '../queries/snippet.query.graphql';
const blobsDefault = [];
-// eslint-disable-next-line import/prefer-default-export
export const getSnippetMixin = {
apollo: {
snippet: {
diff --git a/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql b/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
new file mode 100644
index 00000000000..5bd6c131bab
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
@@ -0,0 +1,5 @@
+query defaultSnippetVisibility {
+ visibilityLevels @client
+ selectedLevel @client
+ multipleLevelsRestricted @client
+}
diff --git a/app/assets/javascripts/snippets/utils/blob.js b/app/assets/javascripts/snippets/utils/blob.js
index fd5ff9a3d2e..21f52671801 100644
--- a/app/assets/javascripts/snippets/utils/blob.js
+++ b/app/assets/javascripts/snippets/utils/blob.js
@@ -4,6 +4,8 @@ import {
SNIPPET_BLOB_ACTION_UPDATE,
SNIPPET_BLOB_ACTION_MOVE,
SNIPPET_BLOB_ACTION_DELETE,
+ SNIPPET_LEVELS_MAP,
+ SNIPPET_VISIBILITY,
} from '../constants';
const createLocalId = () => uniqueId('blob_local_');
@@ -64,3 +66,16 @@ export const diffAll = (blobs, origBlobs) => {
return [...deletedEntries, ...newEntries];
};
+
+export const defaultSnippetVisibilityLevels = arr => {
+ if (Array.isArray(arr)) {
+ return arr.map(l => {
+ const translatedLevel = SNIPPET_LEVELS_MAP[l];
+ return {
+ value: translatedLevel,
+ ...SNIPPET_VISIBILITY[translatedLevel],
+ };
+ });
+ }
+ return [];
+};