Skip to content

Commit

Permalink
Tracker: Issue filters - additional features (#1708)
Browse files Browse the repository at this point in the history
Signed-off-by: Artyom Grigorovich <grigorovichartyom@gmail.com>
  • Loading branch information
agrigorovich-xored authored May 11, 2022
1 parent d7df2ff commit 1c98ca3
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 80 deletions.
17 changes: 10 additions & 7 deletions plugins/tracker-resources/src/components/FilterMenuSection.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = []
Expand All @@ -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
}
Expand All @@ -46,7 +46,8 @@
if (event.key === 'ArrowLeft') {
dispatch('close')
onBack()
onBack?.()
}
}
Expand Down Expand Up @@ -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]
}
}}
>
<div class="buttonContent">
{#if i !== 0}
{#if i !== 0 || (i === 0 && !onBack)}
<div class="flex check pointer-events-none">
<CheckBox checked={selectedElementsMap[i]} primary />
</div>
{/if}
{#if action.icon}
<div class="icon" class:ml-3={i > 0}><Icon icon={action.icon} size={'small'} /></div>
<div class="icon" class:ml-3={i > 0 || (i === 0 && !onBack)}>
<Icon icon={action.icon} size={'small'} />
</div>
{/if}
{#if action.title}
<div class="ml-3 pr-1">{action.title}</div>
Expand Down
95 changes: 86 additions & 9 deletions plugins/tracker-resources/src/components/FilterSummary.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,103 @@
// limitations under the License.
-->
<script lang="ts">
import { Button, IconAdd } from '@anticrm/ui'
import { Button, eventToHTMLElement, IconAdd, showPopup } from '@anticrm/ui'
import FilterSummarySection from './FilterSummarySection.svelte'
import StatusFilterMenuSection from './issues/StatusFilterMenuSection.svelte'
import PriorityFilterMenuSection from './issues/PriorityFilterMenuSection.svelte'
import { defaultPriorities, getGroupedIssues, IssueFilter } from '../utils'
import { WithLookup } from '@anticrm/core'
import { Issue, IssueStatus } from '@anticrm/tracker'
export let filters: IssueFilter[] = []
export let issues: Issue[] = []
export let defaultStatuses: Array<WithLookup<IssueStatus>> = []
export let onUpdateFilter: (result: { [p: string]: any }, filterIndex: number) => void
export let onAddFilter: ((event: MouseEvent) => void) | undefined = undefined
export let onDeleteFilter: (filterIndex?: number) => void
export let onChangeMode: (index: number) => void
$: defaultStatusIds = defaultStatuses.map((x) => x._id)
$: groupedByStatus = getGroupedIssues('status', issues, defaultStatusIds)
$: groupedByPriority = getGroupedIssues('priority', issues, defaultPriorities)
const handleEditFilterMenuOpened = (event: MouseEvent, type: string, index: number) => {
switch (type) {
case 'status': {
const statusGroups: { [key: string]: number } = {}
for (const status of defaultStatuses) {
statusGroups[status._id] = groupedByStatus[status._id]?.length ?? 0
}
const { mode, query } = filters[index]
const currentFilterQuery = query as { [p: string]: { $in?: any[]; $nin?: any[] } } | undefined
export let filters: { [p: string]: any[] } = {}
export let onDeleteFilter: (filterKey?: string) => void
showPopup(
StatusFilterMenuSection,
{
groups: statusGroups,
statuses: defaultStatuses,
selectedElements: currentFilterQuery?.status?.[mode] ?? [],
index,
onUpdate: onUpdateFilter
},
eventToHTMLElement(event)
)
break
}
case 'priority': {
const priorityGroups: { [key: string]: number } = {}
for (const priority of defaultPriorities) {
priorityGroups[priority] = groupedByPriority[priority]?.length ?? 0
}
const { mode, query } = filters[index]
const currentFilterQuery = query as { [p: string]: { $in?: any[]; $nin?: any[] } } | undefined
showPopup(
PriorityFilterMenuSection,
{
groups: priorityGroups,
selectedElements: currentFilterQuery?.priority?.[mode] ?? [],
index,
onUpdate: onUpdateFilter
},
eventToHTMLElement(event)
)
break
}
}
}
</script>

<div class="root">
{#each Object.entries(filters) as [key, value]}
<FilterSummarySection type={key} selectedFilters={value} onDelete={() => onDeleteFilter(key)} />
{#each filters as filter, filterIndex}
{@const [key, value] = Object.entries(filter.query)[0]}
<FilterSummarySection
type={key}
mode={filter.mode}
selectedFilters={value?.[filter.mode]}
onDelete={() => onDeleteFilter(filterIndex)}
onChangeMode={() => onChangeMode(filterIndex)}
onEditFilter={(event) => handleEditFilterMenuOpened(event, key, filterIndex)}
/>
{/each}
<div class="ml-2">
<Button kind={'link'} icon={IconAdd} />
</div>
{#if onAddFilter}
<div class="ml-2">
<Button kind={'link'} icon={IconAdd} on:click={onAddFilter} />
</div>
{/if}
</div>

<style lang="scss">
.root {
display: flex;
flex: 1 1 auto;
flex-flow: row wrap;
align-items: center;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -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
</script>

<div class="root">
Expand All @@ -30,14 +33,20 @@
<div class="buttonWrapper">
<Button
shape="rectangle"
label={selectedFilters.length < 2 ? tracker.string.FilterIs : tracker.string.FilterIsEither}
label={mode === '$nin'
? tracker.string.FilterIsNot
: selectedFilters.length < 2
? tracker.string.FilterIs
: tracker.string.FilterIsEither}
on:click={onChangeMode}
/>
</div>
<div class="buttonWrapper">
<Button
shape={'rectangle'}
label={tracker.string.FilterStatesCount}
labelParams={{ value: selectedFilters.length }}
on:click={onEditFilter}
/>
</div>
<div class="buttonWrapper">
Expand All @@ -49,6 +58,10 @@
.root {
display: flex;
align-items: center;
&:not(:first-child) {
margin-left: 0.5rem;
}
}
.buttonWrapper {
Expand Down
10 changes: 2 additions & 8 deletions plugins/tracker-resources/src/components/PrioritySelector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { IssuePriority } from '@anticrm/tracker'
import { Button, showPopup, SelectPopup, eventToHTMLElement } from '@anticrm/ui'
import type { ButtonKind, ButtonSize } from '@anticrm/ui'
import { issuePriorities } from '../utils'
import { defaultPriorities, issuePriorities } from '../utils'
import tracker from '../plugin'
export let priority: IssuePriority
Expand All @@ -29,13 +29,7 @@
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = 'min-content'
const prioritiesInfo = [
IssuePriority.NoPriority,
IssuePriority.Urgent,
IssuePriority.High,
IssuePriority.Medium,
IssuePriority.Low
].map((p) => ({ id: p, ...issuePriorities[p] }))
const prioritiesInfo = defaultPriorities.map((p) => ({ id: p, ...issuePriorities[p] }))
const handlePriorityEditorOpened = (event: MouseEvent) => {
if (!isEditable) {
Expand Down
Loading

0 comments on commit 1c98ca3

Please sign in to comment.