TSK-806 Пропадают сохраненные View (#2738)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-03-15 21:26:33 +06:00 committed by GitHub
parent ae86bfdacd
commit fff4debc49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 412 additions and 253 deletions

View File

@ -192,17 +192,27 @@ export function createModel (builder: Builder): void {
// ]
// })
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: board.class.Card,
descriptor: board.viewlet.Kanban,
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: board.class.Card,
descriptor: board.viewlet.Kanban,
config: []
},
board.viewlet.KanbanCard
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: board.class.Card,
descriptor: board.viewlet.Table,
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: board.class.Card,
descriptor: board.viewlet.Table,
config: []
},
board.viewlet.TableCard
)
builder.mixin(board.class.Card, core.class.Class, task.mixin.KanbanCard, {
card: board.component.KanbanCard

View File

@ -20,7 +20,7 @@ import type { Ref, Space } from '@hcengineering/core'
import { IntlString, mergeIds } from '@hcengineering/platform'
import { KanbanTemplate, Sequence } from '@hcengineering/task'
import type { AnyComponent } from '@hcengineering/ui'
import { Action, ViewAction, ViewletDescriptor } from '@hcengineering/view'
import { Action, ViewAction, Viewlet, ViewletDescriptor } from '@hcengineering/view'
export default mergeIds(boardId, board, {
component: {
@ -51,6 +51,8 @@ export default mergeIds(boardId, board, {
Sequence: '' as Ref<Sequence>
},
viewlet: {
KanbanCard: '' as Ref<Viewlet>,
TableCard: '' as Ref<Viewlet>,
Kanban: '' as Ref<ViewletDescriptor>,
Table: '' as Ref<ViewletDescriptor>
},

View File

@ -257,24 +257,34 @@ export function createModel (builder: Builder): void {
lead.viewlet.ListLead
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: lead.class.Lead,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: {
attachedTo: lead.mixin.Customer
}
} as FindOptions<Doc>, // TODO: fix
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: lead.class.Lead,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: {
attachedTo: lead.mixin.Customer
}
} as FindOptions<Doc>, // TODO: fix
config: []
},
lead.viewlet.KanbanLead
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: lead.class.Lead,
descriptor: task.viewlet.Dashboard,
options: {},
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: lead.class.Lead,
descriptor: task.viewlet.Dashboard,
options: {},
config: []
},
lead.viewlet.DashboardLead
)
builder.mixin(lead.class.Lead, core.class.Class, task.mixin.KanbanCard, {
card: lead.component.KanbanCard

View File

@ -52,7 +52,9 @@ export default mergeIds(leadId, lead, {
viewlet: {
TableCustomer: '' as Ref<Viewlet>,
TableLead: '' as Ref<Viewlet>,
ListLead: '' as Ref<Viewlet>
ListLead: '' as Ref<Viewlet>,
DashboardLead: '' as Ref<Viewlet>,
KanbanLead: '' as Ref<Viewlet>
},
category: {
Lead: '' as Ref<ActionCategory>

View File

@ -565,22 +565,32 @@ export function createModel (builder: Builder): void {
}
}
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: applicantKanbanLookup
} as FindOptions<Doc>, // TODO: fix
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: applicantKanbanLookup
} as FindOptions<Doc>, // TODO: fix
config: []
},
recruit.viewlet.ApplicantKanban
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.Dashboard,
options: {},
config: []
})
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.Dashboard,
options: {},
config: []
},
recruit.viewlet.ApplicantDashboard
)
builder.mixin(recruit.class.Applicant, core.class.Class, task.mixin.KanbanCard, {
card: recruit.component.KanbanCard

View File

@ -100,10 +100,12 @@ export default mergeIds(recruitId, recruit, {
TableCandidate: '' as Ref<Viewlet>,
TableVacancy: '' as Ref<Viewlet>,
ApplicantTable: '' as Ref<Viewlet>,
ApplicantKanban: '' as Ref<Viewlet>,
TableApplicant: '' as Ref<Viewlet>,
TableApplicantMatch: '' as Ref<Viewlet>,
CalendarReview: '' as Ref<Viewlet>,
TableReview: '' as Ref<Viewlet>,
TableVacancyList: '' as Ref<Viewlet>
TableVacancyList: '' as Ref<Viewlet>,
ApplicantDashboard: '' as Ref<Viewlet>
}
})

View File

@ -387,20 +387,25 @@ export function createModel (builder: Builder): void {
fields: ['assignee']
})
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: task.class.Issue,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: {
assignee: contact.class.Employee,
_id: {
todoItems: task.class.TodoItem
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: task.class.Issue,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: {
assignee: contact.class.Employee,
_id: {
todoItems: task.class.TodoItem
}
}
}
} as FindOptions<Doc>,
config: []
})
} as FindOptions<Doc>,
config: []
},
task.viewlet.KanbanIssue
)
builder.mixin(task.class.Issue, core.class.Class, task.mixin.KanbanCard, {
card: task.component.KanbanCard

View File

@ -69,6 +69,7 @@ export default mergeIds(taskId, task, {
DefaultProject: '' as Ref<KanbanTemplate>
},
viewlet: {
TableIssue: '' as Ref<Viewlet>
TableIssue: '' as Ref<Viewlet>,
KanbanIssue: '' as Ref<Viewlet>
}
})

View File

@ -540,71 +540,80 @@ export function createModel (builder: Builder): void {
]
}
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: tracker.class.Issue,
descriptor: view.viewlet.List,
viewOptions: issuesOptions,
config: [
{
key: '',
presenter: tracker.component.PriorityEditor,
props: { type: 'priority', kind: 'list', size: 'small' }
},
{ key: '', presenter: tracker.component.IssuePresenter, props: { type: 'issue', listProps: { fixed: 'left' } } },
{
key: '',
presenter: tracker.component.StatusEditor,
props: { kind: 'list', size: 'small', justify: 'center' }
},
{ key: '', presenter: tracker.component.TitlePresenter, props: { shouldUseMargin: true } },
{ key: '', presenter: tracker.component.SubIssuesSelector, props: {} },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
{ key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
{
key: '',
presenter: tracker.component.ProjectEditor,
props: {
kind: 'list',
size: 'small',
shape: 'round',
shouldShowPlaceholder: false,
listProps: {
excludeByKey: 'project',
optional: true
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: tracker.class.Issue,
descriptor: view.viewlet.List,
viewOptions: issuesOptions,
config: [
{
key: '',
presenter: tracker.component.PriorityEditor,
props: { type: 'priority', kind: 'list', size: 'small' }
},
{
key: '',
presenter: tracker.component.IssuePresenter,
props: { type: 'issue', listProps: { fixed: 'left' } }
},
{
key: '',
presenter: tracker.component.StatusEditor,
props: { kind: 'list', size: 'small', justify: 'center' }
},
{ key: '', presenter: tracker.component.TitlePresenter, props: { shouldUseMargin: true } },
{ key: '', presenter: tracker.component.SubIssuesSelector, props: {} },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
{ key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
{
key: '',
presenter: tracker.component.ProjectEditor,
props: {
kind: 'list',
size: 'small',
shape: 'round',
shouldShowPlaceholder: false,
listProps: {
excludeByKey: 'project',
optional: true
}
}
}
},
{
key: '',
presenter: tracker.component.SprintEditor,
props: {
kind: 'list',
size: 'small',
shape: 'round',
shouldShowPlaceholder: false,
listProps: {
excludeByKey: 'sprint',
optional: true
},
{
key: '',
presenter: tracker.component.SprintEditor,
props: {
kind: 'list',
size: 'small',
shape: 'round',
shouldShowPlaceholder: false,
listProps: {
excludeByKey: 'sprint',
optional: true
}
}
},
{
key: '',
presenter: tracker.component.EstimationEditor,
props: { kind: 'list', size: 'small', listProps: { optional: true } }
},
{
key: 'modifiedOn',
presenter: tracker.component.ModificationDatePresenter,
props: { listProps: { fixed: 'right', optional: true } }
},
{
key: '$lookup.assignee',
presenter: tracker.component.AssigneePresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
}
},
{
key: '',
presenter: tracker.component.EstimationEditor,
props: { kind: 'list', size: 'small', listProps: { optional: true } }
},
{
key: 'modifiedOn',
presenter: tracker.component.ModificationDatePresenter,
props: { listProps: { fixed: 'right', optional: true } }
},
{
key: '$lookup.assignee',
presenter: tracker.component.AssigneePresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
}
]
})
]
},
tracker.viewlet.IssueList
)
const subIssuesOptions: ViewOptionsModel = {
groupBy: ['status', 'assignee', 'priority', 'sprint'],
@ -681,57 +690,71 @@ export function createModel (builder: Builder): void {
tracker.viewlet.SubIssues
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: tracker.class.IssueTemplate,
descriptor: view.viewlet.List,
viewOptions: {
groupBy: ['assignee', 'priority', 'project', 'sprint'],
orderBy: [
['priority', SortingOrder.Ascending],
['modifiedOn', SortingOrder.Descending],
['dueDate', SortingOrder.Descending],
['rank', SortingOrder.Ascending]
],
other: []
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: tracker.class.IssueTemplate,
descriptor: view.viewlet.List,
viewOptions: {
groupBy: ['assignee', 'priority', 'project', 'sprint'],
orderBy: [
['priority', SortingOrder.Ascending],
['modifiedOn', SortingOrder.Descending],
['dueDate', SortingOrder.Descending],
['rank', SortingOrder.Ascending]
],
other: []
},
config: [
// { key: '', presenter: tracker.component.PriorityEditor, props: { kind: 'list', size: 'small' } },
{
key: '',
presenter: tracker.component.IssueTemplatePresenter,
props: { type: 'issue', shouldUseMargin: true }
},
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
// { key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
{
key: '',
presenter: tracker.component.ProjectEditor,
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
},
{
key: '',
presenter: tracker.component.SprintEditor,
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
},
{ key: '', presenter: tracker.component.TemplateEstimationEditor, props: { kind: 'list', size: 'small' } },
{
key: 'modifiedOn',
presenter: tracker.component.ModificationDatePresenter,
props: { listProps: { fixed: 'right' } }
},
{
key: '$lookup.assignee',
presenter: tracker.component.AssigneePresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
}
]
},
config: [
// { key: '', presenter: tracker.component.PriorityEditor, props: { kind: 'list', size: 'small' } },
{ key: '', presenter: tracker.component.IssueTemplatePresenter, props: { type: 'issue', shouldUseMargin: true } },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
// { key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
{
key: '',
presenter: tracker.component.ProjectEditor,
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
},
{
key: '',
presenter: tracker.component.SprintEditor,
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
},
{ key: '', presenter: tracker.component.TemplateEstimationEditor, props: { kind: 'list', size: 'small' } },
{
key: 'modifiedOn',
presenter: tracker.component.ModificationDatePresenter,
props: { listProps: { fixed: 'right' } }
},
{
key: '$lookup.assignee',
presenter: tracker.component.AssigneePresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
}
]
})
tracker.viewlet.IssueTemplateList
)
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: tracker.class.Issue,
descriptor: tracker.viewlet.Kanban,
viewOptions: {
...issuesOptions,
groupDepth: 1
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: tracker.class.Issue,
descriptor: tracker.viewlet.Kanban,
viewOptions: {
...issuesOptions,
groupDepth: 1
},
config: []
},
config: []
})
tracker.viewlet.IssueKanban
)
builder.createDoc(
view.class.ViewletDescriptor,
@ -1669,42 +1692,47 @@ export function createModel (builder: Builder): void {
other: []
}
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: tracker.class.Sprint,
descriptor: view.viewlet.List,
viewOptions: sprintOptions,
config: [
{
key: '',
presenter: tracker.component.SprintStatusPresenter,
props: { width: '1rem', kind: 'list', size: 'small', justify: 'center' }
},
{ key: '', presenter: tracker.component.SprintPresenter, props: { shouldUseMargin: true } },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
{ key: '', presenter: tracker.component.SprintProjectEditor, props: { kind: 'list' } },
{
key: '',
presenter: contact.component.MembersPresenter,
props: {
kind: 'link',
intlTitle: tracker.string.SprintMembersTitle,
intlSearchPh: tracker.string.SprintMembersSearchPlaceholder
builder.createDoc(
view.class.Viewlet,
core.space.Model,
{
attachTo: tracker.class.Sprint,
descriptor: view.viewlet.List,
viewOptions: sprintOptions,
config: [
{
key: '',
presenter: tracker.component.SprintStatusPresenter,
props: { width: '1rem', kind: 'list', size: 'small', justify: 'center' }
},
{ key: '', presenter: tracker.component.SprintPresenter, props: { shouldUseMargin: true } },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
{ key: '', presenter: tracker.component.SprintProjectEditor, props: { kind: 'list' } },
{
key: '',
presenter: contact.component.MembersPresenter,
props: {
kind: 'link',
intlTitle: tracker.string.SprintMembersTitle,
intlSearchPh: tracker.string.SprintMembersSearchPlaceholder
}
},
{ key: '', presenter: tracker.component.SprintDatePresenter, props: { field: 'startDate' } },
{ key: '', presenter: tracker.component.SprintDatePresenter, props: { field: 'targetDate' } },
{
key: '$lookup.lead',
presenter: tracker.component.SprintLeadPresenter,
props: {
_class: tracker.class.Sprint,
defaultClass: contact.class.Employee,
shouldShowLabel: false,
size: 'x-small'
}
}
},
{ key: '', presenter: tracker.component.SprintDatePresenter, props: { field: 'startDate' } },
{ key: '', presenter: tracker.component.SprintDatePresenter, props: { field: 'targetDate' } },
{
key: '$lookup.lead',
presenter: tracker.component.SprintLeadPresenter,
props: {
_class: tracker.class.Sprint,
defaultClass: contact.class.Employee,
shouldShowLabel: false,
size: 'x-small'
}
}
]
})
]
},
tracker.viewlet.SprintList
)
createAction(
builder,

View File

@ -20,7 +20,7 @@ import { IntlString, mergeIds, Resource } from '@hcengineering/platform'
import { trackerId } from '@hcengineering/tracker'
import tracker from '@hcengineering/tracker-resources/src/plugin'
import type { AnyComponent } from '@hcengineering/ui/src/types'
import { Action, ViewAction, ViewletDescriptor } from '@hcengineering/view'
import { Action, ViewAction, Viewlet, ViewletDescriptor } from '@hcengineering/view'
import { Application } from '@hcengineering/workbench'
export default mergeIds(trackerId, tracker, {
@ -47,6 +47,10 @@ export default mergeIds(trackerId, tracker, {
Tracker: '' as Ref<Application>
},
viewlet: {
IssueList: '' as Ref<Viewlet>,
IssueTemplateList: '' as Ref<Viewlet>,
IssueKanban: '' as Ref<Viewlet>,
SprintList: '' as Ref<Viewlet>,
List: '' as Ref<ViewletDescriptor>,
Kanban: '' as Ref<ViewletDescriptor>
},

View File

@ -105,6 +105,7 @@ export class TFilteredView extends TPreference implements FilteredView {
location!: Location
filters!: string
viewOptions?: ViewOptions
filterClass?: Ref<Class<Doc>>
viewletId?: Ref<Viewlet> | null
}

View File

@ -30,7 +30,13 @@
TabList
} from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import { FilterButton, getViewOptions, setActiveViewletId, ViewletSettingButton } from '@hcengineering/view-resources'
import {
FilterButton,
getViewOptions,
setActiveViewletId,
ViewletSettingButton,
viewOptionStore
} from '@hcengineering/view-resources'
import calendar from '../plugin'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
@ -103,7 +109,7 @@
$: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(selectedViewlet)
$: viewOptions = getViewOptions(selectedViewlet, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>

View File

@ -25,7 +25,8 @@
getViewOptions,
setActiveViewletId,
TableBrowser,
ViewletSettingButton
ViewletSettingButton,
viewOptionStore
} from '@hcengineering/view-resources'
import contact from '../plugin'
import CreateContact from './CreateContact.svelte'
@ -75,7 +76,7 @@
$: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
<ActionContext

View File

@ -18,7 +18,13 @@
import { createQuery, getClient, UsersPopup, IconMembersOutline } from '@hcengineering/presentation'
import { Button, IconAdd, Label, showPopup, Icon } from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import { getViewOptions, setActiveViewletId, Table, ViewletSettingButton } from '@hcengineering/view-resources'
import {
getViewOptions,
setActiveViewletId,
Table,
ViewletSettingButton,
viewOptionStore
} from '@hcengineering/view-resources'
import contact from '../plugin'
export let objectId: Ref<Doc>
@ -91,7 +97,7 @@
}
})
}
$: viewOptions = getViewOptions(descr)
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="antiSection">

