summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-10 09:08:10 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-10 09:08:10 +0000
commit82fa8a3d1e8466ef36b58604d20fcc145ea12118 (patch)
treec5c0286537405c2fa7719ecce3ed0d73d947c555 /app/assets
parent232655bf32cd474d54de357b65ef43d77271117c (diff)
downloadgitlab-ce-82fa8a3d1e8466ef36b58604d20fcc145ea12118.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue90
-rw-r--r--app/assets/javascripts/boards/index.js1
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js9
-rw-r--r--app/assets/javascripts/boards/queries/board.fragment.graphql4
-rw-r--r--app/assets/javascripts/boards/queries/group_boards.query.graphql13
-rw-r--r--app/assets/javascripts/boards/queries/project_boards.query.graphql13
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js14
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue26
-rw-r--r--app/assets/javascripts/snippets/components/snippet_description_edit.vue72
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue2
10 files changed, 209 insertions, 35 deletions
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 5e8b80cd959..8b44ccfd276 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -10,6 +10,11 @@ import {
} from '@gitlab/ui';
import httpStatusCodes from '~/lib/utils/http_status';
+
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import projectQuery from '../queries/project_boards.query.graphql';
+import groupQuery from '../queries/group_boards.query.graphql';
+
import boardsStore from '../stores/boards_store';
import BoardForm from './board_form.vue';
@@ -88,8 +93,9 @@ export default {
},
data() {
return {
- loading: true,
hasScrollFade: false,
+ loadingBoards: 0,
+ loadingRecentBoards: false,
scrollFadeInitialized: false,
boards: [],
recentBoards: [],
@@ -102,6 +108,12 @@ export default {
};
},
computed: {
+ parentType() {
+ return this.groupId ? 'group' : 'project';
+ },
+ loading() {
+ return this.loadingRecentBoards && this.loadingBoards;
+ },
currentPage() {
return this.state.currentPage;
},
@@ -147,49 +159,71 @@ export default {
return;
}
- const recentBoardsPromise = new Promise((resolve, reject) =>
- boardsStore
- .recentBoards()
- .then(resolve)
- .catch(err => {
- /**
- * If user is unauthorized we'd still want to resolve the
- * request to display all boards.
- */
- if (err.response.status === httpStatusCodes.UNAUTHORIZED) {
- resolve({ data: [] }); // recent boards are empty
- return;
- }
- reject(err);
- }),
- );
+ this.$apollo.addSmartQuery('boards', {
+ variables() {
+ return { fullPath: this.state.endpoints.fullPath };
+ },
+ query() {
+ return this.groupId ? groupQuery : projectQuery;
+ },
+ loadingKey: 'loadingBoards',
+ update(data) {
+ if (!data?.[this.parentType]) {
+ return [];
+ }
+ return data[this.parentType].boards.edges.map(({ node }) => ({
+ id: getIdFromGraphQLId(node.id),
+ name: node.name,
+ }));
+ },
+ });
- Promise.all([boardsStore.allBoards(), recentBoardsPromise])
- .then(([allBoards, recentBoards]) => [allBoards.data, recentBoards.data])
- .then(([allBoardsJson, recentBoardsJson]) => {
- this.loading = false;
- this.boards = allBoardsJson;
- this.recentBoards = recentBoardsJson;
+ this.loadingRecentBoards = true;
+ boardsStore
+ .recentBoards()
+ .then(res => {
+ this.recentBoards = res.data;
+ })
+ .catch(err => {
+ /**
+ * If user is unauthorized we'd still want to resolve the
+ * request to display all boards.
+ */
+ if (err?.response?.status === httpStatusCodes.UNAUTHORIZED) {
+ this.recentBoards = []; // recent boards are empty
+ return;
+ }
+ throw err;
})
.then(() => this.$nextTick()) // Wait for boards list in DOM
.then(() => {
this.setScrollFade();
})
- .catch(() => {
- this.loading = false;
+ .catch(() => {})
+ .finally(() => {
+ this.loadingRecentBoards = false;
});
},
isScrolledUp() {
const { content } = this.$refs;
+
+ if (!content) {
+ return false;
+ }
+
const currentPosition = this.contentClientHeight + content.scrollTop;
- return content && currentPosition < this.maxPosition;
+ return currentPosition < this.maxPosition;
},
initScrollFade() {
- this.scrollFadeInitialized = true;
-
const { content } = this.$refs;
+ if (!content) {
+ return;
+ }
+
+ this.scrollFadeInitialized = true;
+
this.contentClientHeight = content.clientHeight;
this.maxPosition = content.scrollHeight;
},
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index f1b481fc386..f72fc8d54b3 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -98,6 +98,7 @@ export default () => {
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
boardId: this.boardId,
+ fullPath: $boardApp.dataset.fullPath,
});
boardsStore.rootPath = this.boardsEndpoint;
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index 8d22f009784..73d37459bfe 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -1,7 +1,15 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import BoardsSelector from '~/boards/components/boards_selector.vue';
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
export default () => {
const boardsSwitcherElement = document.getElementById('js-multiple-boards-switcher');
return new Vue({
@@ -9,6 +17,7 @@ export default () => {
components: {
BoardsSelector,
},
+ apolloProvider,
data() {
const { dataset } = boardsSwitcherElement;
diff --git a/app/assets/javascripts/boards/queries/board.fragment.graphql b/app/assets/javascripts/boards/queries/board.fragment.graphql
new file mode 100644
index 00000000000..48f55e899bf
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/board.fragment.graphql
@@ -0,0 +1,4 @@
+fragment BoardFragment on Board {
+ id,
+ name
+}
diff --git a/app/assets/javascripts/boards/queries/group_boards.query.graphql b/app/assets/javascripts/boards/queries/group_boards.query.graphql
new file mode 100644
index 00000000000..74c224add7d
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/group_boards.query.graphql
@@ -0,0 +1,13 @@
+#import "ee_else_ce/boards/queries/board.fragment.graphql"
+
+query group_boards($fullPath: ID!) {
+ group(fullPath: $fullPath) {
+ boards {
+ edges {
+ node {
+ ...BoardFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/project_boards.query.graphql b/app/assets/javascripts/boards/queries/project_boards.query.graphql
new file mode 100644
index 00000000000..a1326bd5eff
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/project_boards.query.graphql
@@ -0,0 +1,13 @@
+#import "ee_else_ce/boards/queries/board.fragment.graphql"
+
+query project_boards($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ boards {
+ edges {
+ node {
+ ...BoardFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 2a5571543fb..2a2cff3d07d 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -45,7 +45,14 @@ const boardsStore = {
},
multiSelect: { list: [] },
- setEndpoints({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId, recentBoardsEndpoint }) {
+ setEndpoints({
+ boardsEndpoint,
+ listsEndpoint,
+ bulkUpdatePath,
+ boardId,
+ recentBoardsEndpoint,
+ fullPath,
+ }) {
const listsEndpointGenerate = `${listsEndpoint}/generate.json`;
this.state.endpoints = {
boardsEndpoint,
@@ -53,6 +60,7 @@ const boardsStore = {
listsEndpoint,
listsEndpointGenerate,
bulkUpdatePath,
+ fullPath,
recentBoardsEndpoint: `${recentBoardsEndpoint}.json`,
};
},
@@ -542,10 +550,6 @@ const boardsStore = {
return axios.post(endpoint);
},
- allBoards() {
- return axios.get(this.generateBoardsPath());
- },
-
recentBoards() {
return axios.get(this.state.endpoints.recentBoardsEndpoint);
},
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 6994f83bce0..faaa65b1a16 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -165,6 +165,16 @@ export default {
showContainerRegistryPublicNote() {
return this.visibilityLevel === visibilityOptions.PUBLIC;
},
+
+ repositoryHelpText() {
+ if (this.visibilityLevel === visibilityOptions.PRIVATE) {
+ return s__('ProjectSettings|View and edit files in this project');
+ }
+
+ return s__(
+ 'ProjectSettings|View and edit files in this project. Non-project members will only have read access',
+ );
+ },
},
watch: {
@@ -225,6 +235,7 @@ export default {
<div>
<div class="project-visibility-setting">
<project-setting-row
+ ref="project-visibility-settings"
:help-path="visibilityHelpPath"
:label="s__('ProjectSettings|Project visibility')"
>
@@ -270,6 +281,7 @@ export default {
</div>
<div :class="{ 'highlight-changes': highlightChangesClass }" class="project-feature-settings">
<project-setting-row
+ ref="issues-settings"
:label="s__('ProjectSettings|Issues')"
:help-text="s__('ProjectSettings|Lightweight issue tracking system for this project')"
>
@@ -280,8 +292,9 @@ export default {
/>
</project-setting-row>
<project-setting-row
+ ref="repository-settings"
:label="s__('ProjectSettings|Repository')"
- :help-text="s__('ProjectSettings|View and edit files in this project')"
+ :help-text="repositoryHelpText"
>
<project-feature-setting
v-model="repositoryAccessLevel"
@@ -291,6 +304,7 @@ export default {
</project-setting-row>
<div class="project-feature-setting-group">
<project-setting-row
+ ref="merge-request-settings"
:label="s__('ProjectSettings|Merge requests')"
:help-text="s__('ProjectSettings|Submit changes to be merged upstream')"
>
@@ -302,6 +316,7 @@ export default {
/>
</project-setting-row>
<project-setting-row
+ ref="fork-settings"
:label="s__('ProjectSettings|Forks')"
:help-text="
s__('ProjectSettings|Allow users to make copies of your repository to a new project')
@@ -315,6 +330,7 @@ export default {
/>
</project-setting-row>
<project-setting-row
+ ref="pipeline-settings"
:label="s__('ProjectSettings|Pipelines')"
:help-text="s__('ProjectSettings|Build, test, and deploy your changes')"
>
@@ -327,6 +343,7 @@ export default {
</project-setting-row>
<project-setting-row
v-if="registryAvailable"
+ ref="container-registry-settings"
:help-path="registryHelpPath"
:label="s__('ProjectSettings|Container registry')"
:help-text="
@@ -348,6 +365,7 @@ export default {
</project-setting-row>
<project-setting-row
v-if="lfsAvailable"
+ ref="git-lfs-settings"
:help-path="lfsHelpPath"
:label="s__('ProjectSettings|Git Large File Storage')"
:help-text="
@@ -362,6 +380,7 @@ export default {
</project-setting-row>
<project-setting-row
v-if="packagesAvailable"
+ ref="package-settings"
:help-path="packagesHelpPath"
:label="s__('ProjectSettings|Packages')"
:help-text="
@@ -376,6 +395,7 @@ export default {
</project-setting-row>
</div>
<project-setting-row
+ ref="wiki-settings"
:label="s__('ProjectSettings|Wiki')"
:help-text="s__('ProjectSettings|Pages for project documentation')"
>
@@ -386,6 +406,7 @@ export default {
/>
</project-setting-row>
<project-setting-row
+ ref="snippet-settings"
:label="s__('ProjectSettings|Snippets')"
:help-text="s__('ProjectSettings|Share code pastes with others out of Git repository')"
>
@@ -397,6 +418,7 @@ export default {
</project-setting-row>
<project-setting-row
v-if="pagesAvailable && pagesAccessControlEnabled"
+ ref="pages-settings"
:help-path="pagesHelpPath"
:label="s__('ProjectSettings|Pages')"
:help-text="
@@ -410,7 +432,7 @@ export default {
/>
</project-setting-row>
</div>
- <project-setting-row v-if="canDisableEmails" class="mb-3">
+ <project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3">
<label class="js-emails-disabled">
<input :value="emailsDisabled" type="hidden" name="project[emails_disabled]" />
<input v-model="emailsDisabled" type="checkbox" />
diff --git a/app/assets/javascripts/snippets/components/snippet_description_edit.vue b/app/assets/javascripts/snippets/components/snippet_description_edit.vue
new file mode 100644
index 00000000000..5b70ac5b715
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/snippet_description_edit.vue
@@ -0,0 +1,72 @@
+<script>
+import { GlFormInput } from '@gitlab/ui';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import setupCollapsibleInputs from '~/snippet/collapsible_input';
+
+export default {
+ components: {
+ GlFormInput,
+ MarkdownField,
+ },
+ props: {
+ description: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ text: this.description,
+ };
+ },
+ mounted() {
+ setupCollapsibleInputs();
+ },
+};
+</script>
+<template>
+ <div class="form-group js-description-input">
+ <label>{{ s__('Snippets|Description (optional)') }}</label>
+ <div class="js-collapsible-input">
+ <div class="js-collapsed" :class="{ 'd-none': text }">
+ <gl-form-input
+ class="form-control"
+ :placeholder="
+ s__(
+ 'Snippets|Optionally add a description about what your snippet does or how to use it…',
+ )
+ "
+ data-qa-selector="description_placeholder"
+ />
+ </div>
+ <markdown-field
+ class="js-expanded"
+ :class="{ 'd-none': !text }"
+ :markdown-preview-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ >
+ <textarea
+ id="snippet-description"
+ slot="textarea"
+ v-model="text"
+ class="note-textarea js-gfm-input js-autosize markdown-area
+ qa-description-textarea"
+ dir="auto"
+ data-supports-quick-actions="false"
+ :aria-label="__('Description')"
+ :placeholder="__('Write a comment or drag your files here…')"
+ >
+ </textarea>
+ </markdown-field>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index c8d69143f8d..df86725c025 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -212,6 +212,8 @@ export default {
return new MRWidgetService(this.getServiceEndpoints(store));
},
checkStatus(cb, isRebased) {
+ if (document.visibilityState !== 'visible') return Promise.resolve();
+
return this.service
.checkStatus()
.then(({ data }) => {