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>2022-07-01 12:08:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-01 12:08:29 +0300
commit4def415fbf45e0693b17ea418d378d62ab03a146 (patch)
tree48fa3f684b33eefbd37e57b7bbe1a17926825e6a /app/assets/javascripts/vue_shared/components/filtered_search_bar
parenta6dce21d917a0a359b3521ec3cef02ab3e6199cf (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/filtered_search_bar')
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_contact.fragment.graphql6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_organization.fragment.graphql4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_contacts.query.graphql28
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_organizations.query.graphql28
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue131
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue125
6 files changed, 322 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_contact.fragment.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_contact.fragment.graphql
new file mode 100644
index 00000000000..38222e4e8c2
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_contact.fragment.graphql
@@ -0,0 +1,6 @@
+fragment ContactFragment on CustomerRelationsContact {
+ id
+ firstName
+ lastName
+ email
+}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_organization.fragment.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_organization.fragment.graphql
new file mode 100644
index 00000000000..a7de3c7f7af
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/crm_organization.fragment.graphql
@@ -0,0 +1,4 @@
+fragment OrganizationFragment on CustomerRelationsOrganization {
+ id
+ name
+}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_contacts.query.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_contacts.query.graphql
new file mode 100644
index 00000000000..647aaa0f7f8
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_contacts.query.graphql
@@ -0,0 +1,28 @@
+#import "./crm_contact.fragment.graphql"
+
+query searchCrmContacts(
+ $isProject: Boolean = false
+ $fullPath: ID!
+ $searchString: String
+ $searchIds: [CustomerRelationsContactID!]
+) {
+ group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
+ contacts(search: $searchString, ids: $searchIds) {
+ nodes {
+ ...ContactFragment
+ }
+ }
+ }
+ project(fullPath: $fullPath) @include(if: $isProject) {
+ id
+ group {
+ id
+ contacts(search: $searchString, ids: $searchIds) {
+ nodes {
+ ...ContactFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_organizations.query.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_organizations.query.graphql
new file mode 100644
index 00000000000..c4f4663de45
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_crm_organizations.query.graphql
@@ -0,0 +1,28 @@
+#import "./crm_organization.fragment.graphql"
+
+query searchCrmOrganizations(
+ $isProject: Boolean = false
+ $fullPath: ID!
+ $searchString: String
+ $searchIds: [CustomerRelationsOrganizationID!]
+) {
+ group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
+ organizations(search: $searchString, ids: $searchIds) {
+ nodes {
+ ...OrganizationFragment
+ }
+ }
+ }
+ project(fullPath: $fullPath) @include(if: $isProject) {
+ id
+ group {
+ id
+ organizations(search: $searchString, ids: $searchIds) {
+ nodes {
+ ...OrganizationFragment
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue
new file mode 100644
index 00000000000..adfe0559b62
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue
@@ -0,0 +1,131 @@
+<script>
+import { GlFilteredSearchSuggestion } from '@gitlab/ui';
+
+import { ITEM_TYPE } from '~/groups/constants';
+import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
+import createFlash from '~/flash';
+import { isPositiveInteger } from '~/lib/utils/number_utils';
+import { __ } from '~/locale';
+import searchCrmContactsQuery from '../queries/search_crm_contacts.query.graphql';
+
+import { DEFAULT_NONE_ANY } from '../constants';
+
+import BaseToken from './base_token.vue';
+
+export default {
+ components: {
+ BaseToken,
+ GlFilteredSearchSuggestion,
+ },
+ props: {
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ active: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ contacts: this.config.initialContacts || [],
+ loading: false,
+ };
+ },
+ computed: {
+ defaultContacts() {
+ return this.config.defaultContacts || DEFAULT_NONE_ANY;
+ },
+ namespace() {
+ return this.config.isProject ? ITEM_TYPE.PROJECT : ITEM_TYPE.GROUP;
+ },
+ },
+ methods: {
+ getActiveContact(contacts, data) {
+ return contacts.find((contact) => {
+ return `${this.formatContactId(contact)}` === data;
+ });
+ },
+ getContactName(contact) {
+ return `${contact.firstName} ${contact.lastName}`;
+ },
+ fetchContacts(searchTerm) {
+ let searchString = null;
+ let searchId = null;
+ if (isPositiveInteger(searchTerm)) {
+ searchId = this.formatContactGraphQLId(searchTerm);
+ } else {
+ searchString = searchTerm;
+ }
+
+ this.loading = true;
+
+ this.$apollo
+ .query({
+ query: searchCrmContactsQuery,
+ variables: {
+ fullPath: this.config.fullPath,
+ searchString,
+ searchIds: searchId ? [searchId] : null,
+ isProject: this.config.isProject,
+ },
+ })
+ .then(({ data }) => {
+ this.contacts = this.config.isProject
+ ? data[this.namespace]?.group.contacts.nodes
+ : data[this.namespace]?.contacts.nodes;
+ })
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching CRM contacts.'),
+ }),
+ )
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ formatContactId(contact) {
+ return `${getIdFromGraphQLId(contact.id)}`;
+ },
+ formatContactGraphQLId(id) {
+ return convertToGraphQLId('CustomerRelations::Contact', id);
+ },
+ },
+};
+</script>
+
+<template>
+ <base-token
+ :config="config"
+ :value="value"
+ :active="active"
+ :suggestions-loading="loading"
+ :suggestions="contacts"
+ :get-active-token-value="getActiveContact"
+ :default-suggestions="defaultContacts"
+ v-bind="$attrs"
+ @fetch-suggestions="fetchContacts"
+ v-on="$listeners"
+ >
+ <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
+ {{ activeTokenValue ? getContactName(activeTokenValue) : inputValue }}
+ </template>
+ <template #suggestions-list="{ suggestions }">
+ <gl-filtered-search-suggestion
+ v-for="contact in suggestions"
+ :key="formatContactId(contact)"
+ :value="formatContactId(contact)"
+ >
+ <div>
+ <div>{{ getContactName(contact) }}</div>
+ <div class="gl-font-sm">{{ contact.email }}</div>
+ </div>
+ </gl-filtered-search-suggestion>
+ </template>
+ </base-token>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue
new file mode 100644
index 00000000000..e6ab944449e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue
@@ -0,0 +1,125 @@
+<script>
+import { GlFilteredSearchSuggestion } from '@gitlab/ui';
+
+import { ITEM_TYPE } from '~/groups/constants';
+import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
+import createFlash from '~/flash';
+import { isPositiveInteger } from '~/lib/utils/number_utils';
+import { __ } from '~/locale';
+import searchCrmOrganizationsQuery from '../queries/search_crm_organizations.query.graphql';
+
+import { DEFAULT_NONE_ANY } from '../constants';
+
+import BaseToken from './base_token.vue';
+
+export default {
+ components: {
+ BaseToken,
+ GlFilteredSearchSuggestion,
+ },
+ props: {
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ active: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ organizations: this.config.initialOrganizations || [],
+ loading: false,
+ };
+ },
+ computed: {
+ defaultOrganizations() {
+ return this.config.defaultOrganizations || DEFAULT_NONE_ANY;
+ },
+ namespace() {
+ return this.config.isProject ? ITEM_TYPE.PROJECT : ITEM_TYPE.GROUP;
+ },
+ },
+ methods: {
+ getActiveOrganization(organizations, data) {
+ return organizations.find((organization) => {
+ return `${this.formatOrganizationId(organization)}` === data;
+ });
+ },
+ fetchOrganizations(searchTerm) {
+ let searchString = null;
+ let searchId = null;
+ if (isPositiveInteger(searchTerm)) {
+ searchId = this.formatOrganizationGraphQLId(searchTerm);
+ } else {
+ searchString = searchTerm;
+ }
+
+ this.loading = true;
+
+ this.$apollo
+ .query({
+ query: searchCrmOrganizationsQuery,
+ variables: {
+ fullPath: this.config.fullPath,
+ searchString,
+ searchIds: searchId ? [searchId] : null,
+ isProject: this.config.isProject,
+ },
+ })
+ .then(({ data }) => {
+ this.organizations = this.config.isProject
+ ? data[this.namespace]?.group.organizations.nodes
+ : data[this.namespace]?.organizations.nodes;
+ })
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching CRM organizations.'),
+ }),
+ )
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ formatOrganizationId(organization) {
+ return `${getIdFromGraphQLId(organization.id)}`;
+ },
+ formatOrganizationGraphQLId(id) {
+ return convertToGraphQLId('CustomerRelations::Organization', id);
+ },
+ },
+};
+</script>
+
+<template>
+ <base-token
+ :config="config"
+ :value="value"
+ :active="active"
+ :suggestions-loading="loading"
+ :suggestions="organizations"
+ :get-active-token-value="getActiveOrganization"
+ :default-suggestions="defaultOrganizations"
+ v-bind="$attrs"
+ @fetch-suggestions="fetchOrganizations"
+ v-on="$listeners"
+ >
+ <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
+ {{ activeTokenValue ? activeTokenValue.name : inputValue }}
+ </template>
+ <template #suggestions-list="{ suggestions }">
+ <gl-filtered-search-suggestion
+ v-for="organization in suggestions"
+ :key="formatOrganizationId(organization)"
+ :value="formatOrganizationId(organization)"
+ >
+ {{ organization.name }}
+ </gl-filtered-search-suggestion>
+ </template>
+ </base-token>
+</template>