View File

@ -25,6 +25,7 @@
FilterButton,
getViewOptions,
setActiveViewletId,
viewOptionStore,
TableBrowser,
ViewletSettingButton
} from '@hcengineering/view-resources'
@ -72,7 +73,7 @@
let twoRows: boolean
$: twoRows = $deviceInfo.docWidth <= 680
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
<ActionContext

View File

@ -19,7 +19,13 @@
import { createQuery, getClient, UsersPopup } from '@hcengineering/presentation'
import { Button, eventToHTMLElement, IconAdd, Label, Scroller, showPopup } from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import { getViewOptions, setActiveViewletId, Table, ViewletSettingButton } from '@hcengineering/view-resources'
import {
getViewOptions,
setActiveViewletId,
viewOptionStore,
Table,
ViewletSettingButton
} from '@hcengineering/view-resources'
import hr from '../plugin'
import { addMember } from '../utils'
@ -93,7 +99,7 @@
})
}
$: viewOptions = getViewOptions(descr)
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="antiSection">

View File

@ -20,7 +20,13 @@
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, Label, Loading, Scroller, tableSP } from '@hcengineering/ui'
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
import { getViewOptions, setActiveViewletId, Table, ViewletSettingButton } from '@hcengineering/view-resources'
import {
getViewOptions,
setActiveViewletId,
Table,
viewOptionStore,
ViewletSettingButton
} from '@hcengineering/view-resources'
import hr from '../../plugin'
import {
EmployeeReports,
@ -258,7 +264,7 @@
return result
}
$: viewOptions = getViewOptions(descr)
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
{#if departmentStaff.length}

View File

@ -32,6 +32,7 @@
FilterBar,
FilterButton,
getViewOptions,
viewOptionStore,
setActiveViewletId,
TableBrowser,
ViewletSettingButton
@ -231,7 +232,7 @@
$: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(descr)
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>

View File

@ -24,6 +24,7 @@
getViewOptions,
setActiveViewletId,
TableBrowser,
viewOptionStore,
ViewletSettingButton
} from '@hcengineering/view-resources'
import recruit from '../plugin'
@ -142,7 +143,7 @@
$: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(descr)
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>

