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>2019-12-17 21:07:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-12-17 21:07:48 +0300
commite72386771751fb22245bc6604fef236a2ee130cb (patch)
tree7cf54bca933159cb177d3caa2f139f87d6d30391 /app/assets/javascripts/snippets
parentc2b98d3dbd47ab92c79c702276fe9130d9a28036 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/snippets')
-rw-r--r--app/assets/javascripts/snippets/components/app.vue29
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue241
-rw-r--r--app/assets/javascripts/snippets/fragments/author.fragment.graphql8
-rw-r--r--app/assets/javascripts/snippets/fragments/project.fragment.graphql6
-rw-r--r--app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql13
-rw-r--r--app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql5
-rw-r--r--app/assets/javascripts/snippets/queries/getSnippet.query.graphql13
-rw-r--r--app/assets/javascripts/snippets/queries/projectPermissions.query.graphql7
-rw-r--r--app/assets/javascripts/snippets/queries/snippet.query.graphql15
-rw-r--r--app/assets/javascripts/snippets/queries/userPermissions.query.graphql7
10 files changed, 326 insertions, 18 deletions
diff --git a/app/assets/javascripts/snippets/components/app.vue b/app/assets/javascripts/snippets/components/app.vue
index e3d6cdd4606..bd2cb8e4595 100644
--- a/app/assets/javascripts/snippets/components/app.vue
+++ b/app/assets/javascripts/snippets/components/app.vue
@@ -1,10 +1,16 @@
<script>
-import getSnippet from '../queries/getSnippet.query.graphql';
+import GetSnippetQuery from '../queries/snippet.query.graphql';
+import SnippetHeader from './snippet_header.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
+ components: {
+ SnippetHeader,
+ GlLoadingIcon,
+ },
apollo: {
- snippetData: {
- query: getSnippet,
+ snippet: {
+ query: GetSnippetQuery,
variables() {
return {
ids: this.snippetGid,
@@ -21,11 +27,24 @@ export default {
},
data() {
return {
- snippetData: {},
+ snippet: {},
};
},
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.snippet.loading;
+ },
+ },
};
</script>
<template>
- <div class="js-snippet-view"></div>
+ <div class="js-snippet-view">
+ <gl-loading-icon
+ v-if="isLoading"
+ :label="__('Loading snippet')"
+ :size="2"
+ class="loading-animation prepend-top-20 append-bottom-20"
+ />
+ <snippet-header v-else :snippet="snippet" />
+ </div>
</template>
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
new file mode 100644
index 00000000000..e8f1bfeaf43
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -0,0 +1,241 @@
+<script>
+import { __ } from '~/locale';
+import {
+ GlAvatar,
+ GlIcon,
+ GlSprintf,
+ GlButton,
+ GlModal,
+ GlAlert,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+} from '@gitlab/ui';
+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';
+
+export default {
+ components: {
+ GlAvatar,
+ GlIcon,
+ GlSprintf,
+ GlButton,
+ GlModal,
+ GlAlert,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+ TimeAgoTooltip,
+ },
+ apollo: {
+ canCreateSnippet: {
+ query() {
+ return this.snippet.project ? CanCreateProjectSnippet : CanCreatePersonalSnippet;
+ },
+ variables() {
+ return {
+ fullPath: this.snippet.project ? this.snippet.project.fullPath : undefined,
+ };
+ },
+ update(data) {
+ return this.snippet.project
+ ? data.project.userPermissions.createSnippet
+ : data.currentUser.userPermissions.createSnippet;
+ },
+ },
+ },
+ props: {
+ snippet: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isDeleting: false,
+ errorMessage: '',
+ canCreateSnippet: false,
+ };
+ },
+ computed: {
+ personalSnippetActions() {
+ return [
+ {
+ condition: this.snippet.userPermissions.updateSnippet,
+ text: __('Edit'),
+ href: this.editLink,
+ click: undefined,
+ variant: 'outline-info',
+ cssClass: undefined,
+ },
+ {
+ condition: this.snippet.userPermissions.adminSnippet,
+ text: __('Delete'),
+ href: undefined,
+ click: this.showDeleteModal,
+ variant: 'outline-danger',
+ cssClass: 'btn-inverted btn-danger ml-2',
+ },
+ {
+ condition: this.canCreateSnippet,
+ text: __('New snippet'),
+ href: this.snippet.project
+ ? `${this.snippet.project.webUrl}/snippets/new`
+ : '/snippets/new',
+ click: undefined,
+ variant: 'outline-success',
+ cssClass: 'btn-inverted btn-success ml-2',
+ },
+ ];
+ },
+ editLink() {
+ return `${this.snippet.webUrl}/edit`;
+ },
+ visibility() {
+ return this.snippet.visibilityLevel;
+ },
+ snippetVisibilityLevelDescription() {
+ switch (this.visibility) {
+ case 'private':
+ return this.snippet.project !== null
+ ? __('The snippet is visible only to project members.')
+ : __('The snippet is visible only to me.');
+ case 'internal':
+ return __('The snippet is visible to any logged in user.');
+ default:
+ return __('The snippet can be accessed without any authentication.');
+ }
+ },
+ visibilityLevelIcon() {
+ switch (this.visibility) {
+ case 'private':
+ return 'lock';
+ case 'internal':
+ return 'shield';
+ default:
+ return 'earth';
+ }
+ },
+ },
+ methods: {
+ redirectToSnippets() {
+ window.location.pathname = 'dashboard/snippets';
+ },
+ closeDeleteModal() {
+ this.$refs.deleteModal.hide();
+ },
+ showDeleteModal() {
+ this.$refs.deleteModal.show();
+ },
+ deleteSnippet() {
+ this.isDeleting = true;
+ this.$apollo
+ .mutate({
+ mutation: DeleteSnippetMutation,
+ variables: { id: this.snippet.id },
+ })
+ .then(() => {
+ this.isDeleting = false;
+ this.errorMessage = undefined;
+ this.closeDeleteModal();
+ this.redirectToSnippets();
+ })
+ .catch(err => {
+ this.isDeleting = false;
+ this.errorMessage = err.message;
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div class="detail-page-header">
+ <div class="detail-page-header-body">
+ <div
+ class="snippet-box qa-snippet-box has-tooltip d-flex align-items-center append-right-5 mb-1"
+ :title="snippetVisibilityLevelDescription"
+ data-container="body"
+ >
+ <span class="sr-only">
+ {{ s__(`VisibilityLevel|${visibility}`) }}
+ </span>
+ <gl-icon :name="visibilityLevelIcon" :size="14" />
+ </div>
+ <div class="creator">
+ <gl-sprintf message="Authored %{timeago} by %{author}">
+ <template #timeago>
+ <time-ago-tooltip
+ :time="snippet.createdAt"
+ tooltip-placement="bottom"
+ css-class="snippet_updated_ago"
+ />
+ </template>
+ <template #author>
+ <a :href="snippet.author.webUrl" class="d-inline">
+ <gl-avatar :size="24" :src="snippet.author.avatarUrl" />
+ <span class="bold">{{ snippet.author.name }}</span>
+ </a>
+ </template>
+ </gl-sprintf>
+ </div>
+ </div>
+
+ <div class="detail-page-header-actions">
+ <div class="d-none d-sm-block">
+ <template v-for="(action, index) in personalSnippetActions">
+ <gl-button
+ v-if="action.condition"
+ :key="index"
+ :variant="action.variant"
+ :class="action.cssClass"
+ :href="action.href || undefined"
+ @click="action.click ? action.click() : undefined"
+ >
+ {{ action.text }}
+ </gl-button>
+ </template>
+ </div>
+ <div class="d-block d-sm-none dropdown">
+ <gl-dropdown :text="__('Options')" class="w-100" toggle-class="text-center">
+ <gl-dropdown-item
+ v-for="(action, index) in personalSnippetActions"
+ :key="index"
+ :href="action.href || undefined"
+ @click="action.click ? action.click() : undefined"
+ >{{ action.text }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ </div>
+
+ <gl-modal ref="deleteModal" modal-id="delete-modal" title="Example title">
+ <template #modal-title>{{ __('Delete snippet?') }}</template>
+
+ <gl-alert v-if="errorMessage" variant="danger" class="mb-2" @dismiss="errorMessage = ''">{{
+ errorMessage
+ }}</gl-alert>
+
+ <gl-sprintf message="Are you sure you want to delete %{name}?">
+ <template #name
+ ><strong>{{ snippet.title }}</strong></template
+ >
+ </gl-sprintf>
+
+ <template #modal-footer>
+ <gl-button @click="closeDeleteModal">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ variant="danger"
+ :disabled="isDeleting"
+ data-qa-selector="delete_snippet_button"
+ @click="deleteSnippet"
+ >
+ <gl-loading-icon v-if="isDeleting" inline />
+ {{ __('Delete snippet') }}
+ </gl-button>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/snippets/fragments/author.fragment.graphql b/app/assets/javascripts/snippets/fragments/author.fragment.graphql
new file mode 100644
index 00000000000..2684bd0fa37
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/author.fragment.graphql
@@ -0,0 +1,8 @@
+fragment Author on Snippet {
+ author {
+ name,
+ avatarUrl,
+ username,
+ webUrl
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/fragments/project.fragment.graphql b/app/assets/javascripts/snippets/fragments/project.fragment.graphql
new file mode 100644
index 00000000000..7d65789c67b
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/project.fragment.graphql
@@ -0,0 +1,6 @@
+fragment Project on Snippet {
+ project {
+ fullPath
+ webUrl
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql b/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
new file mode 100644
index 00000000000..57348a422ec
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
@@ -0,0 +1,13 @@
+fragment SnippetBase on Snippet {
+ id
+ title
+ description
+ createdAt
+ updatedAt
+ visibilityLevel
+ webUrl
+ userPermissions {
+ adminSnippet
+ updateSnippet
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql
new file mode 100644
index 00000000000..0c829cbdee6
--- /dev/null
+++ b/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql
@@ -0,0 +1,5 @@
+mutation DeleteSnippet($id: ID!) {
+ destroySnippet(input: {id: $id}) {
+ errors
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/queries/getSnippet.query.graphql b/app/assets/javascripts/snippets/queries/getSnippet.query.graphql
deleted file mode 100644
index 5a5f0d05c5b..00000000000
--- a/app/assets/javascripts/snippets/queries/getSnippet.query.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-query getSnippet($ids: [ID!]) {
- snippets(ids: $ids) {
- edges {
- node {
- title
- description
- createdAt
- updatedAt
- visibility
- }
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql b/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
new file mode 100644
index 00000000000..288bd0889bf
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
@@ -0,0 +1,7 @@
+query CanCreateProjectSnippet($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ userPermissions {
+ createSnippet
+ }
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/queries/snippet.query.graphql b/app/assets/javascripts/snippets/queries/snippet.query.graphql
new file mode 100644
index 00000000000..1cb2c86c4d8
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/snippet.query.graphql
@@ -0,0 +1,15 @@
+#import '../fragments/snippetBase.fragment.graphql'
+#import '../fragments/project.fragment.graphql'
+#import '../fragments/author.fragment.graphql'
+
+query GetSnippetQuery($ids: [ID!]) {
+ snippets(ids: $ids) {
+ edges {
+ node {
+ ...SnippetBase
+ ...Project
+ ...Author
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/snippets/queries/userPermissions.query.graphql b/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
new file mode 100644
index 00000000000..f5b97b3d0f0
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
@@ -0,0 +1,7 @@
+query CanCreatePersonalSnippet {
+ currentUser {
+ userPermissions {
+ createSnippet
+ }
+ }
+} \ No newline at end of file