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:
Diffstat (limited to 'app/assets/javascripts/projects/settings')
-rw-r--r--app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue92
-rw-r--r--app/assets/javascripts/projects/settings/topics/index.js51
-rw-r--r--app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql9
3 files changed, 152 insertions, 0 deletions
diff --git a/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue
new file mode 100644
index 00000000000..e8b0e95b142
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue
@@ -0,0 +1,92 @@
+<script>
+import { GlTokenSelector, GlAvatarLabeled } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import searchProjectTopics from '../queries/project_topics_search.query.graphql';
+
+export default {
+ components: {
+ GlTokenSelector,
+ GlAvatarLabeled,
+ },
+ i18n: {
+ placeholder: s__('ProjectSettings|Search for topic'),
+ },
+ props: {
+ selected: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ apollo: {
+ topics: {
+ query: searchProjectTopics,
+ variables() {
+ return {
+ search: this.search,
+ };
+ },
+ update(data) {
+ return (
+ data.topics?.nodes.filter(
+ (topic) => !this.selectedTokens.some((token) => token.name === topic.name),
+ ) || []
+ );
+ },
+ debounce: 250,
+ },
+ },
+ data() {
+ return {
+ topics: [],
+ selectedTokens: this.selected,
+ search: '',
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.topics.loading;
+ },
+ placeholderText() {
+ return this.selectedTokens.length ? '' : this.$options.i18n.placeholder;
+ },
+ },
+ methods: {
+ handleEnter(event) {
+ // Prevent form from submitting when adding a token
+ if (event.target.value !== '') {
+ event.preventDefault();
+ }
+ },
+ filterTopics(searchTerm) {
+ this.search = searchTerm;
+ },
+ onTokensUpdate(tokens) {
+ this.$emit('update', tokens);
+ },
+ },
+};
+</script>
+<template>
+ <gl-token-selector
+ ref="tokenSelector"
+ v-model="selectedTokens"
+ :dropdown-items="topics"
+ :loading="loading"
+ allow-user-defined-tokens
+ :placeholder="placeholderText"
+ @keydown.enter="handleEnter"
+ @text-input="filterTopics"
+ @input="onTokensUpdate"
+ >
+ <template #dropdown-item-content="{ dropdownItem }">
+ <gl-avatar-labeled
+ :src="dropdownItem.avatarUrl"
+ :entity-name="dropdownItem.name"
+ :label="dropdownItem.name"
+ :size="32"
+ shape="rect"
+ />
+ </template>
+ </gl-token-selector>
+</template>
diff --git a/app/assets/javascripts/projects/settings/topics/index.js b/app/assets/javascripts/projects/settings/topics/index.js
new file mode 100644
index 00000000000..3fbd1a61abe
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/index.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import TopicsTokenSelector from './components/topics_token_selector.vue';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default () => {
+ const el = document.querySelector('.js-topics-selector');
+
+ if (!el) return null;
+
+ const { hiddenInputId } = el.dataset;
+ const hiddenInput = document.getElementById(hiddenInputId);
+
+ const selected = hiddenInput.value
+ ? hiddenInput.value.split(/,\s*/).map((token, index) => ({
+ id: index,
+ name: token,
+ }))
+ : [];
+
+ return new Vue({
+ el,
+ apolloProvider,
+ render(createElement) {
+ return createElement(TopicsTokenSelector, {
+ props: {
+ selected,
+ },
+ on: {
+ update(tokens) {
+ const value = tokens.map(({ name }) => name).join(', ');
+ hiddenInput.value = value;
+ // Dispatch `input` event so form submit button becomes active
+ hiddenInput.dispatchEvent(
+ new Event('input', {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql b/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql
new file mode 100644
index 00000000000..b193165062a
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql
@@ -0,0 +1,9 @@
+query searchProjectTopics($search: String) {
+ topics(search: $search) {
+ nodes {
+ id
+ name
+ avatarUrl
+ }
+ }
+}