View File

@ -85,6 +85,7 @@ export interface CandidateDraft extends Doc {
* @public
*/
export interface Applicant extends Task {
space: Ref<Vacancy>
attachedTo: Ref<Candidate>
attachments?: number
comments?: number

View File

@ -5,7 +5,13 @@
import { Issue } from '@hcengineering/tracker'
import { Button, IconDetails, IconDetailsFilled } from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { FilterBar, getActiveViewletId, getViewOptions, setActiveViewletId } from '@hcengineering/view-resources'
import {
FilterBar,
getActiveViewletId,
getViewOptions,
viewOptionStore,
setActiveViewletId
} from '@hcengineering/view-resources'
import ViewletSettingButton from '@hcengineering/view-resources/src/components/ViewletSettingButton.svelte'
import tracker from '../../plugin'
import IssuesContent from './IssuesContent.svelte'
@ -65,7 +71,7 @@
$: if (docWidth <= 900 && !docSize) docSize = true
$: if (docWidth > 900 && docSize) docSize = false
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
<IssuesHeader {viewlets} {label} {space} bind:viewlet bind:search showLabelSelector={$$slots.label_selector}>

View File

@ -29,7 +29,13 @@
navigate
} from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { createFilter, filterStore, getViewOptions, ViewletSettingButton } from '@hcengineering/view-resources'
import {
createFilter,
filterStore,
getViewOptions,
viewOptionStore,
ViewletSettingButton
} from '@hcengineering/view-resources'
import tracker from '../../../plugin'
import CreateSubIssue from './CreateSubIssue.svelte'
import SubIssueList from './SubIssueList.svelte'
@ -86,7 +92,7 @@
statusesQuery.unsubscribe()
}
$: viewOptions = viewlet !== undefined ? getViewOptions(viewlet) : undefined
$: viewOptions = viewlet !== undefined ? getViewOptions(viewlet, $viewOptionStore) : undefined
</script>
<div class="flex-between">

