From 126d57884fcf6a8022967eb2b88d3f0de30f54df Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Mon, 20 Feb 2023 16:03:35 +0600 Subject: [PATCH] Channel filter (#2663) Signed-off-by: Denis Bykhov --- models/contact/src/index.ts | 24 ++++ models/contact/src/plugin.ts | 3 +- .../src/components/ChannelFilter.svelte | 110 ++++++++++++++++++ plugins/contact-resources/src/index.ts | 10 +- plugins/contact-resources/src/plugin.ts | 6 +- plugins/contact-resources/src/utils.ts | 39 ++++++- plugins/contact/src/index.ts | 6 +- 7 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 plugins/contact-resources/src/components/ChannelFilter.svelte diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts index 14f8d58aa2..0d184be0ea 100644 --- a/models/contact/src/index.ts +++ b/models/contact/src/index.ts @@ -487,6 +487,10 @@ export function createModel (builder: Builder): void { filters: ['_class', 'city', 'modifiedOn'] }) + builder.mixin(contact.class.Channel, core.class.Class, view.mixin.AttributeFilter, { + component: contact.component.ChannelFilter + }) + builder.mixin(contact.class.Contact, core.class.Class, setting.mixin.Editable, { value: true }) @@ -552,6 +556,26 @@ export function createModel (builder: Builder): void { builder.mixin(contact.class.Contact, core.class.Class, core.mixin.FullTextSearchContext, { fullTextSummary: true }) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.FilterIsEither, + result: contact.function.FilterChannelInResult + }, + contact.filter.FilterChannelIn + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.FilterIsNot, + result: contact.function.FilterChannelNinResult + }, + contact.filter.FilterChannelNin + ) } export { contactOperation } from './migration' diff --git a/models/contact/src/plugin.ts b/models/contact/src/plugin.ts index 1a701419fc..1014678772 100644 --- a/models/contact/src/plugin.ts +++ b/models/contact/src/plugin.ts @@ -46,7 +46,8 @@ export default mergeIds(contactId, contact, { EmployeeArrayEditor: '' as AnyComponent, EmployeeEditor: '' as AnyComponent, CreateEmployee: '' as AnyComponent, - AccountArrayEditor: '' as AnyComponent + AccountArrayEditor: '' as AnyComponent, + ChannelFilter: '' as AnyComponent }, string: { Persons: '' as IntlString, diff --git a/plugins/contact-resources/src/components/ChannelFilter.svelte b/plugins/contact-resources/src/components/ChannelFilter.svelte new file mode 100644 index 0000000000..02cd14b7e5 --- /dev/null +++ b/plugins/contact-resources/src/components/ChannelFilter.svelte @@ -0,0 +1,110 @@ + + + +
dispatch('changeContent')}> +
+
+ {#if objectsPromise} + + {:else} + {#each objects as element} + + {/each} + {/if} +
+
+
diff --git a/plugins/contact-resources/src/index.ts b/plugins/contact-resources/src/index.ts index f1157c6ed8..90df4123e5 100644 --- a/plugins/contact-resources/src/index.ts +++ b/plugins/contact-resources/src/index.ts @@ -54,8 +54,9 @@ import SocialEditor from './components/SocialEditor.svelte' import ContactRefPresenter from './components/ContactRefPresenter.svelte' import PersonRefPresenter from './components/PersonRefPresenter.svelte' import EmployeeRefPresenter from './components/EmployeeRefPresenter.svelte' +import ChannelFilter from './components/ChannelFilter.svelte' import contact from './plugin' -import { employeeSort } from './utils' +import { employeeSort, filterChannelInResult, filterChannelNinResult } from './utils' export { Channels, @@ -168,7 +169,8 @@ export default async (): Promise => ({ EmployeeArrayEditor, EmployeeEditor, CreateEmployee, - AccountArrayEditor + AccountArrayEditor, + ChannelFilter }, completion: { EmployeeQuery: async ( @@ -188,6 +190,8 @@ export default async (): Promise => ({ GetFileUrl: getFileUrl, GetGravatarUrl: getGravatarUrl, GetColorUrl: (uri: string) => uri, - EmployeeSort: employeeSort + EmployeeSort: employeeSort, + FilterChannelInResult: filterChannelInResult, + FilterChannelNinResult: filterChannelNinResult } }) diff --git a/plugins/contact-resources/src/plugin.ts b/plugins/contact-resources/src/plugin.ts index 0315607ec5..c0394d1ff1 100644 --- a/plugins/contact-resources/src/plugin.ts +++ b/plugins/contact-resources/src/plugin.ts @@ -16,7 +16,7 @@ import contact, { contactId } from '@hcengineering/contact' import { IntlString, mergeIds } from '@hcengineering/platform' -import { SortFunc } from '@hcengineering/view' +import { FilterFunction, SortFunc } from '@hcengineering/view' export default mergeIds(contactId, contact, { string: { @@ -66,6 +66,8 @@ export default mergeIds(contactId, contact, { NotSpecified: '' as IntlString }, function: { - EmployeeSort: '' as SortFunc + EmployeeSort: '' as SortFunc, + FilterChannelInResult: '' as FilterFunction, + FilterChannelNinResult: '' as FilterFunction } }) diff --git a/plugins/contact-resources/src/utils.ts b/plugins/contact-resources/src/utils.ts index 957d88132f..6846b2bb33 100644 --- a/plugins/contact-resources/src/utils.ts +++ b/plugins/contact-resources/src/utils.ts @@ -15,8 +15,10 @@ // import contact, { ChannelProvider, Employee, formatName } from '@hcengineering/contact' -import { Ref, Timestamp, toIdMap } from '@hcengineering/core' +import { Doc, ObjQueryType, Ref, Timestamp, toIdMap } from '@hcengineering/core' import { createQuery, getClient } from '@hcengineering/presentation' +import view, { Filter } from '@hcengineering/view' +import { FilterQuery } from '@hcengineering/view-resources' const client = getClient() const channelProviders = client.findAll(contact.class.ChannelProvider, {}) @@ -70,3 +72,38 @@ export async function employeeSort (value: Array>): Promise void): Promise> { + const result = await getRefs(filter, onUpdate) + return { $in: result } +} + +export async function filterChannelNinResult (filter: Filter, onUpdate: () => void): Promise> { + const result = await getRefs(filter, onUpdate) + return { $nin: result } +} + +export async function getRefs (filter: Filter, onUpdate: () => void): Promise>> { + const lq = FilterQuery.getLiveQuery(filter.index) + const client = getClient() + const mode = await client.findOne(view.class.FilterMode, { _id: filter.mode }) + if (mode === undefined) return [] + const promise = new Promise>>((resolve, reject) => { + const refresh = lq.query( + contact.class.Channel, + { + provider: { $in: filter.value } + }, + (refs) => { + const result = Array.from(new Set(refs.map((p) => p.attachedTo))) + FilterQuery.results.set(filter.index, result) + resolve(result) + onUpdate() + } + ) + if (!refresh) { + resolve(FilterQuery.results.get(filter.index) ?? []) + } + }) + return await promise +} diff --git a/plugins/contact/src/index.ts b/plugins/contact/src/index.ts index 305b74ec51..a389bac2ed 100644 --- a/plugins/contact/src/index.ts +++ b/plugins/contact/src/index.ts @@ -32,7 +32,7 @@ import { import type { Asset, Plugin, Resource } from '@hcengineering/platform' import { IntlString, plugin } from '@hcengineering/platform' import type { AnyComponent, IconSize } from '@hcengineering/ui' -import { ViewAction, Viewlet } from '@hcengineering/view' +import { FilterMode, ViewAction, Viewlet } from '@hcengineering/view' /** * @public @@ -283,6 +283,10 @@ const contactPlugin = plugin(contactId, { viewlet: { TableMember: '' as Ref, TableContact: '' as Ref + }, + filter: { + FilterChannelIn: '' as Ref, + FilterChannelNin: '' as Ref } })