mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 11:50:56 +00:00
Channel filter (#2663)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
f71554a016
commit
126d57884f
@ -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'
|
||||
|
@ -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,
|
||||
|
110
plugins/contact-resources/src/components/ChannelFilter.svelte
Normal file
110
plugins/contact-resources/src/components/ChannelFilter.svelte
Normal file
@ -0,0 +1,110 @@
|
||||
<!--
|
||||
// Copyright © 2023 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { ChannelProvider } from '@hcengineering/contact'
|
||||
import { Class, Doc, FindResult, Ref } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Button, CheckBox, Icon, Label, Loading, resizeObserver } from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { FilterQuery } from '@hcengineering/view-resources'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import contact from '../plugin'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let filter: Filter
|
||||
export let onChange: (e: Filter) => void
|
||||
filter.onRemove = () => {
|
||||
FilterQuery.remove(filter.index)
|
||||
}
|
||||
const client = getClient()
|
||||
let selected: Ref<ChannelProvider>[] = filter.value
|
||||
const level: number = filter.props?.level ?? 0
|
||||
|
||||
filter.modes = [contact.filter.FilterChannelIn, contact.filter.FilterChannelNin]
|
||||
filter.mode = filter.mode === undefined ? filter.modes[0] : filter.mode
|
||||
|
||||
let objects: ChannelProvider[] = []
|
||||
|
||||
let objectsPromise: Promise<FindResult<ChannelProvider>> | undefined
|
||||
|
||||
async function getValues (): Promise<void> {
|
||||
if (objectsPromise) {
|
||||
await objectsPromise
|
||||
}
|
||||
objectsPromise = client.findAll(contact.class.ChannelProvider, {})
|
||||
objects = await objectsPromise
|
||||
objectsPromise = undefined
|
||||
}
|
||||
|
||||
const isSelected = (element: ChannelProvider): boolean => {
|
||||
if (selected.filter((p) => p === element._id).length > 0) return true
|
||||
return false
|
||||
}
|
||||
|
||||
const checkSelected = (element: ChannelProvider): void => {
|
||||
if (isSelected(element)) {
|
||||
selected = selected.filter((p) => p !== element._id)
|
||||
} else {
|
||||
selected = [...selected, element._id]
|
||||
}
|
||||
objects = objects
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
getValues()
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#if objectsPromise}
|
||||
<Loading />
|
||||
{:else}
|
||||
{#each objects as element}
|
||||
<button
|
||||
class="menu-item"
|
||||
on:click={() => {
|
||||
checkSelected(element)
|
||||
}}
|
||||
>
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex">
|
||||
<div class="check pointer-events-none">
|
||||
<CheckBox checked={isSelected(element)} primary />
|
||||
</div>
|
||||
{#if element.icon}
|
||||
<span class="mr-2"><Icon icon={element.icon} size="inline" /></span>
|
||||
{/if}
|
||||
<Label label={element.label} />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
shape={'round'}
|
||||
label={view.string.Apply}
|
||||
on:click={async () => {
|
||||
filter.value = [...selected]
|
||||
// Replace last one with value with level
|
||||
filter.props = { level }
|
||||
onChange(filter)
|
||||
dispatch('close')
|
||||
}}
|
||||
/>
|
||||
</div>
|
@ -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<Resources> => ({
|
||||
EmployeeArrayEditor,
|
||||
EmployeeEditor,
|
||||
CreateEmployee,
|
||||
AccountArrayEditor
|
||||
AccountArrayEditor,
|
||||
ChannelFilter
|
||||
},
|
||||
completion: {
|
||||
EmployeeQuery: async (
|
||||
@ -188,6 +190,8 @@ export default async (): Promise<Resources> => ({
|
||||
GetFileUrl: getFileUrl,
|
||||
GetGravatarUrl: getGravatarUrl,
|
||||
GetColorUrl: (uri: string) => uri,
|
||||
EmployeeSort: employeeSort
|
||||
EmployeeSort: employeeSort,
|
||||
FilterChannelInResult: filterChannelInResult,
|
||||
FilterChannelNinResult: filterChannelNinResult
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
|
@ -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<Ref<Employee>>): Promise<Array<
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function filterChannelInResult (filter: Filter, onUpdate: () => void): Promise<ObjQueryType<any>> {
|
||||
const result = await getRefs(filter, onUpdate)
|
||||
return { $in: result }
|
||||
}
|
||||
|
||||
export async function filterChannelNinResult (filter: Filter, onUpdate: () => void): Promise<ObjQueryType<any>> {
|
||||
const result = await getRefs(filter, onUpdate)
|
||||
return { $nin: result }
|
||||
}
|
||||
|
||||
export async function getRefs (filter: Filter, onUpdate: () => void): Promise<Array<Ref<Doc>>> {
|
||||
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<Array<Ref<Doc>>>((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
|
||||
}
|
||||
|
@ -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<Viewlet>,
|
||||
TableContact: '' as Ref<Viewlet>
|
||||
},
|
||||
filter: {
|
||||
FilterChannelIn: '' as Ref<FilterMode>,
|
||||
FilterChannelNin: '' as Ref<FilterMode>
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user