Subissues filter (#2653)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-02-17 15:25:40 +06:00 committed by GitHub
parent 056b3ee9a8
commit 8cc64cf8a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 38 deletions

View File

@ -15,10 +15,21 @@
<script lang="ts">
import { Ref, SortingOrder, toIdMap, WithLookup } from '@hcengineering/core'
import { createQuery } from '@hcengineering/presentation'
import { Issue, IssueStatus, Team } from '@hcengineering/tracker'
import { Button, Chevron, closeTooltip, ExpandCollapse, IconAdd, IconArrowRight, Label } from '@hcengineering/ui'
import { Issue, IssueStatus, Team, trackerId } from '@hcengineering/tracker'
import {
Button,
Chevron,
closeTooltip,
ExpandCollapse,
getCurrentLocation,
IconScaleFull,
IconAdd,
IconArrowRight,
Label,
navigate
} from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { getViewOptions, ViewletSettingButton } from '@hcengineering/view-resources'
import { createFilter, filterStore, getViewOptions, ViewletSettingButton } from '@hcengineering/view-resources'
import tracker from '../../../plugin'
import CreateSubIssue from './CreateSubIssue.svelte'
import SubIssueList from './SubIssueList.svelte'
@ -99,6 +110,27 @@
{#if viewlet && hasSubIssues && viewOptions}
<ViewletSettingButton bind:viewOptions {viewlet} kind={'transparent'} />
{/if}
<Button
width="min-content"
icon={IconScaleFull}
kind={'transparent'}
size={'small'}
showTooltip={{ label: tracker.string.OpenSubIssues, direction: 'bottom' }}
on:click={() => {
const filter = createFilter(tracker.class.Issue, 'attachedTo', [issue._id])
if (filter !== undefined) {
closeTooltip()
const loc = getCurrentLocation()
loc.fragment = undefined
loc.query = undefined
loc.path[2] = trackerId
loc.path[3] = issue.space
loc.path[4] = 'issues'
navigate(loc)
$filterStore = [filter]
}
}}
/>
<Button
id="add-sub-issue"
width="min-content"

View File

@ -13,18 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import core, {
AnyAttribute,
ArrOf,
AttachedDoc,
Class,
Collection,
Doc,
Ref,
RefTo,
Space,
Type
} from '@hcengineering/core'
import core, { AnyAttribute, ArrOf, Class, Doc, Ref, RefTo, Space, Type } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import {
closePopup,
@ -38,7 +27,7 @@
} from '@hcengineering/ui'
import { Filter, KeyFilter } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import { FilterQuery } from '../../filter'
import { buildFilterKey, FilterQuery } from '../../filter'
import view from '../../plugin'
export let _class: Ref<Class<Doc>>
@ -67,25 +56,7 @@
function buildFilterFromKey (_class: Ref<Class<Doc>>, key: string): KeyFilter | undefined {
const attribute = hierarchy.getAttribute(_class, key)
return buildFilter(_class, key, attribute)
}
function buildFilter (_class: Ref<Class<Doc>>, key: string, attribute: AnyAttribute): KeyFilter | undefined {
const isCollection = hierarchy.isDerived(attribute.type._class, core.class.Collection)
const targetClass = isCollection ? (attribute.type as Collection<AttachedDoc>).of : attribute.type._class
const clazz = hierarchy.getClass(targetClass)
const filter = hierarchy.as(clazz, view.mixin.AttributeFilter)
const attrOf = hierarchy.getClass(attribute.attributeOf)
if (filter.component === undefined) return undefined
return {
_class,
key: isCollection ? '_id' : key,
attribute,
label: attribute.label,
icon: attribute.icon ?? clazz.icon ?? attrOf.icon ?? view.icon.Setting,
component: filter.component
}
return buildFilterKey(hierarchy, _class, key, attribute)
}
function getValue (name: string, type: Type<any>): string {
@ -103,7 +74,7 @@
if (result.findIndex((p) => p.key === value) !== -1) {
return
}
const filter = buildFilter(_class, value, attribute)
const filter = buildFilterKey(hierarchy, _class, value, attribute)
if (filter !== undefined) {
result.push(filter)
}

View File

@ -1,7 +1,18 @@
import { Doc, FindResult, ObjQueryType, Ref } from '@hcengineering/core'
import core, {
AnyAttribute,
AttachedDoc,
Class,
Collection,
Doc,
FindResult,
Hierarchy,
ObjQueryType,
Ref
} from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { createQuery, getClient, LiveQuery } from '@hcengineering/presentation'
import { Filter } from '@hcengineering/view'
import { AnyComponent } from '@hcengineering/ui'
import { Filter, FilterMode, KeyFilter } from '@hcengineering/view'
import { writable } from 'svelte/store'
import view from './plugin'
@ -94,3 +105,70 @@ export async function getRefs (filter: Filter, onUpdate: () => void): Promise<Ar
})
return await promise
}
export function buildFilterKey (
hierarchy: Hierarchy,
_class: Ref<Class<Doc>>,
key: string,
attribute: AnyAttribute
): KeyFilter | undefined {
const isCollection = hierarchy.isDerived(attribute.type._class, core.class.Collection)
const targetClass = isCollection ? (attribute.type as Collection<AttachedDoc>).of : attribute.type._class
const clazz = hierarchy.getClass(targetClass)
const filter = hierarchy.as(clazz, view.mixin.AttributeFilter)
const attrOf = hierarchy.getClass(attribute.attributeOf)
if (filter.component === undefined) return undefined
return {
_class,
key: isCollection ? '_id' : key,
attribute,
label: attribute.label,
icon: attribute.icon ?? clazz.icon ?? attrOf.icon ?? view.icon.Setting,
component: filter.component
}
}
interface FilterModes {
modes: Array<Ref<FilterMode>>
mode: Ref<FilterMode>
}
function getFilterModes (component: AnyComponent): FilterModes | undefined {
if (component === view.component.ObjectFilter) {
return {
modes: [view.filter.FilterObjectIn, view.filter.FilterObjectNin],
mode: view.filter.FilterObjectIn
}
}
if (component === view.component.ValueFilter) {
return {
modes: [view.filter.FilterValueIn, view.filter.FilterValueNin],
mode: view.filter.FilterValueIn
}
}
if (component === view.component.TimestampFilter) {
return {
modes: [view.filter.FilterBefore, view.filter.FilterAfter],
mode: view.filter.FilterBefore
}
}
}
export function createFilter (_class: Ref<Class<Doc>>, key: string, value: any[]): Filter | undefined {
const client = getClient()
const hierarchy = client.getHierarchy()
const attribute = hierarchy.getAttribute(_class, key)
const filterKey = buildFilterKey(hierarchy, _class, key, attribute)
if (filterKey === undefined) return
const modes = getFilterModes(filterKey.component)
if (modes === undefined) return
return {
key: filterKey,
value,
index: 1,
modes: modes.modes,
mode: modes.mode
}
}