Filters_bind_fix (#2102)

Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
Denis Bykhov 2022-06-19 22:25:14 +06:00 committed by GitHub
parent 8441f0b5ab
commit d0f68cc87f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 62 additions and 84 deletions

View File

@ -29,7 +29,7 @@
showPopup,
Tooltip
} from '@anticrm/ui'
import view, { Filter, Viewlet, ViewletPreference } from '@anticrm/view'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { FilterButton, ViewletSettingButton } from '@anticrm/view-resources'
import calendar from '../plugin'
@ -43,7 +43,6 @@
export let createComponent: AnyComponent | undefined = calendar.component.CreateEvent
export let createLabel: IntlString | undefined = calendar.string.CreateEvent
let filters: Filter[] = []
const viewletQuery = createQuery()
let search = ''
let resultQuery: DocumentQuery<Event> = {}
@ -98,7 +97,7 @@
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={viewIcon} size={'small'} /></div>
<span class="ac-header__title"><Label label={viewLabel} /></span>
<div class="ml-4"><FilterButton {_class} bind:filters /></div>
<div class="ml-4"><FilterButton {_class} /></div>
</div>
{#if viewlets.length > 1}
@ -144,7 +143,6 @@
config: preference?.config ?? selectedViewlet.config,
viewlet: selectedViewlet,
query: resultQuery,
filters,
search,
createComponent
}}

View File

@ -12,7 +12,6 @@
import { SearchType } from '../utils'
import MessagesBrowser from './MessagesBrowser.svelte'
import { FilterButton } from '@anticrm/view-resources'
import { Filter } from '@anticrm/view'
let userSearch_: string = ''
userSearch.subscribe((v) => (userSearch_ = v))
@ -40,8 +39,6 @@
},
{ searchType: SearchType.Contacts, component: EmployeeBrowser, filterClass: contact.class.Employee }
]
let filters: Filter[] = []
</script>
<div class="flex-col h-full">
@ -56,14 +53,13 @@
this={components[searchType].component}
withHeader={false}
bind:search={userSearch_}
bind:filters
{...components[searchType].props}
/>
{/if}
</div>
</div>
<div class="p-3 bar">
<div class="w-32 flex-center"><FilterButton _class={components[searchType].filterClass} bind:filters /></div>
<div class="w-32 flex-center"><FilterButton _class={components[searchType].filterClass} /></div>
<div class="flex-center w-full mr-32 buttons">
<div class="ml-1 p-1 btn">
<Button
@ -92,7 +88,6 @@
selected={searchType === SearchType.Files}
on:click={() => {
searchType = SearchType.Files
filters = []
}}
/>
</div>
@ -103,7 +98,6 @@
selected={searchType === SearchType.Contacts}
on:click={() => {
searchType = SearchType.Contacts
filters = []
}}
/>
</div>

View File

