From 34a844fffc9c69c594ac22fb1754f423b9ac8d6b Mon Sep 17 00:00:00 2001 From: Artyom Grigorovich Date: Wed, 11 May 2022 13:52:08 +0700 Subject: [PATCH 1/4] Add new utils Signed-off-by: Artyom Grigorovich --- plugins/tracker-resources/src/utils.ts | 39 +++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts index f3dadb96dc..19d16278b3 100644 --- a/plugins/tracker-resources/src/utils.ts +++ b/plugins/tracker-resources/src/utils.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import { Ref, SortingOrder } from '@anticrm/core' +import { DocumentQuery, Ref, SortingOrder } from '@anticrm/core' import type { Asset, IntlString } from '@anticrm/platform' import { IssuePriority, @@ -147,6 +147,11 @@ export interface FilterSectionElement extends Omit { isSelected?: boolean } +export interface IssueFilter { + mode: '$in' | '$nin' + query: DocumentQuery +} + export const getGroupedIssues = ( key: IssuesGroupByKeys | undefined, elements: Issue[], @@ -186,8 +191,40 @@ export const getIssueFilterAssetsByType = (type: string): { icon: Asset, label: label: tracker.string.Status } } + case 'priority': { + return { + icon: tracker.icon.PriorityHigh, + label: tracker.string.Priority + } + } default: { return undefined } } } + +export const defaultPriorities = [ + IssuePriority.NoPriority, + IssuePriority.Urgent, + IssuePriority.High, + IssuePriority.Medium, + IssuePriority.Low +] + +export const getArraysIntersection = (a: any[], b: any[]): any[] => { + const setB = new Set(b) + const intersection = new Set(a.filter((x) => setB.has(x))) + + return Array.from(intersection) +} + +export const getArraysUnion = (a: any[], b: any[]): any[] => { + const setB = new Set(b) + const union = new Set(a) + + for (const element of setB) { + union.add(element) + } + + return Array.from(union) +} From 07f49ddd27cdc2c986d93fb4b8d9cf9d77aca3b9 Mon Sep 17 00:00:00 2001 From: Artyom Grigorovich Date: Wed, 11 May 2022 13:53:25 +0700 Subject: [PATCH 2/4] Update Issues filter menu Signed-off-by: Artyom Grigorovich --- .../src/components/FilterMenuSection.svelte | 17 ++--- .../components/issues/IssuesFilterMenu.svelte | 50 ++++++++++++--- .../issues/PriorityFilterMenuSection.svelte | 63 +++++++++++++++++++ .../issues/StatusFilterMenuSection.svelte | 23 ++++--- 4 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 plugins/tracker-resources/src/components/issues/PriorityFilterMenuSection.svelte diff --git a/plugins/tracker-resources/src/components/FilterMenuSection.svelte b/plugins/tracker-resources/src/components/FilterMenuSection.svelte index be449f1532..623ad0081b 100644 --- a/plugins/tracker-resources/src/components/FilterMenuSection.svelte +++ b/plugins/tracker-resources/src/components/FilterMenuSection.svelte @@ -18,7 +18,7 @@ import { FilterSectionElement } from '../utils' export let actions: FilterSectionElement[] = [] - export let onBack: () => void + export let onBack: (() => void) | undefined = undefined const dispatch = createEventDispatcher() const actionElements: HTMLButtonElement[] = [] @@ -28,7 +28,7 @@ const getSelectedElementsMap = (actions: FilterSectionElement[]) => { const result: { [k: number]: boolean } = {} - for (let i = 1; i < actions.length; ++i) { + for (let i = onBack ? 1 : 0; i < actions.length; ++i) { result[i] = !!actions[i].isSelected } @@ -46,7 +46,8 @@ if (event.key === 'ArrowLeft') { dispatch('close') - onBack() + + onBack?.() } } @@ -74,25 +75,27 @@ event.currentTarget.focus() }} on:click={(event) => { - if (i === 0) { + if (i === 0 && onBack) { dispatch('close') } action.onSelect(event) - if (i !== 0) { + if (i !== 0 || !onBack) { selectedElementsMap[i] = !selectedElementsMap[i] } }} >
- {#if i !== 0} + {#if i !== 0 || (i === 0 && !onBack)}
{/if} {#if action.icon} -
0}>
+
0 || (i === 0 && !onBack)}> + +
{/if} {#if action.title}
{action.title}
diff --git a/plugins/tracker-resources/src/components/issues/IssuesFilterMenu.svelte b/plugins/tracker-resources/src/components/issues/IssuesFilterMenu.svelte index 21799264c2..636e11239c 100644 --- a/plugins/tracker-resources/src/components/issues/IssuesFilterMenu.svelte +++ b/plugins/tracker-resources/src/components/issues/IssuesFilterMenu.svelte @@ -17,24 +17,35 @@ import { Issue, IssueStatus } from '@anticrm/tracker' import { showPopup } from '@anticrm/ui' import StatusFilterMenuSection from './StatusFilterMenuSection.svelte' + import PriorityFilterMenuSection from './PriorityFilterMenuSection.svelte' import FilterMenu from '../FilterMenu.svelte' - import { FilterAction, getGroupedIssues, getIssueFilterAssetsByType } from '../../utils' + import { + defaultPriorities, + FilterAction, + getGroupedIssues, + getIssueFilterAssetsByType, + IssueFilter + } from '../../utils' export let targetHtml: HTMLElement - export let currentFilter: { [p: string]: { $in: any[] } } = {} + export let filters: IssueFilter[] = [] + export let index: number = 0 export let defaultStatuses: Array> = [] export let issues: Issue[] = [] - export let onUpdate: (result: { [p: string]: any }) => void - export let onBack: () => void + export let onUpdate: (result: { [p: string]: any }, filterIndex: number) => void + export let onBack: (() => void) | undefined = undefined + $: currentFilterQuery = filters[index]?.query as { [p: string]: { $in?: any[]; $nin?: any[] } } | undefined + $: currentFilterMode = filters[index]?.mode $: defaultStatusIds = defaultStatuses.map((x) => x._id) $: groupedByStatus = getGroupedIssues('status', issues, defaultStatusIds) + $: groupedByPriority = getGroupedIssues('priority', issues, defaultPriorities) const handleStatusFilterMenuSectionOpened = (event: MouseEvent | KeyboardEvent) => { const statusGroups: { [key: string]: number } = {} - for (const defaultStatus of defaultStatuses) { - statusGroups[defaultStatus._id] = groupedByStatus[defaultStatus._id]?.length ?? 0 + for (const status of defaultStatuses) { + statusGroups[status._id] = groupedByStatus[status._id]?.length ?? 0 } showPopup( @@ -42,7 +53,28 @@ { groups: statusGroups, statuses: defaultStatuses, - selectedElements: currentFilter.status?.$in, + selectedElements: currentFilterQuery?.status?.[currentFilterMode] ?? [], + index, + onUpdate, + onBack + }, + targetHtml + ) + } + + const handlePriorityFilterMenuSectionOpened = (event: MouseEvent | KeyboardEvent) => { + const priorityGroups: { [key: string]: number } = {} + + for (const priority of defaultPriorities) { + priorityGroups[priority] = groupedByPriority[priority]?.length ?? 0 + } + + showPopup( + PriorityFilterMenuSection, + { + groups: priorityGroups, + selectedElements: currentFilterQuery?.priority?.[currentFilterMode] ?? [], + index, onUpdate, onBack }, @@ -54,6 +86,10 @@ { ...getIssueFilterAssetsByType('status'), onSelect: handleStatusFilterMenuSectionOpened + }, + { + ...getIssueFilterAssetsByType('priority'), + onSelect: handlePriorityFilterMenuSectionOpened } ] diff --git a/plugins/tracker-resources/src/components/issues/PriorityFilterMenuSection.svelte b/plugins/tracker-resources/src/components/issues/PriorityFilterMenuSection.svelte new file mode 100644 index 0000000000..22085d32f3 --- /dev/null +++ b/plugins/tracker-resources/src/components/issues/PriorityFilterMenuSection.svelte @@ -0,0 +1,63 @@ + + + +{#await getFilterElements(groups, selectedElements) then actions} + +{/await} diff --git a/plugins/tracker-resources/src/components/issues/StatusFilterMenuSection.svelte b/plugins/tracker-resources/src/components/issues/StatusFilterMenuSection.svelte index 3ea98d0fa5..7d34dafca8 100644 --- a/plugins/tracker-resources/src/components/issues/StatusFilterMenuSection.svelte +++ b/plugins/tracker-resources/src/components/issues/StatusFilterMenuSection.svelte @@ -24,8 +24,9 @@ export let selectedElements: any[] = [] export let statuses: Array> = [] export let groups: { [key: string]: number } - export let onUpdate: (result: { [p: string]: any }) => void - export let onBack: () => void + export let index: number = 0 + export let onUpdate: (result: { [p: string]: any }, filterIndex?: number) => void + export let onBack: (() => void) | undefined = undefined let backButtonTitle = '' @@ -41,13 +42,15 @@ selected: any[], backButtonTitle: string ) => { - const elements: FilterSectionElement[] = [ - { - icon: IconNavPrev, - title: backButtonTitle, - onSelect: onBack - } - ] + const elements: FilterSectionElement[] = onBack + ? [ + { + icon: IconNavPrev, + title: backButtonTitle, + onSelect: onBack + } + ] + : [] for (const [key, value] of Object.entries(groups)) { const status = defaultStatuses.find((x) => x._id === key) @@ -61,7 +64,7 @@ title: status.name, count: value, isSelected: selected.includes(key), - onSelect: () => onUpdate({ status: key }) + onSelect: () => onUpdate({ status: key }, index) }) } From 1205ec9d618bca45375ecadd96a2a2e7557b5258 Mon Sep 17 00:00:00 2001 From: Artyom Grigorovich Date: Wed, 11 May 2022 13:53:56 +0700 Subject: [PATCH 3/4] Add new filter summary features Signed-off-by: Artyom Grigorovich --- .../src/components/FilterSummary.svelte | 95 +++++++++++++++++-- .../components/FilterSummarySection.svelte | 15 ++- 2 files changed, 100 insertions(+), 10 deletions(-) diff --git a/plugins/tracker-resources/src/components/FilterSummary.svelte b/plugins/tracker-resources/src/components/FilterSummary.svelte index 92ee7ad69d..23a6c84742 100644 --- a/plugins/tracker-resources/src/components/FilterSummary.svelte +++ b/plugins/tracker-resources/src/components/FilterSummary.svelte @@ -13,26 +13,103 @@ // limitations under the License. -->
- {#each Object.entries(filters) as [key, value]} - onDeleteFilter(key)} /> + {#each filters as filter, filterIndex} + {@const [key, value] = Object.entries(filter.query)[0]} + onDeleteFilter(filterIndex)} + onChangeMode={() => onChangeMode(filterIndex)} + onEditFilter={(event) => handleEditFilterMenuOpened(event, key, filterIndex)} + /> {/each} -
-
+ {#if onAddFilter} +
+
+ {/if}
diff --git a/plugins/tracker-resources/src/components/FilterSummarySection.svelte b/plugins/tracker-resources/src/components/FilterSummarySection.svelte index 34d31194bd..088a5d3253 100644 --- a/plugins/tracker-resources/src/components/FilterSummarySection.svelte +++ b/plugins/tracker-resources/src/components/FilterSummarySection.svelte @@ -19,8 +19,11 @@ import tracker from '../plugin' export let type: string = '' + export let mode: '$in' | '$nin' = '$in' export let selectedFilters: any[] = [] export let onDelete: () => void + export let onChangeMode: () => void + export let onEditFilter: (event: MouseEvent) => void
@@ -30,7 +33,12 @@
@@ -38,6 +46,7 @@ shape={'rectangle'} label={tracker.string.FilterStatesCount} labelParams={{ value: selectedFilters.length }} + on:click={onEditFilter} />
@@ -49,6 +58,10 @@ .root { display: flex; align-items: center; + + &:not(:first-child) { + margin-left: 0.5rem; + } } .buttonWrapper { From a54e463f6404b53c18cde416237d6721a3cfa29c Mon Sep 17 00:00:00 2001 From: Artyom Grigorovich Date: Wed, 11 May 2022 13:54:14 +0700 Subject: [PATCH 4/4] Fix Issues component Signed-off-by: Artyom Grigorovich --- .../src/components/PrioritySelector.svelte | 10 +- .../src/components/issues/Issues.svelte | 118 ++++++++++++------ 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/plugins/tracker-resources/src/components/PrioritySelector.svelte b/plugins/tracker-resources/src/components/PrioritySelector.svelte index 01cd140ff0..24ab3ffea3 100644 --- a/plugins/tracker-resources/src/components/PrioritySelector.svelte +++ b/plugins/tracker-resources/src/components/PrioritySelector.svelte @@ -15,7 +15,7 @@