mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
[UBER-329] Remove "Project" filter from a single project view (#3345)
Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@icloud.com>
This commit is contained in:
parent
36b7014327
commit
34147e980f
@ -1467,7 +1467,8 @@ export function createModel (builder: Builder): void {
|
||||
showNested: false
|
||||
}
|
||||
],
|
||||
ignoreKeys: ['number', 'estimation', 'attachedTo']
|
||||
ignoreKeys: ['number', 'estimation', 'attachedTo'],
|
||||
getVisibleFilters: tracker.function.GetVisibleFilters
|
||||
})
|
||||
|
||||
builder.mixin(tracker.class.IssueTemplate, core.class.Class, view.mixin.ClassFilters, {
|
||||
|
@ -52,6 +52,7 @@ import {
|
||||
IgnoreActions,
|
||||
InlineAttributEditor,
|
||||
KeyBinding,
|
||||
KeyFilter,
|
||||
KeyFilterPreset,
|
||||
LinkPresenter,
|
||||
LinkProvider,
|
||||
@ -153,6 +154,7 @@ export class TClassFilters extends TClass implements ClassFilters {
|
||||
filters!: (string | KeyFilterPreset)[]
|
||||
ignoreKeys?: string[] | undefined
|
||||
strict?: boolean | undefined
|
||||
getVisibleFilters?: Resource<(filters: KeyFilter[], space?: Ref<Space>) => Promise<KeyFilter[]>>
|
||||
}
|
||||
|
||||
@Mixin(view.mixin.AttributeFilter, core.class.Class)
|
||||
|
@ -117,7 +117,8 @@ import {
|
||||
issueStatusSort,
|
||||
moveIssuesToAnotherMilestone,
|
||||
milestoneSort,
|
||||
subIssueQuery
|
||||
subIssueQuery,
|
||||
getVisibleFilters
|
||||
} from './utils'
|
||||
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
@ -497,7 +498,8 @@ export default async (): Promise<Resources> => ({
|
||||
SubIssueQuery: subIssueQuery,
|
||||
GetAllPriority: getAllPriority,
|
||||
GetAllComponents: getAllComponents,
|
||||
GetAllMilestones: getAllMilestones
|
||||
GetAllMilestones: getAllMilestones,
|
||||
GetVisibleFilters: getVisibleFilters
|
||||
},
|
||||
actionImpl: {
|
||||
Move: move,
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
import { Client, Doc, Ref } from '@hcengineering/core'
|
||||
import { Client, Doc, Ref, Space } from '@hcengineering/core'
|
||||
import type { Asset, IntlString, Metadata, Resource } from '@hcengineering/platform'
|
||||
import { mergeIds } from '@hcengineering/platform'
|
||||
import { IssueDraft } from '@hcengineering/tracker'
|
||||
@ -24,7 +24,8 @@ import {
|
||||
SortFunc,
|
||||
Viewlet,
|
||||
ViewletDescriptor,
|
||||
ViewQueryAction
|
||||
ViewQueryAction,
|
||||
KeyFilter
|
||||
} from '@hcengineering/view'
|
||||
import tracker, { trackerId } from '../../tracker/lib'
|
||||
|
||||
@ -392,7 +393,8 @@ export default mergeIds(trackerId, tracker, {
|
||||
SubIssueQuery: '' as ViewQueryAction,
|
||||
GetAllPriority: '' as GetAllValuesFunc,
|
||||
GetAllComponents: '' as GetAllValuesFunc,
|
||||
GetAllMilestones: '' as GetAllValuesFunc
|
||||
GetAllMilestones: '' as GetAllValuesFunc,
|
||||
GetVisibleFilters: '' as Resource<(filters: KeyFilter[], space?: Ref<Space>) => Promise<KeyFilter[]>>
|
||||
},
|
||||
aggregation: {
|
||||
CreateComponentAggregationManager: '' as CreateAggregationManagerFunc,
|
||||
|
@ -25,6 +25,7 @@ import core, {
|
||||
DocumentUpdate,
|
||||
Ref,
|
||||
SortingOrder,
|
||||
Space,
|
||||
Status,
|
||||
StatusCategory,
|
||||
StatusManager,
|
||||
@ -58,7 +59,7 @@ import {
|
||||
MILLISECONDS_IN_WEEK,
|
||||
PaletteColorIndexes
|
||||
} from '@hcengineering/ui'
|
||||
import { ViewletDescriptor } from '@hcengineering/view'
|
||||
import { KeyFilter, ViewletDescriptor } from '@hcengineering/view'
|
||||
import { CategoryQuery, groupBy, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
|
||||
import tracker from './plugin'
|
||||
import { defaultPriorities, defaultMilestoneStatuses } from './types'
|
||||
@ -654,3 +655,8 @@ export const IssuePriorityColor = {
|
||||
[IssuePriority.Medium]: PaletteColorIndexes.Ocean,
|
||||
[IssuePriority.Low]: PaletteColorIndexes.Cloud
|
||||
}
|
||||
|
||||
export async function getVisibleFilters (filters: KeyFilter[], space?: Ref<Space>): Promise<KeyFilter[]> {
|
||||
// Removes the "Project" filter if a specific space is provided
|
||||
return space === undefined ? filters : filters.filter((f) => f.key !== 'space')
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Label, Scroller, Submenu, closePopup, closeTooltip, resizeObserver, showPopup } from '@hcengineering/ui'
|
||||
import { ClassFilters, Filter, KeyFilter, KeyFilterPreset } from '@hcengineering/view'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { FilterQuery, buildFilterKey } from '../../filter'
|
||||
import view from '../../plugin'
|
||||
@ -101,12 +102,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getTypes (_class: Ref<Class<Doc>>, nestedFrom: KeyFilter | undefined): KeyFilter[] {
|
||||
async function getTypes (_class: Ref<Class<Doc>>, nestedFrom: KeyFilter | undefined): Promise<KeyFilter[]> {
|
||||
let res: KeyFilter[] = []
|
||||
if (nestedFrom !== undefined) {
|
||||
res = getNestedTypes(nestedFrom)
|
||||
res = await getNestedTypes(nestedFrom)
|
||||
} else {
|
||||
res = getOwnTypes(_class)
|
||||
res = await getOwnTypes(_class)
|
||||
}
|
||||
res.sort((a, b) => {
|
||||
if (a.group === b.group) return 0
|
||||
@ -119,20 +120,23 @@
|
||||
return res
|
||||
}
|
||||
|
||||
function getNestedTypes (type: KeyFilter): KeyFilter[] {
|
||||
async function getNestedTypes (type: KeyFilter): Promise<KeyFilter[]> {
|
||||
const targetClass = (hierarchy.getAttribute(type._class, type.key).type as RefTo<Doc>).to
|
||||
return getOwnTypes(targetClass)
|
||||
return await getOwnTypes(targetClass)
|
||||
}
|
||||
|
||||
function getOwnTypes (_class: Ref<Class<Doc>>): KeyFilter[] {
|
||||
async function getOwnTypes (_class: Ref<Class<Doc>>): Promise<KeyFilter[]> {
|
||||
const mixin = hierarchy.classHierarchyMixin(_class, view.mixin.ClassFilters)
|
||||
if (mixin === undefined) return []
|
||||
_class = hierarchy.getBaseClass(_class)
|
||||
const result = getFilters(_class, mixin)
|
||||
const getVisibleFilters = mixin.getVisibleFilters
|
||||
? await getResource(mixin.getVisibleFilters)
|
||||
: async (filters: KeyFilter[]) => filters
|
||||
|
||||
if (mixin.strict) {
|
||||
// Attributes not specified in "mixing.filters" are ignored
|
||||
return result
|
||||
// Attributes not specified in "mixin.filters" are ignored in "strict" mode
|
||||
return await getVisibleFilters(result, space)
|
||||
}
|
||||
|
||||
const allAttributes = hierarchy.getAllAttributes(_class)
|
||||
@ -166,7 +170,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
return await getVisibleFilters(result, space)
|
||||
}
|
||||
|
||||
const actionElements: HTMLButtonElement[] = []
|
||||
@ -260,8 +264,6 @@
|
||||
|
||||
const elements: HTMLElement[] = []
|
||||
|
||||
$: types = getTypes(_class, nestedFrom)
|
||||
|
||||
function nextDiffCat (types: KeyFilter[], i: number): boolean {
|
||||
if (types[i + 1] === undefined) return false
|
||||
return types[i].group !== types[i + 1].group
|
||||
@ -289,45 +291,47 @@
|
||||
</button>
|
||||
<div class="divider" />
|
||||
{/if}
|
||||
{#each types as type, i}
|
||||
{#if filter === undefined && hasNested(type)}
|
||||
<Submenu
|
||||
bind:element={elements[i]}
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={() => {
|
||||
elements[i]?.focus()
|
||||
}}
|
||||
label={type.label}
|
||||
props={{
|
||||
_class,
|
||||
space,
|
||||
index,
|
||||
target,
|
||||
onChange,
|
||||
nestedFrom: type
|
||||
}}
|
||||
options={{ component: view.component.FilterTypePopup }}
|
||||
withHover
|
||||
/>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
class="menu-item"
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={(event) => {
|
||||
event.currentTarget.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
click(type)
|
||||
}}
|
||||
>
|
||||
<div class="overflow-label pr-1"><Label label={type.label} /></div>
|
||||
</button>
|
||||
{/if}
|
||||
{#if nextDiffCat(types, i)}
|
||||
<div class="menu-separator" />
|
||||
{/if}
|
||||
{/each}
|
||||
{#await getTypes(_class, nestedFrom) then types}
|
||||
{#each types as type, i}
|
||||
{#if filter === undefined && hasNested(type)}
|
||||
<Submenu
|
||||
bind:element={elements[i]}
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={() => {
|
||||
elements[i]?.focus()
|
||||
}}
|
||||
label={type.label}
|
||||
props={{
|
||||
_class,
|
||||
space,
|
||||
index,
|
||||
target,
|
||||
onChange,
|
||||
nestedFrom: type
|
||||
}}
|
||||
options={{ component: view.component.FilterTypePopup }}
|
||||
withHover
|
||||
/>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
class="menu-item"
|
||||
on:keydown={(event) => keyDown(event, i)}
|
||||
on:mouseover={(event) => {
|
||||
event.currentTarget.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
click(type)
|
||||
}}
|
||||
>
|
||||
<div class="overflow-label pr-1"><Label label={type.label} /></div>
|
||||
</button>
|
||||
{/if}
|
||||
{#if nextDiffCat(types, i)}
|
||||
<div class="menu-separator" />
|
||||
{/if}
|
||||
{/each}
|
||||
{/await}
|
||||
</Scroller>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -128,6 +128,8 @@ export interface ClassFilters extends Class<Doc> {
|
||||
|
||||
// Ignore attributes not specified in the "filters" array
|
||||
strict?: boolean
|
||||
// Allows to filter out the provided keys, leaving only the necessary ones
|
||||
getVisibleFilters?: Resource<(filters: KeyFilter[], space?: Ref<Space>) => Promise<KeyFilter[]>>
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user