@ -5,7 +5,6 @@
import core, { DocumentQuery, Ref, SortingOrder } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import { Label, Scroller, SearchEdit } from '@anticrm/ui'
import type { Filter } from '@anticrm/view'
import { FilterBar } from '@anticrm/view-resources'
import MessageComponent from './Message.svelte'
import plugin from '../plugin'
@ -17,8 +16,6 @@
let searchQuery: DocumentQuery<ChunterMessage> = { $search: search }
export let filters: Filter[] = []
function updateSearchQuery (search: string): void {
searchQuery = { $search: search }
}
@ -111,7 +108,7 @@
/>
</div>
{/if}
<FilterBar _class={filterClass} query={searchQuery} bind:filters on:change={(e) => (resultQuery = e.detail)} />
<FilterBar _class={filterClass} query={searchQuery} on:change={(e) => (resultQuery = e.detail)} />
{#if messages.length > 0}
<Scroller>
{#each messages as message}

View File

@ -17,7 +17,6 @@
import { Doc, DocumentQuery } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import type { Filter } from '@anticrm/view'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { ActionContext, FilterButton, TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import contact from '../plugin'
@ -25,7 +24,6 @@
let search = ''
let resultQuery: DocumentQuery<Doc> = {}
let filters: Filter[] = []
function updateResultQuery (search: string): void {
resultQuery = search === '' ? {} : { $search: search }
@ -75,7 +73,7 @@
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={contact.icon.Person} size={'small'} /></div>
<span class="ac-header__title"><Label label={contact.string.Contacts} /></span>
<div class="ml-4"><FilterButton _class={contact.class.Contact} bind:filters /></div>
<div class="ml-4"><FilterButton _class={contact.class.Contact} /></div>
</div>
<SearchEdit
@ -102,7 +100,6 @@
config={preference?.config ?? viewlet.config}
options={viewlet.options}
query={resultQuery}
bind:filters
showNotification
/>
{/if}

View File

@ -17,7 +17,7 @@
import { createQuery, getClient } from '@anticrm/presentation'
import { Vacancy } from '@anticrm/recruit'
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import view, { BuildModelKey, Filter, Viewlet, ViewletPreference } from '@anticrm/view'
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@anticrm/view'
import { FilterButton, TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import recruit from '../plugin'
import CreateVacancy from './CreateVacancy.svelte'
@ -88,7 +88,6 @@
])
const client = getClient()
let filters: Filter[] = []
let descr: Viewlet | undefined
let loading = true
@ -136,7 +135,7 @@
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
<span class="ac-header__title"><Label label={recruit.string.Vacancies} /></span>
<div class="ml-4"><FilterButton _class={recruit.class.Vacancy} bind:filters /></div>
<div class="ml-4"><FilterButton _class={recruit.class.Vacancy} /></div>
</div>
<SearchEdit
bind:value={search}
@ -159,7 +158,6 @@
...resultQuery,
archived: false
}}
bind:filters
showNotification
/>
{/if}

View File

@ -22,14 +22,12 @@
import { TableBrowser } from '@anticrm/view-resources'
import task from '../plugin'
import StatesBar from './state/StatesBar.svelte'
import type { Filter } from '@anticrm/view'
export let _class: Ref<Class<Task>>
export let space: Ref<SpaceWithStates>
export let options: FindOptions<Task> | undefined
export let config: string[]
export let search: string
export let filters: Filter[] = []
let doneStatusesView: boolean = false
let state: Ref<State> | undefined = undefined
@ -160,7 +158,7 @@
{/if}
</div>
<div class="statustableview-container">
<TableBrowser {_class} bind:query config={resConfig} {options} bind:filters showNotification />
<TableBrowser {_class} bind:query config={resConfig} {options} showNotification />
</div>
<style lang="scss">

View File

@ -2,7 +2,7 @@
import { Ref, WithLookup } from '@anticrm/core'
import { Team, ViewOptions } from '@anticrm/tracker'
import { Button, Icon, Tooltip, IconOptions, showPopup, eventToHTMLElement } from '@anticrm/ui'
import { Filter, Viewlet } from '@anticrm/view'
import { Viewlet } from '@anticrm/view'
import { FilterButton, setActiveViewletId } from '@anticrm/view-resources'
import tracker from '../../plugin'
import ViewOptionsPopup from './ViewOptionsPopup.svelte'
@ -11,7 +11,6 @@
export let viewlet: WithLookup<Viewlet> | undefined
export let viewlets: WithLookup<Viewlet>[] = []
export let label: string
export let filters: Filter[] = []
export let viewOptions: ViewOptions
const handleOptionsEditorOpened = (event: MouseEvent) => {
@ -29,7 +28,7 @@
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={tracker.icon.Issues} size={'small'} /></div>
<span class="ac-header__title">{label}</span>
<div class="ml-4"><FilterButton _class={tracker.class.Issue} bind:filters /></div>
<div class="ml-4"><FilterButton _class={tracker.class.Issue} /></div>
</div>
{#if viewlets.length > 1}
<div class="flex">

View File

@ -11,7 +11,7 @@
ViewOptions
} from '@anticrm/tracker'
import { Button, IconDetails } from '@anticrm/ui'
import view, { Filter, Viewlet } from '@anticrm/view'
import view, { Viewlet } from '@anticrm/view'
import { FilterBar } from '@anticrm/view-resources'
import { getActiveViewletId } from '@anticrm/view-resources/src/utils'
import tracker from '../../plugin'
@ -26,7 +26,6 @@
export let panelWidth: number = 0
let viewlet: WithLookup<Viewlet> | undefined = undefined
let filters: Filter[]
let viewOptions: ViewOptions = {
groupBy: IssuesGrouping.Status,
orderBy: IssuesOrdering.Status,
@ -78,7 +77,7 @@
</script>
{#if currentSpace}
<IssuesHeader {currentSpace} {viewlets} {label} bind:viewlet bind:viewOptions bind:filters>
<IssuesHeader {currentSpace} {viewlets} {label} bind:viewlet bind:viewOptions>
<svelte:fragment slot="extra">
{#if asideFloat && $$slots.aside}
<Button
@ -93,7 +92,7 @@
{/if}
</svelte:fragment>
</IssuesHeader>
<FilterBar _class={tracker.class.Issue} {query} bind:filters on:change={(e) => (resultQuery = e.detail)} />
<FilterBar _class={tracker.class.Issue} {query} on:change={(e) => (resultQuery = e.detail)} />
<div class="flex h-full">
<div class="antiPanel-component">
<IssuesContent {currentSpace} {viewlet} query={resultQuery} {viewOptions} />

View File

@ -16,7 +16,6 @@
import type { Class, Doc, DocumentQuery, FindOptions, Ref } from '@anticrm/core'
import { Scroller } from '@anticrm/ui'
import { BuildModelKey } from '@anticrm/view'
import type { Filter } from '@anticrm/view'
import { onMount } from 'svelte'
import { ActionContext } from '..'
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '../selection'
@ -33,7 +32,6 @@
// If defined, will show a number of dummy items before real data will appear.
export let loadingProps: LoadingProps | undefined = undefined
export let filters: Filter[] = []
let resultQuery = query
@ -56,7 +54,7 @@
}}
/>
<FilterBar {_class} {query} bind:filters on:change={(e) => (resultQuery = e.detail)} />
<FilterBar {_class} {query} on:change={(e) => (resultQuery = e.detail)} />
<Scroller tableFade>
<Table
bind:this={table}

View File

@ -19,13 +19,13 @@
import { Button, eventToHTMLElement, getCurrentLocation, IconAdd, locationToUrl, showPopup } from '@anticrm/ui'
import { Filter } from '@anticrm/view'
import { createEventDispatcher } from 'svelte'
import { filterStore } from '../../filter'
import view from '../../plugin'
import FilterSection from './FilterSection.svelte'
import FilterTypePopup from './FilterTypePopup.svelte'
export let _class: Ref<Class<Doc>>
export let query: DocumentQuery<Doc>
export let filters: Filter[] = []
const client = getClient()
const hierarchy = client.getHierarchy()
@ -36,14 +36,13 @@
function onChange (e: Filter | undefined) {
if (e === undefined) return
const index = filters.findIndex((p) => p.index === e.index)
const index = $filterStore.findIndex((p) => p.index === e.index)
if (index === -1) {
filters.push(e)
filters = filters
$filterStore.push(e)
} else {
filters[index] = e
filters = filters
$filterStore[index] = e
}
$filterStore = $filterStore
}
function add (e: MouseEvent) {
@ -63,12 +62,12 @@
$: load(_class)
function remove (i: number) {
filters[i]?.onRemove?.()
filters.splice(i, 1)
filters = filters
$filterStore[i]?.onRemove?.()
$filterStore.splice(i, 1)
$filterStore = $filterStore
}
$: saveFilters(filters)
$: saveFilters($filterStore)
function saveFilters (filters: Filter[]) {
const key = makeKey(_class)
@ -83,13 +82,13 @@
function load (_class: Ref<Class<Doc>>) {
loading = true
const oldFilters = filters
const oldFilters = $filterStore
const key = makeKey(_class)
const saved = localStorage.getItem(key)
if (saved !== null) {
filters = JSON.parse(saved)
$filterStore = JSON.parse(saved)
} else {
filters = []
$filterStore = []
}
loading = false
oldFilters.forEach((p) => p.onRemove?.())
@ -161,23 +160,23 @@
dispatch('change', newQuery)
}
$: makeQuery(query, filters)
$: makeQuery(query, $filterStore)
$: clazz = hierarchy.getClass(_class)
$: visible = hierarchy.hasMixin(clazz, view.mixin.ClassFilters)
</script>
{#if visible && filters && filters.length > 0}
{#if visible && $filterStore && $filterStore.length > 0}
<div class="filterbar-container">
<div class="filters">
{#if !loading}
{#each filters as filter, i}
{#each $filterStore as filter, i}
<FilterSection
{_class}
{filter}
on:change={() => {
makeQuery(query, filters)
saveFilters(filters)
makeQuery(query, $filterStore)
saveFilters($filterStore)
}}
on:remove={() => {
remove(i)

View File

@ -17,17 +17,17 @@
import { getClient } from '@anticrm/presentation'
import { Button, eventToHTMLElement, IconAdd, IconClose, Icon, showPopup, Label } from '@anticrm/ui'
import { Filter } from '@anticrm/view'
import { filterStore } from '../../filter'
import view from '../../plugin'
import FilterTypePopup from './FilterTypePopup.svelte'
export let _class: Ref<Class<Doc>> | undefined
export let filters: Filter[]
const client = getClient()
const hierarchy = client.getHierarchy()
function onChange (e: Filter | undefined) {
if (e !== undefined) filters = [e]
if (e !== undefined) $filterStore = [e]
}
function add (e: MouseEvent) {
@ -59,13 +59,13 @@
kind={'link-bordered'}
borderStyle={'dashed'}
on:click={(ev) => {
if (filters.length === 0) add(ev)
else filters = []
if ($filterStore.length === 0) add(ev)
else $filterStore = []
}}
>
<svelte:fragment slot="content">
<div class="flex-row-center pointer-events-none">
{#if filters.length === 0}
{#if $filterStore.length === 0}
<Icon icon={IconAdd} size={'x-small'} />
<span class="overflow-label ml-1"><Label label={view.string.Filter} /></span>
{:else}

View File

@ -0,0 +1,7 @@
import { Filter } from '@anticrm/view'
import { writable } from 'svelte/store'
/**
* @public
*/
export const filterStore = writable<Filter[]>([])

View File

@ -17,13 +17,11 @@
import type { Asset } from '@anticrm/platform'
import { Icon } from '@anticrm/ui'
import { FilterButton } from '@anticrm/view-resources'
import type { Filter } from '@anticrm/view'
export let icon: Asset | undefined
export let label: string
export let description: string | undefined
export let _class: Ref<Class<Doc>> | undefined = undefined
export let filters: Filter[] = []
</script>
<div class="ac-header__wrap-description">
@ -32,7 +30,7 @@
{#if icon}<div class="ac-header__icon"><Icon {icon} size={'small'} /></div>{/if}
<span class="ac-header__title">{label}</span>
</div>
{#if _class}<div class="ml-4"><FilterButton {_class} bind:filters /></div>{/if}
{#if _class}<div class="ml-4"><FilterButton {_class} /></div>{/if}
</div>
{#if description}<span class="ac-header__description">{description}</span>{/if}
</div>

View File

@ -39,7 +39,6 @@
import { FilterBar, FilterButton, SpacePresenter } from '@anticrm/view-resources'
import { IntlString } from '@anticrm/platform'
import { classIcon } from '../utils'
import { Filter } from '@anticrm/view'
export let _class: Ref<Class<Space>>
export let label: IntlString
@ -55,7 +54,6 @@
const sort: SortingQuery<Space> = {
name: SortingOrder.Ascending
}
export let filters: Filter[] = []
let searchQuery: DocumentQuery<Space>
let resultQuery: DocumentQuery<Space>
@ -135,10 +133,10 @@
{/if}
{#if withFilterButton}
<div class="ml-10 mt-4 mb-4">
<FilterButton {_class} bind:filters />
<FilterButton {_class} />
</div>
{/if}
<FilterBar {_class} query={searchQuery} bind:filters on:change={(e) => (resultQuery = e.detail)} />
<FilterBar {_class} query={searchQuery} on:change={(e) => (resultQuery = e.detail)} />
<Scroller padding={'2.5rem'}>
<div class="flex-col">
{#each spaces as space (space._id)}

View File

@ -18,13 +18,11 @@
import { createQuery } from '@anticrm/presentation'
import { Component, Loading } from '@anticrm/ui'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import type { Filter } from '@anticrm/view'
export let _class: Ref<Class<Doc>>
export let space: Ref<Space>
export let search: string
export let viewlet: WithLookup<Viewlet> | undefined
export let filters: Filter[] = []
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
@ -58,7 +56,6 @@
options: viewlet.options,
config: preference?.config ?? viewlet.config,
viewlet,
filters,
search
}}
/>

View File

@ -18,7 +18,6 @@
import { IntlString } from '@anticrm/platform'
import presentation, { createQuery, getClient } from '@anticrm/presentation'
import { AnyComponent, Button, Icon, IconAdd, SearchEdit, showPanel, showPopup, Tooltip } from '@anticrm/ui'
import type { Filter } from '@anticrm/view'
import view, { Viewlet } from '@anticrm/view'
import { ViewletSettingButton } from '@anticrm/view-resources'
import { createEventDispatcher } from 'svelte'
@ -33,7 +32,6 @@
export let viewlet: WithLookup<Viewlet> | undefined
export let viewlets: WithLookup<Viewlet>[] = []
export let _class: Ref<Class<Doc>> | undefined = undefined
export let filters: Filter[] = []
const client = getClient()
const hierarchy = client.getHierarchy()
@ -84,7 +82,6 @@
label={space.name}
description={space.description}
{_class}
bind:filters
on:click={onSpaceEdit}
/>
{#if viewlets.length > 1}

View File

@ -21,7 +21,6 @@
import type { ViewConfiguration } from '@anticrm/workbench'
import SpaceContent from './SpaceContent.svelte'
import SpaceHeader from './SpaceHeader.svelte'
import type { Filter } from '@anticrm/view'
export let currentSpace: Ref<Space> | undefined
export let currentView: ViewConfiguration | undefined
@ -33,7 +32,6 @@
let space: Space | undefined
let _class: Ref<Class<Doc>> | undefined = undefined
let header: AnyComponent | undefined
let filters: Filter[] = []
const client = getClient()
@ -95,10 +93,9 @@
{viewlets}
{createItemDialog}
{createItemLabel}
bind:filters
bind:search
bind:viewlet
/>
{/if}
<SpaceContent space={space._id} {_class} bind:filters bind:search {viewlet} />
<SpaceContent space={space._id} {_class} bind:search {viewlet} />
{/if}

View File

@ -17,7 +17,7 @@
import { Asset, IntlString } from '@anticrm/platform'
import { createQuery, getClient } from '@anticrm/presentation'
import { AnyComponent, Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import view, { Filter, Viewlet, ViewletDescriptor, ViewletPreference } from '@anticrm/view'
import view, { Viewlet, ViewletDescriptor, ViewletPreference } from '@anticrm/view'
import { FilterButton, TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
export let _class: Ref<Class<Doc>>
@ -29,7 +29,6 @@
export let baseQuery: DocumentQuery<Doc> = {}
let search = ''
let filters: Filter[] = []
let descr: Viewlet | undefined
$: resultQuery = updateResultQuery(search, baseQuery)
@ -80,7 +79,7 @@
<div class="ac-header__wrap-title">
<span class="ac-header__icon"><Icon {icon} size={'small'} /></span>
<span class="ac-header__title"><Label {label} /></span>
<div class="ml-4"><FilterButton {_class} bind:filters /></div>
<div class="ml-4"><FilterButton {_class} /></div>
</div>
<SearchEdit bind:value={search} />
@ -99,7 +98,6 @@
config={preference?.config ?? descr.config}
options={descr.options}
query={resultQuery}
bind:filters
showNotification
/>
{/if}

View File

@ -130,8 +130,8 @@
async function syncLoc (loc: Location): Promise<void> {
const app = loc.path.length > 1 ? (loc.path[1] as Ref<Application>) : undefined
let space = loc.path.length > 2 ? (loc.path[2] as Ref<Space>) : undefined
let special = loc.path.length > 3 ? loc.path[3] : undefined
const space = loc.path.length > 2 ? (loc.path[2] as Ref<Space>) : undefined
const special = loc.path.length > 3 ? loc.path[3] : undefined
if (currentApp !== app) {
clear(1)
@ -144,8 +144,17 @@
const last = localStorage.getItem(`platform_last_loc_${app}`)
if (last !== null) {
const newLocation: Location = JSON.parse(last)
loc.path[2] = space = newLocation.path[2] as Ref<Space>
loc.path[3] = special = newLocation.path[3]
if (newLocation.path[2] != null) {
loc.path[2] = newLocation.path[2] as Ref<Space>
loc.path[3] = newLocation.path[3]
if (loc.path[3] == null) {
loc.path.length = 3
} else {
loc.path.length = 4
}
navigate(loc)
return
}
}
}