View File

@ -4,7 +4,12 @@
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, Icon, IconAdd, Label, showPopup, Component } from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { getViewOptions, ViewletSettingButton, getAdditionalHeader } from '@hcengineering/view-resources'
import {
getViewOptions,
ViewletSettingButton,
viewOptionStore,
getAdditionalHeader
} from '@hcengineering/view-resources'
import viewplg from '@hcengineering/view-resources/src/plugin'
import tracker from '../../../plugin'
import RelatedIssues from './RelatedIssues.svelte'
@ -22,7 +27,7 @@
;[viewlet] = res
})
let viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
const createIssue = () => showPopup(tracker.component.CreateIssue, { relatedTo: object, space: object.space }, 'top')
let query: DocumentQuery<Issue>

View File

@ -24,6 +24,7 @@
FilterButton,
getActiveViewletId,
getViewOptions,
viewOptionStore,
setActiveViewletId,
ViewletSettingButton
} from '@hcengineering/view-resources'
@ -90,7 +91,7 @@
$: if (docWidth <= 900 && !docSize) docSize = true
$: if (docWidth > 900 && docSize) docSize = false
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
const handleViewModeChanged = (newMode: SprintViewMode) => {
if (newMode === undefined || newMode === mode) {

View File

@ -5,7 +5,13 @@
import { IssueTemplate } from '@hcengineering/tracker'
import { Button, IconAdd, IconDetails, IconDetailsFilled, showPopup } from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { FilterBar, getActiveViewletId, getViewOptions, setActiveViewletId } from '@hcengineering/view-resources'
import {
FilterBar,
getActiveViewletId,
getViewOptions,
viewOptionStore,
setActiveViewletId
} from '@hcengineering/view-resources'
import ViewletSettingButton from '@hcengineering/view-resources/src/components/ViewletSettingButton.svelte'
import tracker from '../../plugin'
import IssuesHeader from '../issues/IssuesHeader.svelte'
@ -71,7 +77,7 @@
showPopup(CreateIssueTemplate, { targetElement: null, space }, 'top')
}
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
<IssuesHeader {space} {viewlets} {label} bind:viewlet bind:search showLabelSelector={$$slots.label_selector}>

View File

@ -16,14 +16,14 @@
import { Class, Doc, DocumentQuery, Ref } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import { Button, eventToHTMLElement, getCurrentLocation, IconAdd, locationToUrl, showPopup } from '@hcengineering/ui'
import { Button, eventToHTMLElement, IconAdd, showPopup } from '@hcengineering/ui'
import { Filter, ViewOptions } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import { filterStore } from '../../filter'
import { filterStore, getFilterKey } from '../../filter'
import view from '../../plugin'
import FilterSave from './FilterSave.svelte'
import FilterSection from './FilterSection.svelte'
import FilterTypePopup from './FilterTypePopup.svelte'
import FilterSave from './FilterSave.svelte'
export let _class: Ref<Class<Doc>>
export let query: DocumentQuery<Doc>
@ -71,7 +71,7 @@
$: saveFilters($filterStore)
function saveFilters (filters: Filter[]) {
const key = makeKey(_class)
const key = getFilterKey(_class)
if (filters.length > 0) {
localStorage.setItem(key, JSON.stringify(filters))
} else {
@ -80,7 +80,7 @@
}
async function saveFilteredView () {
showPopup(FilterSave, { viewOptions })
showPopup(FilterSave, { viewOptions, _class })
}
let loading = false
@ -88,7 +88,7 @@
function load (_class: Ref<Class<Doc>>) {
loading = true
const oldFilters = $filterStore
const key = makeKey(_class)
const key = getFilterKey(_class)
const saved = localStorage.getItem(key)
if (saved !== null) {
$filterStore = JSON.parse(saved)
@ -99,13 +99,6 @@
oldFilters.forEach((p) => p.onRemove?.())
}
function makeKey (_class: Ref<Class<Doc>>): string {
const loc = getCurrentLocation()
loc.fragment = undefined
loc.query = undefined
return 'filter' + locationToUrl(loc) + _class
}
async function makeQuery (query: DocumentQuery<Doc>, filters: Filter[]): Promise<void> {
const newQuery = hierarchy.clone(query)
for (let i = 0; i < filters.length; i++) {

View File

@ -6,10 +6,11 @@
import { createEventDispatcher } from 'svelte'
import { filterStore } from '../../filter'
import { ViewOptions } from '@hcengineering/view'
import { Doc, Ref } from '@hcengineering/core'
import { Class, Doc, Ref } from '@hcengineering/core'
import { getActiveViewletId } from '../../utils'
export let viewOptions: ViewOptions | undefined = undefined
export let _class: Ref<Class<Doc>>
let filterName = ''
const client = getClient()

View File

@ -11,7 +11,7 @@ import core, {
} from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { createQuery, getClient, LiveQuery } from '@hcengineering/presentation'
import { AnyComponent } from '@hcengineering/ui'
import { AnyComponent, getCurrentLocation, locationToUrl } from '@hcengineering/ui'
import { Filter, FilterMode, KeyFilter } from '@hcengineering/view'
import { writable } from 'svelte/store'
import view from './plugin'
@ -172,3 +172,10 @@ export function createFilter (_class: Ref<Class<Doc>>, key: string, value: any[]
mode: modes.mode
}
}
export function getFilterKey (_class: Ref<Class<Doc>>): string {
const loc = getCurrentLocation()
loc.fragment = undefined
loc.query = undefined
return 'filter' + locationToUrl(loc) + _class
}

View File

@ -10,6 +10,7 @@ import {
ViewOptions,
ViewOptionsModel
} from '@hcengineering/view'
import { get, writable } from 'svelte/store'
import view from './plugin'
export const noCategory = '#no_category'
@ -35,20 +36,29 @@ function makeViewOptionsKey (viewlet: Viewlet): string {
return `viewOptions:${prefix}:${locationToUrl(loc)}`
}
function _setViewOptions (viewlet: Viewlet, options: ViewOptions): void {
export function setViewOptions (viewlet: Viewlet, options: ViewOptions): void {
const key = makeViewOptionsKey(viewlet)
localStorage.setItem(key, JSON.stringify(options))
setStore(key, options)
}
export function setViewOptions (viewlet: Viewlet, options: ViewOptions): void {
_setViewOptions(viewlet, options)
function setStore (key: string, options: ViewOptions): void {
const map = get(viewOptionStore)
map.set(key, options)
viewOptionStore.set(map)
}
function _getViewOptions (viewlet: Viewlet): ViewOptions | null {
function _getViewOptions (viewlet: Viewlet, viewOptionStore: Map<string, ViewOptions>): ViewOptions | null {
const key = makeViewOptionsKey(viewlet)
const store = viewOptionStore.get(key)
if (store !== undefined) {
return store
}
const options = localStorage.getItem(key)
if (options === null) return null
return JSON.parse(options)
const res = JSON.parse(options)
setStore(key, res)
return res
}
function getDefaults (viewOptions: ViewOptionsModel): ViewOptions {
@ -62,11 +72,15 @@ function getDefaults (viewOptions: ViewOptionsModel): ViewOptions {
return res
}
export function getViewOptions (viewlet: Viewlet | undefined, defaults = defaulOptions): ViewOptions {
export function getViewOptions (
viewlet: Viewlet | undefined,
viewOptionStore: Map<string, ViewOptions>,
defaults = defaulOptions
): ViewOptions {
if (viewlet === undefined) {
return { ...defaults }
}
const res = _getViewOptions(viewlet)
const res = _getViewOptions(viewlet, viewOptionStore)
if (res !== null) return res
return viewlet.viewOptions != null ? getDefaults(viewlet.viewOptions) : defaults
}
@ -132,3 +146,5 @@ export const CategoryQuery = {
this.results.delete(index)
}
}
export const viewOptionStore = writable(new Map<string, ViewOptions>())

View File

@ -89,6 +89,7 @@ export interface FilteredView extends Preference {
location: PlatformLocation
filters: string
viewOptions?: ViewOptions
filterClass?: Ref<Class<Doc>>
viewletId?: Ref<Viewlet> | null
}

View File

@ -4,7 +4,14 @@
import setting from '@hcengineering/setting'
import { Action, navigate } from '@hcengineering/ui'
import view, { FilteredView } from '@hcengineering/view'
import { filterStore, setActiveViewletId, setViewOptions, TreeNode, TreeItem } from '@hcengineering/view-resources'
import {
filterStore,
getFilterKey,
setActiveViewletId,
setViewOptions,
TreeItem,
TreeNode
} from '@hcengineering/view-resources'
import { Application } from '@hcengineering/workbench'
export let currentApplication: Application | undefined
@ -41,6 +48,11 @@
setViewOptions(viewlet, fv.viewOptions)
}
}
if (fv.filterClass !== undefined) {
const key = getFilterKey(fv.filterClass)
const filters = JSON.parse(fv.filters)
localStorage.setItem(key, JSON.stringify(filters))
}
navigate(fv.location)
$filterStore = JSON.parse(fv.filters)
}

View File

@ -18,7 +18,7 @@
import { getClient } from '@hcengineering/presentation'
import { AnyComponent, Component } from '@hcengineering/ui'
import view, { Viewlet } from '@hcengineering/view'
import { getActiveViewletId, getViewOptions } from '@hcengineering/view-resources'
import { getActiveViewletId, getViewOptions, viewOptionStore } from '@hcengineering/view-resources'
import type { ViewConfiguration } from '@hcengineering/workbench'
import SpaceContent from './SpaceContent.svelte'
import SpaceHeader from './SpaceHeader.svelte'
@ -80,7 +80,7 @@
viewlet = e.detail
}
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
{#if _class && space}

View File

@ -34,6 +34,7 @@
FilterButton,
getViewOptions,
setActiveViewletId,
viewOptionStore,
ViewletSettingButton
} from '@hcengineering/view-resources'
@ -100,7 +101,7 @@
$: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(viewlet)
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>