summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-12 12:09:15 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-12 12:09:15 +0000
commitd7fd035dc387e9c2e5c31bbb53d867239689cfbf (patch)
treecfa2a19998e4743be51c987f200495d80a4c4466 /app/assets
parentede2fbdc8734f095d371614d362b5ae373d6a243 (diff)
downloadgitlab-ce-d7fd035dc387e9c2e5c31bbb53d867239689cfbf.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js8
-rw-r--r--app/assets/javascripts/delete_label_modal.js16
-rw-r--r--app/assets/javascripts/jira_connect/api.js3
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list.vue96
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list_item.vue13
-rw-r--r--app/assets/javascripts/pages/groups/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/delete_label_modal.vue81
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss3
10 files changed, 179 insertions, 52 deletions
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index ca019bc4178..66e8d982113 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -4,13 +4,13 @@ import axios from '../lib/utils/axios_utils';
import { __ } from '../locale';
import DivergenceGraph from './components/divergence_graph.vue';
-export function createGraphVueApp(el, data, maxCommits) {
+export function createGraphVueApp(el, data, maxCommits, defaultBranch) {
return new Vue({
el,
render(h) {
return h(DivergenceGraph, {
props: {
- defaultBranch: 'master',
+ defaultBranch,
distance: data.distance ? parseInt(data.distance, 10) : null,
aheadCount: parseInt(data.ahead, 10),
behindCount: parseInt(data.behind, 10),
@@ -21,7 +21,7 @@ export function createGraphVueApp(el, data, maxCommits) {
});
}
-export default (endpoint) => {
+export default (endpoint, defaultBranch) => {
const names = [...document.querySelectorAll('.js-branch-item')].map(
({ dataset }) => dataset.name,
);
@@ -47,7 +47,7 @@ export default (endpoint) => {
if (!el) return;
- createGraphVueApp(el, val, maxCommits);
+ createGraphVueApp(el, val, maxCommits, defaultBranch);
});
})
.catch(() =>
diff --git a/app/assets/javascripts/delete_label_modal.js b/app/assets/javascripts/delete_label_modal.js
new file mode 100644
index 00000000000..cf7c9e7734f
--- /dev/null
+++ b/app/assets/javascripts/delete_label_modal.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue';
+
+const mountDeleteLabelModal = (optionalProps) =>
+ new Vue({
+ render(h) {
+ return h(DeleteLabelModal, {
+ props: {
+ selector: '.js-delete-label-modal-button',
+ ...optionalProps,
+ },
+ });
+ },
+ }).$mount();
+
+export default (optionalProps = {}) => mountDeleteLabelModal(optionalProps);
diff --git a/app/assets/javascripts/jira_connect/api.js b/app/assets/javascripts/jira_connect/api.js
index d78aba0a3f7..8da2ca73f9a 100644
--- a/app/assets/javascripts/jira_connect/api.js
+++ b/app/assets/javascripts/jira_connect/api.js
@@ -39,11 +39,12 @@ export const removeSubscription = async (removePath) => {
});
};
-export const fetchGroups = async (groupsPath, { page, perPage }) => {
+export const fetchGroups = async (groupsPath, { page, perPage, search }) => {
return axios.get(groupsPath, {
params: {
page,
per_page: perPage,
+ search,
},
});
};
diff --git a/app/assets/javascripts/jira_connect/components/groups_list.vue b/app/assets/javascripts/jira_connect/components/groups_list.vue
index 69f2903388c..275ff820419 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTabs, GlTab, GlLoadingIcon, GlPagination, GlAlert } from '@gitlab/ui';
+import { GlLoadingIcon, GlPagination, GlAlert, GlSearchBoxByType } from '@gitlab/ui';
import { fetchGroups } from '~/jira_connect/api';
import { defaultPerPage } from '~/jira_connect/constants';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
@@ -8,11 +8,10 @@ import GroupsListItem from './groups_list_item.vue';
export default {
components: {
- GlTabs,
- GlTab,
GlLoadingIcon,
GlPagination,
GlAlert,
+ GlSearchBoxByType,
GroupsListItem,
},
inject: {
@@ -23,7 +22,8 @@ export default {
data() {
return {
groups: [],
- isLoading: false,
+ isLoadingInitial: true,
+ isLoadingMore: false,
page: 1,
perPage: defaultPerPage,
totalItems: 0,
@@ -31,15 +31,18 @@ export default {
};
},
mounted() {
- this.loadGroups();
+ return this.loadGroups().finally(() => {
+ this.isLoadingInitial = false;
+ });
},
methods: {
- loadGroups() {
- this.isLoading = true;
+ loadGroups({ searchTerm } = {}) {
+ this.isLoadingMore = true;
- fetchGroups(this.groupsPath, {
+ return fetchGroups(this.groupsPath, {
page: this.page,
perPage: this.perPage,
+ search: searchTerm,
})
.then((response) => {
const { page, total } = parseIntPagination(normalizeHeaders(response.headers));
@@ -51,50 +54,61 @@ export default {
this.errorMessage = s__('Integrations|Failed to load namespaces. Please try again.');
})
.finally(() => {
- this.isLoading = false;
+ this.isLoadingMore = false;
});
},
+ onGroupSearch(searchTerm) {
+ return this.loadGroups({ searchTerm });
+ },
},
};
</script>
<template>
<div>
- <gl-alert v-if="errorMessage" class="gl-mb-6" variant="danger" @dismiss="errorMessage = null">
+ <gl-alert v-if="errorMessage" class="gl-mb-5" variant="danger" @dismiss="errorMessage = null">
{{ errorMessage }}
</gl-alert>
- <gl-tabs>
- <gl-tab :title="__('Groups and subgroups')" class="gl-pt-3">
- <gl-loading-icon v-if="isLoading" size="md" />
- <div v-else-if="groups.length === 0" class="gl-text-center">
- <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
- <p class="gl-mt-5">
- {{
- s__('Integrations|You must have owner or maintainer permissions to link namespaces.')
- }}
- </p>
- </div>
- <ul v-else class="gl-list-style-none gl-pl-0">
- <groups-list-item
- v-for="group in groups"
- :key="group.id"
- :group="group"
- @error="errorMessage = $event"
- />
- </ul>
+ <gl-search-box-by-type
+ class="gl-mb-5"
+ debounce="500"
+ :placeholder="__('Search by name')"
+ :is-loading="isLoadingMore"
+ @input="onGroupSearch"
+ />
+
+ <gl-loading-icon v-if="isLoadingInitial" size="md" />
+ <div v-else-if="groups.length === 0" class="gl-text-center">
+ <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
+ <p class="gl-mt-5">
+ {{ s__('Integrations|You must have owner or maintainer permissions to link namespaces.') }}
+ </p>
+ </div>
+ <ul
+ v-else
+ class="gl-list-style-none gl-pl-0 gl-border-t-1 gl-border-t-solid gl-border-t-gray-100"
+ :class="{ 'gl-opacity-5': isLoadingMore }"
+ data-testid="groups-list"
+ >
+ <groups-list-item
+ v-for="group in groups"
+ :key="group.id"
+ :group="group"
+ :disabled="isLoadingMore"
+ @error="errorMessage = $event"
+ />
+ </ul>
- <div class="gl-display-flex gl-justify-content-center gl-mt-5">
- <gl-pagination
- v-if="totalItems > perPage && groups.length > 0"
- v-model="page"
- class="gl-mb-0"
- :per-page="perPage"
- :total-items="totalItems"
- @input="loadGroups"
- />
- </div>
- </gl-tab>
- </gl-tabs>
+ <div class="gl-display-flex gl-justify-content-center gl-mt-5">
+ <gl-pagination
+ v-if="totalItems > perPage && groups.length > 0"
+ v-model="page"
+ class="gl-mb-0"
+ :per-page="perPage"
+ :total-items="totalItems"
+ @input="loadGroups"
+ />
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/components/groups_list_item.vue b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
index b8959a2a505..9c5722c44c7 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list_item.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
@@ -21,6 +21,11 @@ export default {
type: Object,
required: true,
},
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -60,7 +65,7 @@ export default {
</script>
<template>
- <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-200">
+ <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
<div class="gl-display-flex gl-align-items-center gl-py-3">
<gl-icon name="folder-o" class="gl-mr-3" />
<div class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3">
@@ -83,11 +88,13 @@ export default {
<gl-button
category="secondary"
- variant="success"
+ variant="confirm"
:loading="isLoading"
+ :disabled="disabled"
@click.prevent="onClick"
- >{{ __('Link') }}</gl-button
>
+ {{ __('Link') }}
+ </gl-button>
</div>
</div>
</li>
diff --git a/app/assets/javascripts/pages/groups/labels/index/index.js b/app/assets/javascripts/pages/groups/labels/index/index.js
index 87d522d7654..95c2c7cd7d0 100644
--- a/app/assets/javascripts/pages/groups/labels/index/index.js
+++ b/app/assets/javascripts/pages/groups/labels/index/index.js
@@ -1,3 +1,5 @@
+import initDeleteLabelModal from '~/delete_label_modal';
import initLabels from '~/init_labels';
initLabels();
+initDeleteLabelModal();
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index 52f9cbea370..45b1cfecc5a 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -5,5 +5,10 @@ import initDiverganceGraph from '~/branches/divergence_graph';
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
-initDiverganceGraph(document.querySelector('.js-branch-list').dataset.divergingCountsEndpoint);
+
+const { divergingCountsEndpoint, defaultBranch } = document.querySelector(
+ '.js-branch-list',
+).dataset;
+
+initDiverganceGraph(divergingCountsEndpoint, defaultBranch);
BranchSortDropdown();
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 9f782c07101..94ab0d64de4 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import initDeleteLabelModal from '~/delete_label_modal';
import initLabels from '~/init_labels';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
@@ -9,6 +10,7 @@ Vue.use(Translate);
const initLabelIndex = () => {
initLabels();
+ initDeleteLabelModal();
const onRequestFinished = ({ labelUrl, successful }) => {
const button = document.querySelector(
diff --git a/app/assets/javascripts/vue_shared/components/delete_label_modal.vue b/app/assets/javascripts/vue_shared/components/delete_label_modal.vue
new file mode 100644
index 00000000000..1ff0938d086
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/delete_label_modal.vue
@@ -0,0 +1,81 @@
+<script>
+import { GlModal, GlSprintf, GlButton } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+
+export default {
+ components: {
+ GlModal,
+ GlSprintf,
+ GlButton,
+ },
+ props: {
+ selector: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ labelName: '',
+ subjectName: '',
+ destroyPath: '',
+ modalId: uniqueId('modal-delete-label-'),
+ };
+ },
+ mounted() {
+ document.querySelectorAll(this.selector).forEach((button) => {
+ button.addEventListener('click', (e) => {
+ e.preventDefault();
+
+ const { labelName, subjectName, destroyPath } = button.dataset;
+ this.labelName = labelName;
+ this.subjectName = subjectName;
+ this.destroyPath = destroyPath;
+ this.openModal();
+ });
+ });
+ },
+ methods: {
+ openModal() {
+ this.$refs.modal.show();
+ },
+ closeModal() {
+ this.$refs.modal.hide();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal ref="modal" :modal-id="modalId">
+ <template #modal-title>
+ <gl-sprintf :message="__('Delete label: %{labelName}')">
+ <template #labelName>
+ {{ labelName }}
+ </template>
+ </gl-sprintf>
+ </template>
+ <gl-sprintf
+ :message="
+ __(
+ `%{strongStart}${labelName}%{strongEnd} will be permanently deleted from ${subjectName}. This cannot be undone.`,
+ )
+ "
+ >
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ <template #modal-footer>
+ <gl-button category="secondary" @click="closeModal">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ category="primary"
+ variant="danger"
+ :href="destroyPath"
+ data-method="delete"
+ data-testid="delete-button"
+ >{{ __('Delete label') }}</gl-button
+ >
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index eb2dd6e578e..346cdbb9a8d 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -4,7 +4,6 @@
@import 'bootstrap-vue/src/index';
@import '@gitlab/ui/src/scss/utilities';
-@import '@gitlab/ui/src/components/base/alert/alert';
// We should only import styles that we actually use.
@import '@gitlab/ui/src/components/base/alert/alert';
@@ -16,8 +15,8 @@
@import '@gitlab/ui/src/components/base/loading_icon/loading_icon';
@import '@gitlab/ui/src/components/base/modal/modal';
@import '@gitlab/ui/src/components/base/pagination/pagination';
-@import '@gitlab/ui/src/components/base/tabs/tabs/tabs';
@import '@gitlab/ui/src/components/base/tooltip/tooltip';
+@import '@gitlab/ui/src/components/base/search_box_by_type/search_box_by_type';
$atlaskit-border-color: #dfe1e6;
$header-height: 40px;