mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-14 12:25:17 +00:00
Nested filter fixes (#2123)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
parent
0cadc19331
commit
41ebded8c9
@ -120,25 +120,6 @@ export function createModel (builder: Builder): void {
|
||||
hr.action.EditDepartment
|
||||
)
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: view.actionImpl.ShowPopup,
|
||||
actionProps: {
|
||||
component: hr.component.DepartmentStaff,
|
||||
element: 'float'
|
||||
},
|
||||
label: hr.string.ShowEmployees,
|
||||
icon: contact.icon.Person,
|
||||
keyBinding: ['m'],
|
||||
input: 'any',
|
||||
category: hr.category.HR,
|
||||
target: hr.class.Department,
|
||||
context: { mode: 'context', application: hr.app.HR, group: 'top' }
|
||||
},
|
||||
hr.action.ShowEmployees
|
||||
)
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
|
@ -23,8 +23,7 @@ import { Action, ActionCategory } from '@anticrm/view'
|
||||
export default mergeIds(hrId, hr, {
|
||||
string: {
|
||||
HRApplication: '' as IntlString,
|
||||
Departments: '' as IntlString,
|
||||
ShowEmployees: '' as IntlString
|
||||
Departments: '' as IntlString
|
||||
},
|
||||
component: {
|
||||
Structure: '' as AnyComponent,
|
||||
@ -37,7 +36,6 @@ export default mergeIds(hrId, hr, {
|
||||
},
|
||||
action: {
|
||||
EditDepartment: '' as Ref<Action>,
|
||||
ShowEmployees: '' as Ref<Action>,
|
||||
DeleteDepartment: '' as Ref<Action>
|
||||
}
|
||||
})
|
||||
|
@ -60,9 +60,6 @@ export default mergeIds(viewId, view, {
|
||||
Open: '' as ViewAction
|
||||
},
|
||||
component: {
|
||||
ObjectFilter: '' as AnyComponent,
|
||||
ValueFilter: '' as AnyComponent,
|
||||
TimestampFilter: '' as AnyComponent,
|
||||
StringEditor: '' as AnyComponent,
|
||||
StringEditorPopup: '' as AnyComponent,
|
||||
StringPresenter: '' as AnyComponent,
|
||||
|
@ -28,13 +28,21 @@
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let labelProps: Record<string, any> = {}
|
||||
export let withHover: boolean = false
|
||||
export let element: HTMLElement | undefined = undefined
|
||||
|
||||
let element: HTMLElement
|
||||
let optionsMod: LabelAndProps
|
||||
$: optionsMod = { component: options.component ?? Menu, props, element, kind: 'submenu' }
|
||||
</script>
|
||||
|
||||
<div bind:this={element} use:tooltip={optionsMod} class="antiPopup-submenu" class:withHover tabindex={focusIndex}>
|
||||
<div
|
||||
bind:this={element}
|
||||
on:keydown
|
||||
on:click
|
||||
use:tooltip={optionsMod}
|
||||
class="antiPopup-submenu"
|
||||
class:withHover
|
||||
tabindex={focusIndex}
|
||||
>
|
||||
{#if component}
|
||||
{#if typeof component === 'string'}
|
||||
<Component is={component} {props} />
|
||||
|
@ -4,7 +4,7 @@
|
||||
"ParentDepartmentLabel": "Parent department",
|
||||
"Structure":"Structure",
|
||||
"CreateDepartment": "Create department",
|
||||
"CreateDepartmentLabel": "Create department",
|
||||
"CreateDepartmentLabel": "Department",
|
||||
"DepartmentPlaceholder": "Department",
|
||||
"TeamLead": "Team lead",
|
||||
"UnAssignLead": "Unassign team lead",
|
||||
@ -15,7 +15,6 @@
|
||||
"MoveStaff": "Employee transfer",
|
||||
"MoveStaffDescr": "Do you want to transfer employee from {current} to {department}",
|
||||
"Departments": "Departments",
|
||||
"ShowEmployees": "Show employees",
|
||||
"AddEmployee": "Add employee"
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
"ParentDepartmentLabel": "Родительский департамент",
|
||||
"Structure":"Структура",
|
||||
"CreateDepartment": "Создать департамент",
|
||||
"CreateDepartmentLabel": "Создать департамент",
|
||||
"CreateDepartmentLabel": "Департамент",
|
||||
"DepartmentPlaceholder": "Департамент",
|
||||
"TeamLead": "Менеджер",
|
||||
"UnAssignLead": "Отменить назначение менеджера",
|
||||
@ -15,7 +15,6 @@
|
||||
"MoveStaff": "Перевод сотрудника",
|
||||
"MoveStaffDescr": "Вы действительно хотите перевести сотрудника из {current} в {department}",
|
||||
"Departments": "Департаменты",
|
||||
"ShowEmployees": "Просмотреть сотрудников",
|
||||
"AddEmployee": "Добавить сотрудника"
|
||||
}
|
||||
}
|
@ -13,11 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { AnyAttribute, ArrOf, AttachedDoc, Class, Collection, Doc, Ref, Type } from '@anticrm/core'
|
||||
import core, { AnyAttribute, ArrOf, AttachedDoc, Class, Collection, Doc, Ref, RefTo, Type } from '@anticrm/core'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import { Icon, Label, showPopup } from '@anticrm/ui'
|
||||
import { closePopup, closeTooltip, Icon, Label, showPopup, Submenu } from '@anticrm/ui'
|
||||
import { Filter, KeyFilter } from '@anticrm/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { FilterQuery } from '../../filter'
|
||||
import view from '../../plugin'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
@ -106,7 +107,8 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function click (type: KeyFilter): void {
|
||||
dispatch('close')
|
||||
closePopup()
|
||||
closeTooltip()
|
||||
|
||||
showPopup(
|
||||
type.component,
|
||||
@ -122,28 +124,78 @@
|
||||
target
|
||||
)
|
||||
}
|
||||
|
||||
function hasNested (type: KeyFilter): boolean {
|
||||
const targetClass = (hierarchy.getAttribute(_class, type.key).type as RefTo<Doc>).to
|
||||
const clazz = hierarchy.getClass(targetClass)
|
||||
return hierarchy.hasMixin(clazz, view.mixin.ClassFilters)
|
||||
}
|
||||
|
||||
function setNestedFilter (type: KeyFilter, e: Filter | undefined) {
|
||||
const filter: Filter = {
|
||||
value: [],
|
||||
key: type,
|
||||
index,
|
||||
mode: view.filter.FilterNestedMatch,
|
||||
modes: [view.filter.FilterNestedMatch, view.filter.FilterNestedDontMatch],
|
||||
onRemove: () => {
|
||||
FilterQuery.remove(index)
|
||||
}
|
||||
}
|
||||
if (e === undefined || filter === undefined) return
|
||||
filter.nested = e
|
||||
filter.value = e.value
|
||||
onChange(filter)
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
function getNestedProps (type: KeyFilter): any {
|
||||
const targetClass = (hierarchy.getAttribute(_class, type.key).type as RefTo<Doc>).to
|
||||
return {
|
||||
_class: targetClass,
|
||||
index: index,
|
||||
target,
|
||||
onChange: (e: Filter | undefined) => {
|
||||
setNestedFilter(type, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="selectPopup">
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each getTypes(_class) as type, i}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
class="menu-item withIcon"
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={(event) => {
|
||||
event.currentTarget.focus()
|
||||
}}
|
||||
on:click={(event) => {
|
||||
click(type)
|
||||
}}
|
||||
>
|
||||
{#if type.icon}
|
||||
<div class="icon"><Icon icon={type.icon} size={'small'} /></div>
|
||||
{/if}
|
||||
<div class="ml-3 pr-1"><Label label={type.label} /></div>
|
||||
</button>
|
||||
{#if filter === undefined && type.component === view.component.ObjectFilter && hasNested(type)}
|
||||
<Submenu
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:click={(event) => {
|
||||
click(type)
|
||||
}}
|
||||
icon={type.icon}
|
||||
label={type.label}
|
||||
props={getNestedProps(type)}
|
||||
options={{ component: view.component.FilterTypePopup }}
|
||||
withHover
|
||||
/>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
class="menu-item withIcon"
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={(event) => {
|
||||
event.currentTarget.focus()
|
||||
}}
|
||||
on:click={(event) => {
|
||||
click(type)
|
||||
}}
|
||||
>
|
||||
{#if type.icon}
|
||||
<div class="icon mr-3"><Icon icon={type.icon} size={'small'} /></div>
|
||||
{/if}
|
||||
<div class="pr-1"><Label label={type.label} /></div>
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,16 +16,13 @@
|
||||
import { Class, Doc, FindResult, getObjectValue, Ref, RefTo, SortingOrder } from '@anticrm/core'
|
||||
import { translate } from '@anticrm/platform'
|
||||
import presentation, { getClient } from '@anticrm/presentation'
|
||||
import ui, { Button, CheckBox, eventToHTMLElement, Label, Loading, showPopup } from '@anticrm/ui'
|
||||
import { Filter } from '@anticrm/view'
|
||||
import { onMount } from 'svelte'
|
||||
import { buildConfigLookup, getPresenter } from '../../utils'
|
||||
import view from '../../plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import task from '@anticrm/task'
|
||||
import type { State } from '@anticrm/task'
|
||||
import FilterTypePopup from './FilterTypePopup.svelte'
|
||||
import { FilterQuery } from '../../filter'
|
||||
import task from '@anticrm/task'
|
||||
import ui, { Button, CheckBox, Label, Loading } from '@anticrm/ui'
|
||||
import { Filter } from '@anticrm/view'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import view from '../../plugin'
|
||||
import { buildConfigLookup, getPresenter } from '../../utils'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let filter: Filter
|
||||
@ -136,42 +133,9 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
getValues(search)
|
||||
|
||||
$: byCriteria = hierarchy.hasMixin(clazz, view.mixin.ClassFilters)
|
||||
|
||||
function setNestedFilter (e: Filter | undefined) {
|
||||
if (e === undefined) return
|
||||
filter.nested = e
|
||||
filter.mode = view.filter.FilterNestedMatch
|
||||
filter.modes = [view.filter.FilterNestedMatch, view.filter.FilterNestedDontMatch]
|
||||
filter.value = e.value
|
||||
filter.onRemove = () => {
|
||||
FilterQuery.remove(filter.index)
|
||||
}
|
||||
onChange(filter)
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
function nestedFilter (e: MouseEvent) {
|
||||
const target = eventToHTMLElement(e)
|
||||
showPopup(
|
||||
FilterTypePopup,
|
||||
{
|
||||
_class: targetClass,
|
||||
target,
|
||||
index: filter.index,
|
||||
filter: filter.nested,
|
||||
onChange: setNestedFilter
|
||||
},
|
||||
target
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="selectPopup">
|
||||
{#if byCriteria}
|
||||
<Button shape={'round'} label={view.string.MatchCriteria} on:click={nestedFilter} />
|
||||
{/if}
|
||||
{#if clazz.sortingKey}
|
||||
<div class="header">
|
||||
<input
|
||||
|
@ -56,7 +56,6 @@ export const FilterQuery = {
|
||||
getLiveQuery (index: number): LiveQuery {
|
||||
const current = FilterQuery.queries.get(index)
|
||||
if (current !== undefined) return current
|
||||
console.error('create new query')
|
||||
const query = createQuery(true)
|
||||
this.queries.set(index, query)
|
||||
return query
|
||||
@ -89,7 +88,6 @@ export async function getRefs (filter: Filter, onUpdate: () => void): Promise<Ar
|
||||
onUpdate()
|
||||
}
|
||||
)
|
||||
console.error(refresh)
|
||||
if (!refresh) {
|
||||
resolve(FilterQuery.results.get(filter.index) ?? [])
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import FilterBar from './components/filter/FilterBar.svelte'
|
||||
import ObjectFilter from './components/filter/ObjectFilter.svelte'
|
||||
import TimestampFilter from './components/filter/TimestampFilter.svelte'
|
||||
import ValueFilter from './components/filter/ValueFilter.svelte'
|
||||
import FilterTypePopup from './components/filter/FilterTypePopup.svelte'
|
||||
import HTMLPresenter from './components/HTMLPresenter.svelte'
|
||||
import IntlStringPresenter from './components/IntlStringPresenter.svelte'
|
||||
import GithubPresenter from './components/linkPresenters/GithubPresenter.svelte'
|
||||
@ -129,7 +130,8 @@ export default async (): Promise<Resources> => ({
|
||||
ActionsPopup,
|
||||
StringEditorPopup: EditBoxPopup,
|
||||
BooleanTruePresenter,
|
||||
EnumEditor
|
||||
EnumEditor,
|
||||
FilterTypePopup
|
||||
},
|
||||
popup: {
|
||||
PositionElementAlignment
|
||||
|
@ -20,6 +20,10 @@ import view, { viewId } from '@anticrm/view'
|
||||
|
||||
export default mergeIds(viewId, view, {
|
||||
component: {
|
||||
ObjectFilter: '' as AnyComponent,
|
||||
ValueFilter: '' as AnyComponent,
|
||||
TimestampFilter: '' as AnyComponent,
|
||||
FilterTypePopup: '' as AnyComponent,
|
||||
ActionsPopup: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
|
Loading…
Reference in New Issue
Block a user