mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-09 09:20:54 +00:00
Fix statuses (#3666)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
47e39eae75
commit
f3c3541964
@ -35,12 +35,13 @@ import contact from '@hcengineering/model-contact'
|
|||||||
import core, { TDoc, TType } from '@hcengineering/model-core'
|
import core, { TDoc, TType } from '@hcengineering/model-core'
|
||||||
import preference, { TPreference } from '@hcengineering/model-preference'
|
import preference, { TPreference } from '@hcengineering/model-preference'
|
||||||
import tags from '@hcengineering/model-tags'
|
import tags from '@hcengineering/model-tags'
|
||||||
import task, { TSpaceWithStates, TTask } from '@hcengineering/model-task'
|
import task, { TSpaceWithStates, TTask, actionTemplates as taskActionTemplates } from '@hcengineering/model-task'
|
||||||
import view, { actionTemplates, createAction, actionTemplates as viewTemplates } from '@hcengineering/model-view'
|
import view, { actionTemplates, createAction, actionTemplates as viewTemplates } from '@hcengineering/model-view'
|
||||||
import workbench, { Application } from '@hcengineering/model-workbench'
|
import workbench, { Application } from '@hcengineering/model-workbench'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import type { AnyComponent } from '@hcengineering/ui'
|
import type { AnyComponent } from '@hcengineering/ui'
|
||||||
import board from './plugin'
|
import board from './plugin'
|
||||||
|
import { State } from '@hcengineering/task'
|
||||||
|
|
||||||
export { boardId } from '@hcengineering/board'
|
export { boardId } from '@hcengineering/board'
|
||||||
export { boardOperation } from './migration'
|
export { boardOperation } from './migration'
|
||||||
@ -99,6 +100,9 @@ export class TCard extends TTask implements Card {
|
|||||||
|
|
||||||
@Prop(TypeDate(), task.string.StartDate)
|
@Prop(TypeDate(), task.string.StartDate)
|
||||||
startDate!: Timestamp | null
|
startDate!: Timestamp | null
|
||||||
|
|
||||||
|
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: board.attribute.State })
|
||||||
|
declare status: Ref<State>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(board.class.MenuPage, core.class.Doc, DOMAIN_MODEL)
|
@Model(board.class.MenuPage, core.class.Doc, DOMAIN_MODEL)
|
||||||
@ -167,6 +171,27 @@ export function createModel (builder: Builder): void {
|
|||||||
board.app.Board
|
board.app.Board
|
||||||
)
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
...taskActionTemplates.editStatus,
|
||||||
|
target: board.class.Board,
|
||||||
|
actionProps: {
|
||||||
|
ofAttribute: board.attribute.State,
|
||||||
|
doneOfAttribute: board.attribute.DoneState
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
archived: false
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
mode: ['context', 'browser'],
|
||||||
|
group: 'edit'
|
||||||
|
},
|
||||||
|
override: [task.action.EditStatuses]
|
||||||
|
},
|
||||||
|
board.action.EditStatuses
|
||||||
|
)
|
||||||
|
|
||||||
// const leadLookup: Lookup<Card> =
|
// const leadLookup: Lookup<Card> =
|
||||||
// {
|
// {
|
||||||
// state: task.class.State,
|
// state: task.class.State,
|
||||||
|
@ -22,7 +22,7 @@ import task, { KanbanTemplate, createStates } from '@hcengineering/task'
|
|||||||
import board from './plugin'
|
import board from './plugin'
|
||||||
|
|
||||||
async function createSpace (tx: TxOperations): Promise<void> {
|
async function createSpace (tx: TxOperations): Promise<void> {
|
||||||
const currentTemplate = await tx.findOne(core.class.Space, {
|
const currentTemplate = await tx.findOne(task.class.KanbanTemplateSpace, {
|
||||||
_id: board.space.BoardTemplates
|
_id: board.space.BoardTemplates
|
||||||
})
|
})
|
||||||
if (currentTemplate === undefined) {
|
if (currentTemplate === undefined) {
|
||||||
@ -36,10 +36,17 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
private: false,
|
private: false,
|
||||||
archived: false,
|
archived: false,
|
||||||
members: [],
|
members: [],
|
||||||
attachedToClass: board.class.Board
|
attachedToClass: board.class.Board,
|
||||||
|
ofAttribute: board.attribute.State,
|
||||||
|
doneAttribute: board.attribute.DoneState
|
||||||
},
|
},
|
||||||
board.space.BoardTemplates
|
board.space.BoardTemplates
|
||||||
)
|
)
|
||||||
|
} else if (currentTemplate.ofAttribute === undefined) {
|
||||||
|
await tx.update(currentTemplate, {
|
||||||
|
ofAttribute: board.attribute.State,
|
||||||
|
doneAttribute: board.attribute.DoneState
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const current = await tx.findOne(core.class.Space, {
|
const current = await tx.findOne(core.class.Space, {
|
||||||
@ -47,7 +54,7 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
})
|
})
|
||||||
if (current === undefined) {
|
if (current === undefined) {
|
||||||
const defaultTmpl = await createDefaultKanbanTemplate(tx)
|
const defaultTmpl = await createDefaultKanbanTemplate(tx)
|
||||||
const [states, doneStates] = await createStates(tx, defaultTmpl)
|
const [states, doneStates] = await createStates(tx, board.attribute.State, board.attribute.DoneState, defaultTmpl)
|
||||||
await tx.createDoc(
|
await tx.createDoc(
|
||||||
board.class.Board,
|
board.class.Board,
|
||||||
core.space.Space,
|
core.space.Space,
|
||||||
@ -77,13 +84,18 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Kanba
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createKanbanTemplate(tx, {
|
return await createKanbanTemplate(
|
||||||
kanbanId: board.template.DefaultBoard,
|
tx,
|
||||||
space: board.space.BoardTemplates,
|
{
|
||||||
title: 'Default board',
|
kanbanId: board.template.DefaultBoard,
|
||||||
states: defaultKanban.states,
|
space: board.space.BoardTemplates,
|
||||||
doneStates: defaultKanban.doneStates
|
title: 'Default board',
|
||||||
})
|
states: defaultKanban.states,
|
||||||
|
doneStates: defaultKanban.doneStates
|
||||||
|
},
|
||||||
|
board.attribute.State,
|
||||||
|
board.attribute.DoneState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
async function createDefaults (tx: TxOperations): Promise<void> {
|
async function createDefaults (tx: TxOperations): Promise<void> {
|
||||||
await createSpace(tx)
|
await createSpace(tx)
|
||||||
|
@ -62,6 +62,7 @@ export default mergeIds(boardId, board, {
|
|||||||
ConfigDescription: '' as IntlString
|
ConfigDescription: '' as IntlString
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
|
EditStatuses: '' as Ref<Action>,
|
||||||
ConvertToCard: '' as Ref<Action>
|
ConvertToCard: '' as Ref<Action>
|
||||||
},
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
|
@ -81,7 +81,7 @@ export class TLead extends TTask implements Lead {
|
|||||||
@Prop(TypeRef(contact.mixin.Employee), lead.string.Assignee)
|
@Prop(TypeRef(contact.mixin.Employee), lead.string.Assignee)
|
||||||
declare assignee: Ref<Employee> | null
|
declare assignee: Ref<Employee> | null
|
||||||
|
|
||||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: task.attribute.State })
|
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: lead.attribute.State })
|
||||||
declare status: Ref<State>
|
declare status: Ref<State>
|
||||||
|
|
||||||
declare space: Ref<Funnel>
|
declare space: Ref<Funnel>
|
||||||
@ -365,6 +365,27 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
...actionTemplates.editStatus,
|
||||||
|
target: lead.class.Funnel,
|
||||||
|
actionProps: {
|
||||||
|
ofAttribute: lead.attribute.State,
|
||||||
|
doneOfAttribute: lead.attribute.DoneState
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
archived: false
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
mode: ['context', 'browser'],
|
||||||
|
group: 'edit'
|
||||||
|
},
|
||||||
|
override: [task.action.EditStatuses]
|
||||||
|
},
|
||||||
|
lead.action.EditStatuses
|
||||||
|
)
|
||||||
|
|
||||||
builder.createDoc(
|
builder.createDoc(
|
||||||
notification.class.NotificationGroup,
|
notification.class.NotificationGroup,
|
||||||
core.space.Model,
|
core.space.Model,
|
||||||
|
@ -22,7 +22,7 @@ import { PaletteColorIndexes } from '@hcengineering/ui/src/colors'
|
|||||||
import lead from './plugin'
|
import lead from './plugin'
|
||||||
|
|
||||||
async function createSpace (tx: TxOperations): Promise<void> {
|
async function createSpace (tx: TxOperations): Promise<void> {
|
||||||
const currentTemplate = await tx.findOne(core.class.Space, {
|
const currentTemplate = await tx.findOne(task.class.KanbanTemplateSpace, {
|
||||||
_id: lead.space.FunnelTemplates
|
_id: lead.space.FunnelTemplates
|
||||||
})
|
})
|
||||||
if (currentTemplate === undefined) {
|
if (currentTemplate === undefined) {
|
||||||
@ -36,10 +36,17 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
private: false,
|
private: false,
|
||||||
members: [],
|
members: [],
|
||||||
archived: false,
|
archived: false,
|
||||||
attachedToClass: lead.class.Funnel
|
attachedToClass: lead.class.Funnel,
|
||||||
|
ofAttribute: lead.attribute.State,
|
||||||
|
doneAttribute: lead.attribute.DoneState
|
||||||
},
|
},
|
||||||
lead.space.FunnelTemplates
|
lead.space.FunnelTemplates
|
||||||
)
|
)
|
||||||
|
} else if (currentTemplate.ofAttribute === undefined) {
|
||||||
|
await tx.update(currentTemplate, {
|
||||||
|
ofAttribute: lead.attribute.State,
|
||||||
|
doneAttribute: lead.attribute.DoneState
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const current = await tx.findOne(core.class.Space, {
|
const current = await tx.findOne(core.class.Space, {
|
||||||
@ -47,7 +54,7 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
})
|
})
|
||||||
if (current === undefined) {
|
if (current === undefined) {
|
||||||
const defaultTmpl = await createDefaultKanbanTemplate(tx)
|
const defaultTmpl = await createDefaultKanbanTemplate(tx)
|
||||||
const [states, doneStates] = await createStates(tx, defaultTmpl)
|
const [states, doneStates] = await createStates(tx, lead.attribute.State, lead.attribute.DoneState, defaultTmpl)
|
||||||
await tx.createDoc(
|
await tx.createDoc(
|
||||||
lead.class.Funnel,
|
lead.class.Funnel,
|
||||||
core.space.Space,
|
core.space.Space,
|
||||||
@ -81,13 +88,18 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Kanba
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createKanbanTemplate(tx, {
|
return await createKanbanTemplate(
|
||||||
kanbanId: lead.template.DefaultFunnel,
|
tx,
|
||||||
space: lead.space.FunnelTemplates,
|
{
|
||||||
title: 'Default funnel',
|
kanbanId: lead.template.DefaultFunnel,
|
||||||
states: defaultKanban.states,
|
space: lead.space.FunnelTemplates,
|
||||||
doneStates: defaultKanban.doneStates
|
title: 'Default funnel',
|
||||||
})
|
states: defaultKanban.states,
|
||||||
|
doneStates: defaultKanban.doneStates
|
||||||
|
},
|
||||||
|
lead.attribute.State,
|
||||||
|
lead.attribute.DoneState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fixTemplateSpace (tx: TxOperations): Promise<void> {
|
async function fixTemplateSpace (tx: TxOperations): Promise<void> {
|
||||||
|
@ -60,6 +60,7 @@ export default mergeIds(leadId, lead, {
|
|||||||
Lead: '' as Ref<ActionCategory>
|
Lead: '' as Ref<ActionCategory>
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
|
EditStatuses: '' as Ref<Action>,
|
||||||
CreateGlobalLead: '' as Ref<Action>
|
CreateGlobalLead: '' as Ref<Action>
|
||||||
},
|
},
|
||||||
ids: {
|
ids: {
|
||||||
|
@ -165,7 +165,7 @@ export class TApplicant extends TTask implements Applicant {
|
|||||||
@Prop(TypeRef(contact.mixin.Employee), recruit.string.AssignedRecruiter)
|
@Prop(TypeRef(contact.mixin.Employee), recruit.string.AssignedRecruiter)
|
||||||
declare assignee: Ref<Employee> | null
|
declare assignee: Ref<Employee> | null
|
||||||
|
|
||||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: task.attribute.State })
|
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: recruit.attribute.State })
|
||||||
declare status: Ref<State>
|
declare status: Ref<State>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +368,27 @@ export function createModel (builder: Builder): void {
|
|||||||
recruit.app.Recruit
|
recruit.app.Recruit
|
||||||
)
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
...actionTemplates.editStatus,
|
||||||
|
target: recruit.class.Vacancy,
|
||||||
|
actionProps: {
|
||||||
|
ofAttribute: recruit.attribute.State,
|
||||||
|
doneOfAttribute: recruit.attribute.DoneState
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
archived: false
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
mode: ['context', 'browser'],
|
||||||
|
group: 'edit'
|
||||||
|
},
|
||||||
|
override: [task.action.EditStatuses]
|
||||||
|
},
|
||||||
|
recruit.action.EditStatuses
|
||||||
|
)
|
||||||
|
|
||||||
builder.createDoc(
|
builder.createDoc(
|
||||||
view.class.Viewlet,
|
view.class.Viewlet,
|
||||||
core.space.Model,
|
core.space.Model,
|
||||||
|
@ -92,15 +92,20 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Kanba
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return await createKanbanTemplate(tx, {
|
return await createKanbanTemplate(
|
||||||
kanbanId: recruit.template.DefaultVacancy,
|
tx,
|
||||||
space: recruit.space.VacancyTemplates as Ref<Doc> as Ref<Space>,
|
{
|
||||||
title: 'Default vacancy',
|
kanbanId: recruit.template.DefaultVacancy,
|
||||||
description: '',
|
space: recruit.space.VacancyTemplates as Ref<Doc> as Ref<Space>,
|
||||||
shortDescription: '',
|
title: 'Default vacancy',
|
||||||
states: defaultKanban.states,
|
description: '',
|
||||||
doneStates: defaultKanban.doneStates
|
shortDescription: '',
|
||||||
})
|
states: defaultKanban.states,
|
||||||
|
doneStates: defaultKanban.doneStates
|
||||||
|
},
|
||||||
|
recruit.attribute.State,
|
||||||
|
recruit.attribute.DoneState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createSpaces (tx: TxOperations): Promise<void> {
|
async function createSpaces (tx: TxOperations): Promise<void> {
|
||||||
@ -142,7 +147,7 @@ async function createSpaces (tx: TxOperations): Promise<void> {
|
|||||||
await tx.update(currentReviews, { private: false })
|
await tx.update(currentReviews, { private: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentTemplate = await tx.findOne(core.class.Space, {
|
const currentTemplate = await tx.findOne(task.class.KanbanTemplateSpace, {
|
||||||
_id: recruit.space.VacancyTemplates
|
_id: recruit.space.VacancyTemplates
|
||||||
})
|
})
|
||||||
if (currentTemplate === undefined) {
|
if (currentTemplate === undefined) {
|
||||||
@ -157,9 +162,16 @@ async function createSpaces (tx: TxOperations): Promise<void> {
|
|||||||
private: false,
|
private: false,
|
||||||
members: [],
|
members: [],
|
||||||
archived: false,
|
archived: false,
|
||||||
attachedToClass: recruit.class.Vacancy
|
attachedToClass: recruit.class.Vacancy,
|
||||||
|
ofAttribute: recruit.attribute.State,
|
||||||
|
doneAttribute: recruit.attribute.DoneState
|
||||||
},
|
},
|
||||||
recruit.space.VacancyTemplates
|
recruit.space.VacancyTemplates
|
||||||
)
|
)
|
||||||
|
} else if (currentTemplate.ofAttribute === undefined) {
|
||||||
|
await tx.update(currentTemplate, {
|
||||||
|
ofAttribute: recruit.attribute.State,
|
||||||
|
doneAttribute: recruit.attribute.DoneState
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
CopyApplicationLink: '' as Ref<Action>,
|
CopyApplicationLink: '' as Ref<Action>,
|
||||||
CopyCandidateLink: '' as Ref<Action>,
|
CopyCandidateLink: '' as Ref<Action>,
|
||||||
MoveApplicant: '' as Ref<Action>,
|
MoveApplicant: '' as Ref<Action>,
|
||||||
GetTalentIds: '' as Ref<Action>
|
GetTalentIds: '' as Ref<Action>,
|
||||||
|
EditStatuses: '' as Ref<Action>
|
||||||
},
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
CreateOpinion: '' as ViewAction,
|
CreateOpinion: '' as ViewAction,
|
||||||
|
@ -158,6 +158,8 @@ export class TKanbanTemplateSpace extends TSpace implements KanbanTemplateSpace
|
|||||||
description!: IntlString
|
description!: IntlString
|
||||||
icon!: AnyComponent
|
icon!: AnyComponent
|
||||||
editor!: AnyComponent
|
editor!: AnyComponent
|
||||||
|
ofAttribute!: Ref<Attribute<State>>
|
||||||
|
doneAttribute!: Ref<Attribute<DoneState>>
|
||||||
attachedToClass!: Ref<Class<Doc>>
|
attachedToClass!: Ref<Class<Doc>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +339,10 @@ export function createModel (builder: Builder): void {
|
|||||||
{
|
{
|
||||||
...actionTemplates.editStatus,
|
...actionTemplates.editStatus,
|
||||||
target: task.class.SpaceWithStates,
|
target: task.class.SpaceWithStates,
|
||||||
|
actionProps: {
|
||||||
|
ofAttribute: task.attribute.State,
|
||||||
|
doneOfAttribute: task.attribute.DoneState
|
||||||
|
},
|
||||||
query: {
|
query: {
|
||||||
archived: false
|
archived: false
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Attribute,
|
||||||
Class,
|
Class,
|
||||||
DOMAIN_STATUS,
|
DOMAIN_STATUS,
|
||||||
DOMAIN_TX,
|
DOMAIN_TX,
|
||||||
@ -25,13 +26,14 @@ import {
|
|||||||
TxCollectionCUD,
|
TxCollectionCUD,
|
||||||
TxCreateDoc,
|
TxCreateDoc,
|
||||||
TxOperations,
|
TxOperations,
|
||||||
TxUpdateDoc
|
TxUpdateDoc,
|
||||||
|
toIdMap
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient, createOrUpdate } from '@hcengineering/model'
|
import { MigrateOperation, MigrationClient, MigrationUpgradeClient, createOrUpdate } from '@hcengineering/model'
|
||||||
import core, { DOMAIN_SPACE } from '@hcengineering/model-core'
|
import core, { DOMAIN_SPACE } from '@hcengineering/model-core'
|
||||||
import tags from '@hcengineering/model-tags'
|
import tags from '@hcengineering/model-tags'
|
||||||
import { DOMAIN_VIEW } from '@hcengineering/model-view'
|
import { DOMAIN_VIEW } from '@hcengineering/model-view'
|
||||||
import { DoneStateTemplate, KanbanTemplate, StateTemplate, Task, genRanks } from '@hcengineering/task'
|
import { DoneState, DoneStateTemplate, KanbanTemplate, State, StateTemplate, Task, genRanks } from '@hcengineering/task'
|
||||||
import view, { Filter, FilteredView } from '@hcengineering/view'
|
import view, { Filter, FilteredView } from '@hcengineering/view'
|
||||||
import { DOMAIN_TASK } from '.'
|
import { DOMAIN_TASK } from '.'
|
||||||
import task from './plugin'
|
import task from './plugin'
|
||||||
@ -73,7 +75,9 @@ export async function createSequence (tx: TxOperations, _class: Ref<Class<Doc>>)
|
|||||||
*/
|
*/
|
||||||
export async function createKanbanTemplate (
|
export async function createKanbanTemplate (
|
||||||
client: TxOperations,
|
client: TxOperations,
|
||||||
data: KanbanTemplateData
|
data: KanbanTemplateData,
|
||||||
|
ofAttribute: Ref<Attribute<Status>>,
|
||||||
|
doneAtrtribute?: Ref<Attribute<DoneState>>
|
||||||
): Promise<Ref<KanbanTemplate>> {
|
): Promise<Ref<KanbanTemplate>> {
|
||||||
const current = await client.findOne(task.class.KanbanTemplate, { _id: data.kanbanId })
|
const current = await client.findOne(task.class.KanbanTemplate, { _id: data.kanbanId })
|
||||||
if (current !== undefined) {
|
if (current !== undefined) {
|
||||||
@ -96,7 +100,7 @@ export async function createKanbanTemplate (
|
|||||||
data.doneStates.map((st, i) =>
|
data.doneStates.map((st, i) =>
|
||||||
client.createDoc(st.isWon ? task.class.WonStateTemplate : task.class.LostStateTemplate, data.space, {
|
client.createDoc(st.isWon ? task.class.WonStateTemplate : task.class.LostStateTemplate, data.space, {
|
||||||
rank: doneStateRanks[i],
|
rank: doneStateRanks[i],
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute: doneAtrtribute ?? ofAttribute,
|
||||||
name: st.name,
|
name: st.name,
|
||||||
attachedTo: data.kanbanId
|
attachedTo: data.kanbanId
|
||||||
})
|
})
|
||||||
@ -108,7 +112,7 @@ export async function createKanbanTemplate (
|
|||||||
data.states.map((st, i) =>
|
data.states.map((st, i) =>
|
||||||
client.createDoc(task.class.StateTemplate, data.space, {
|
client.createDoc(task.class.StateTemplate, data.space, {
|
||||||
attachedTo: data.kanbanId,
|
attachedTo: data.kanbanId,
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
rank: stateRanks[i],
|
rank: stateRanks[i],
|
||||||
name: st.name,
|
name: st.name,
|
||||||
color: st.color
|
color: st.color
|
||||||
@ -226,7 +230,46 @@ async function renameStatePrefs (client: MigrationUpgradeClient): Promise<void>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fixStatusAttributes (client: MigrationClient): Promise<void> {
|
||||||
|
const spaces = await client.find<Space>(DOMAIN_SPACE, {})
|
||||||
|
const map = toIdMap(spaces)
|
||||||
|
const oldStatuses = await client.find<OldStatus>(DOMAIN_STATUS, { space: { $ne: task.space.Statuses } })
|
||||||
|
for (const oldStatus of oldStatuses) {
|
||||||
|
const space = map.get(oldStatus.space)
|
||||||
|
if (space !== undefined) {
|
||||||
|
try {
|
||||||
|
const isDone = oldStatus._class === task.class.DoneState
|
||||||
|
let ofAttribute = task.attribute.State
|
||||||
|
if (space._class === ('recruit:class:Vacancy' as Ref<Class<Space>>)) {
|
||||||
|
ofAttribute = isDone
|
||||||
|
? ('recruit.attribute.DoneState' as Ref<Attribute<State>>)
|
||||||
|
: ('recruit:attribute:State' as Ref<Attribute<State>>)
|
||||||
|
}
|
||||||
|
if (space._class === ('lead:class:Funnel' as Ref<Class<Space>>)) {
|
||||||
|
ofAttribute = isDone
|
||||||
|
? ('lead.attribute.DoneState' as Ref<Attribute<State>>)
|
||||||
|
: ('lead:attribute:State' as Ref<Attribute<State>>)
|
||||||
|
}
|
||||||
|
if (space._class === ('board:class:Board' as Ref<Class<Space>>)) {
|
||||||
|
ofAttribute = isDone
|
||||||
|
? ('board.attribute.DoneState' as Ref<Attribute<State>>)
|
||||||
|
: ('board:attribute:State' as Ref<Attribute<State>>)
|
||||||
|
}
|
||||||
|
if (space._class === ('tracker:class:Project' as Ref<Class<Space>>)) {
|
||||||
|
ofAttribute = 'tracker:attribute:IssueStatus' as Ref<Attribute<State>>
|
||||||
|
}
|
||||||
|
if (ofAttribute !== oldStatus.ofAttribute) {
|
||||||
|
await client.update(DOMAIN_STATUS, { _id: oldStatus._id }, { ofAttribute })
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function migrateStatuses (client: MigrationClient): Promise<void> {
|
async function migrateStatuses (client: MigrationClient): Promise<void> {
|
||||||
|
await fixStatusAttributes(client)
|
||||||
const oldStatuses = await client.find<OldStatus>(DOMAIN_STATUS, { space: { $ne: task.space.Statuses } })
|
const oldStatuses = await client.find<OldStatus>(DOMAIN_STATUS, { space: { $ne: task.space.Statuses } })
|
||||||
const newStatuses: Map<string, Status> = new Map()
|
const newStatuses: Map<string, Status> = new Map()
|
||||||
const oldStatusesMap = new Map<Ref<Status>, Ref<Status>>()
|
const oldStatusesMap = new Map<Ref<Status>, Ref<Status>>()
|
||||||
|
@ -23,7 +23,12 @@ export async function createVacancy (
|
|||||||
|
|
||||||
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
|
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
|
||||||
|
|
||||||
const [states, doneStates] = await createStates(client, templateId)
|
const [states, doneStates] = await createStates(
|
||||||
|
client,
|
||||||
|
recruit.attribute.State,
|
||||||
|
recruit.attribute.DoneState,
|
||||||
|
templateId
|
||||||
|
)
|
||||||
|
|
||||||
const id = await client.createDoc(recruit.class.Vacancy, core.space.Space, {
|
const id = await client.createDoc(recruit.class.Vacancy, core.space.Space, {
|
||||||
name,
|
name,
|
||||||
|
@ -25,7 +25,7 @@ export async function createBoard (
|
|||||||
description: string,
|
description: string,
|
||||||
templateId?: Ref<KanbanTemplate>
|
templateId?: Ref<KanbanTemplate>
|
||||||
): Promise<Ref<Board>> {
|
): Promise<Ref<Board>> {
|
||||||
const [states, doneStates] = await createStates(client, templateId)
|
const [states, doneStates] = await createStates(client, board.attribute.State, board.attribute.DoneState, templateId)
|
||||||
|
|
||||||
const boardRef = await client.createDoc(board.class.Board, core.space.Space, {
|
const boardRef = await client.createDoc(board.class.Board, core.space.Space, {
|
||||||
name,
|
name,
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import { Employee } from '@hcengineering/contact'
|
import { Employee } from '@hcengineering/contact'
|
||||||
import type { Class, Doc, Markup, Ref, Timestamp, Type } from '@hcengineering/core'
|
import type { Attribute, Class, Doc, Markup, Ref, Timestamp, Type } from '@hcengineering/core'
|
||||||
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import type { Preference } from '@hcengineering/preference'
|
import type { Preference } from '@hcengineering/preference'
|
||||||
@ -120,6 +120,10 @@ const boards = plugin(boardId, {
|
|||||||
string: {
|
string: {
|
||||||
ConfigLabel: '' as IntlString
|
ConfigLabel: '' as IntlString
|
||||||
},
|
},
|
||||||
|
attribute: {
|
||||||
|
State: '' as Ref<Attribute<State>>,
|
||||||
|
DoneState: '' as Ref<Attribute<DoneState>>
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
Board: '' as Asset,
|
Board: '' as Asset,
|
||||||
Card: '' as Asset
|
Card: '' as Asset
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import type { Contact } from '@hcengineering/contact'
|
import type { Contact } from '@hcengineering/contact'
|
||||||
import type { Class, Doc, Ref, Timestamp } from '@hcengineering/core'
|
import type { Attribute, Class, Doc, Ref, Timestamp } from '@hcengineering/core'
|
||||||
import { Mixin } from '@hcengineering/core'
|
import { Mixin } from '@hcengineering/core'
|
||||||
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import type { KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
|
import type { DoneState, KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@ -73,6 +73,10 @@ const lead = plugin(leadId, {
|
|||||||
Lead: '' as IntlString,
|
Lead: '' as IntlString,
|
||||||
ConfigLabel: '' as IntlString
|
ConfigLabel: '' as IntlString
|
||||||
},
|
},
|
||||||
|
attribute: {
|
||||||
|
State: '' as Ref<Attribute<State>>,
|
||||||
|
DoneState: '' as Ref<Attribute<DoneState>>
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
Funnel: '' as Asset,
|
Funnel: '' as Asset,
|
||||||
Lead: '' as Asset,
|
Lead: '' as Asset,
|
||||||
|
@ -174,7 +174,12 @@
|
|||||||
|
|
||||||
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
|
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
|
||||||
|
|
||||||
const [states, doneStates] = await createStates(client, templateId)
|
const [states, doneStates] = await createStates(
|
||||||
|
client,
|
||||||
|
recruit.attribute.State,
|
||||||
|
recruit.attribute.DoneState,
|
||||||
|
templateId
|
||||||
|
)
|
||||||
|
|
||||||
const id = await client.createDoc(
|
const id = await client.createDoc(
|
||||||
recruit.class.Vacancy,
|
recruit.class.Vacancy,
|
||||||
|
@ -15,11 +15,21 @@
|
|||||||
|
|
||||||
import { Event } from '@hcengineering/calendar'
|
import { Event } from '@hcengineering/calendar'
|
||||||
import type { Channel, Organization, Person } from '@hcengineering/contact'
|
import type { Channel, Organization, Person } from '@hcengineering/contact'
|
||||||
import type { AttachedData, AttachedDoc, Class, Doc, Mixin, Ref, Space, Timestamp } from '@hcengineering/core'
|
import type {
|
||||||
|
AttachedData,
|
||||||
|
AttachedDoc,
|
||||||
|
Attribute,
|
||||||
|
Class,
|
||||||
|
Doc,
|
||||||
|
Mixin,
|
||||||
|
Ref,
|
||||||
|
Space,
|
||||||
|
Timestamp
|
||||||
|
} from '@hcengineering/core'
|
||||||
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
|
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import { TagReference } from '@hcengineering/tags'
|
import { TagReference } from '@hcengineering/tags'
|
||||||
import type { KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
|
import type { DoneState, KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
|
||||||
import { AnyComponent, ResolvedLocation } from '@hcengineering/ui'
|
import { AnyComponent, ResolvedLocation } from '@hcengineering/ui'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,6 +165,10 @@ const recruit = plugin(recruitId, {
|
|||||||
Candidate: '' as Ref<Mixin<Candidate>>,
|
Candidate: '' as Ref<Mixin<Candidate>>,
|
||||||
VacancyList: '' as Ref<Mixin<VacancyList>>
|
VacancyList: '' as Ref<Mixin<VacancyList>>
|
||||||
},
|
},
|
||||||
|
attribute: {
|
||||||
|
State: '' as Ref<Attribute<State>>,
|
||||||
|
DoneState: '' as Ref<Attribute<DoneState>>
|
||||||
|
},
|
||||||
component: {
|
component: {
|
||||||
EditVacancy: '' as AnyComponent
|
EditVacancy: '' as AnyComponent
|
||||||
},
|
},
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
let templateMap = new Map<Ref<KanbanTemplate>, KanbanTemplate>()
|
let templateMap = new Map<Ref<KanbanTemplate>, KanbanTemplate>()
|
||||||
const templatesQ = createQuery()
|
const templatesQ = createQuery()
|
||||||
$: if (folder !== undefined) {
|
$: if (folder !== undefined) {
|
||||||
templatesQ.query(task.class.KanbanTemplate, { space: folder._id as Ref<Doc> as Ref<Space> }, (result) => {
|
templatesQ.query(task.class.KanbanTemplate, { space: folder._id }, (result) => {
|
||||||
templates = result
|
templates = result
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
doneStates.map(async (ds) => {
|
doneStates.map(async (ds) => {
|
||||||
await client.createDoc(ds.class, space as Ref<Doc> as Ref<Space>, {
|
await client.createDoc(ds.class, space, {
|
||||||
attachedTo: template,
|
attachedTo: template,
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute: task.attribute.DoneState,
|
||||||
name: ds.name,
|
name: ds.name,
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Data, Ref } from '@hcengineering/core'
|
import { Attribute, Class, Data, Ref, Status } from '@hcengineering/core'
|
||||||
import presentation, { Card, createQuery, getClient } from '@hcengineering/presentation'
|
import presentation, { Card, createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { DoneState, SpaceWithStates, State, createState } from '@hcengineering/task'
|
import { DoneState, SpaceWithStates, State, createState } from '@hcengineering/task'
|
||||||
import { EditBox, Label } from '@hcengineering/ui'
|
import { EditBox, Label } from '@hcengineering/ui'
|
||||||
@ -25,6 +25,7 @@
|
|||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
export let status: State | undefined = undefined
|
export let status: State | undefined = undefined
|
||||||
export let _class: Ref<Class<State | DoneState>> | undefined = status?._class
|
export let _class: Ref<Class<State | DoneState>> | undefined = status?._class
|
||||||
|
export let ofAttribute: Ref<Attribute<Status>>
|
||||||
export let value = status?.name ?? ''
|
export let value = status?.name ?? ''
|
||||||
export let space: Ref<SpaceWithStates>
|
export let space: Ref<SpaceWithStates>
|
||||||
|
|
||||||
@ -40,7 +41,7 @@
|
|||||||
if (status === undefined) {
|
if (status === undefined) {
|
||||||
if (!hierarchy.isDerived(_class, task.class.DoneState)) {
|
if (!hierarchy.isDerived(_class, task.class.DoneState)) {
|
||||||
const newDoc: Data<State> = {
|
const newDoc: Data<State> = {
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
name: value.trim(),
|
name: value.trim(),
|
||||||
color: 9
|
color: 9
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@
|
|||||||
await client.update(_space, { $push: { states: id } })
|
await client.update(_space, { $push: { states: id } })
|
||||||
} else {
|
} else {
|
||||||
const newDoc: Data<DoneState> = {
|
const newDoc: Data<DoneState> = {
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute,
|
||||||
name: value.trim()
|
name: value.trim()
|
||||||
}
|
}
|
||||||
const id = await createState(client, _class, newDoc)
|
const id = await createState(client, _class, newDoc)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Data, Ref, SortingOrder } from '@hcengineering/core'
|
import { Attribute, Class, Data, Ref, SortingOrder, Status } from '@hcengineering/core'
|
||||||
import presentation, { Card, getClient } from '@hcengineering/presentation'
|
import presentation, { Card, getClient } from '@hcengineering/presentation'
|
||||||
import { DoneStateTemplate, KanbanTemplate, KanbanTemplateSpace, StateTemplate, calcRank } from '@hcengineering/task'
|
import { DoneStateTemplate, KanbanTemplate, KanbanTemplateSpace, StateTemplate, calcRank } from '@hcengineering/task'
|
||||||
import { EditBox, Label } from '@hcengineering/ui'
|
import { EditBox, Label } from '@hcengineering/ui'
|
||||||
@ -26,6 +26,7 @@
|
|||||||
export let status: StateTemplate | undefined = undefined
|
export let status: StateTemplate | undefined = undefined
|
||||||
export let _class: Ref<Class<StateTemplate | DoneStateTemplate>> | undefined = status?._class
|
export let _class: Ref<Class<StateTemplate | DoneStateTemplate>> | undefined = status?._class
|
||||||
export let template: KanbanTemplate
|
export let template: KanbanTemplate
|
||||||
|
export let ofAttribute: Ref<Attribute<Status>>
|
||||||
export let space: KanbanTemplateSpace
|
export let space: KanbanTemplateSpace
|
||||||
export let value = status?.name ?? ''
|
export let value = status?.name ?? ''
|
||||||
|
|
||||||
@ -36,14 +37,14 @@
|
|||||||
if (_class !== undefined && status === undefined) {
|
if (_class !== undefined && status === undefined) {
|
||||||
const lastOne = await client.findOne(_class, attachedTo, { sort: { rank: SortingOrder.Descending } })
|
const lastOne = await client.findOne(_class, attachedTo, { sort: { rank: SortingOrder.Descending } })
|
||||||
let newDoc: Data<StateTemplate> = {
|
let newDoc: Data<StateTemplate> = {
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
name: value.trim(),
|
name: value.trim(),
|
||||||
rank: calcRank(lastOne, undefined),
|
rank: calcRank(lastOne, undefined),
|
||||||
...attachedTo
|
...attachedTo
|
||||||
}
|
}
|
||||||
if (!hierarchy.isDerived(_class, task.class.DoneState)) {
|
if (!hierarchy.isDerived(_class, task.class.DoneState)) {
|
||||||
newDoc = {
|
newDoc = {
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
name: value.trim(),
|
name: value.trim(),
|
||||||
color: 9,
|
color: 9,
|
||||||
rank: calcRank(lastOne, undefined),
|
rank: calcRank(lastOne, undefined),
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Doc, DocumentQuery, IdMap, Ref, Status } from '@hcengineering/core'
|
import type { Attribute, Doc, DocumentQuery, IdMap, Ref, Status } from '@hcengineering/core'
|
||||||
import { MessageBox, createQuery, getClient } from '@hcengineering/presentation'
|
import { MessageBox, createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import type { DoneState, LostState, SpaceWithStates, State, WonState } from '@hcengineering/task'
|
import type { DoneState, LostState, SpaceWithStates, State, WonState } from '@hcengineering/task'
|
||||||
import { Icon, Label, Panel, Scroller, showPopup } from '@hcengineering/ui'
|
import { Icon, Label, Panel, Scroller, showPopup } from '@hcengineering/ui'
|
||||||
@ -24,6 +24,8 @@
|
|||||||
import StatesEditor from './StatesEditor.svelte'
|
import StatesEditor from './StatesEditor.svelte'
|
||||||
|
|
||||||
export let _id: Ref<SpaceWithStates>
|
export let _id: Ref<SpaceWithStates>
|
||||||
|
export let ofAttribute: Ref<Attribute<Status>>
|
||||||
|
export let doneOfAttribute: Ref<Attribute<Status>>
|
||||||
|
|
||||||
let spaceInstance: SpaceWithStates | undefined
|
let spaceInstance: SpaceWithStates | undefined
|
||||||
|
|
||||||
@ -150,13 +152,18 @@
|
|||||||
|
|
||||||
<Scroller>
|
<Scroller>
|
||||||
<div class="popupPanel-body__main-content py-10 clear-mins">
|
<div class="popupPanel-body__main-content py-10 clear-mins">
|
||||||
<StatesEditor
|
{#if spaceInstance}
|
||||||
{states}
|
<StatesEditor
|
||||||
{wonStates}
|
space={_id}
|
||||||
{lostStates}
|
{ofAttribute}
|
||||||
on:delete={(e) => deleteState(e.detail)}
|
{doneOfAttribute}
|
||||||
on:move={(e) => onMove(e.detail.stateID, e.detail.position)}
|
{states}
|
||||||
/>
|
{wonStates}
|
||||||
|
{lostStates}
|
||||||
|
on:delete={(e) => deleteState(e.detail)}
|
||||||
|
on:move={(e) => onMove(e.detail.stateID, e.detail.position)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Scroller>
|
</Scroller>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
@ -14,12 +14,11 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Ref } from '@hcengineering/core'
|
import { Attribute, Ref, Status } from '@hcengineering/core'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import type { DoneState, KanbanTemplate, KanbanTemplateSpace, State } from '@hcengineering/task'
|
import type { DoneState, SpaceWithStates, State } from '@hcengineering/task'
|
||||||
import {
|
import {
|
||||||
CircleButton,
|
CircleButton,
|
||||||
Component,
|
|
||||||
IconAdd,
|
IconAdd,
|
||||||
IconCircles,
|
IconCircles,
|
||||||
IconMoreH,
|
IconMoreH,
|
||||||
@ -39,8 +38,9 @@
|
|||||||
import Won from '../icons/Won.svelte'
|
import Won from '../icons/Won.svelte'
|
||||||
import StatusesPopup from './StatusesPopup.svelte'
|
import StatusesPopup from './StatusesPopup.svelte'
|
||||||
|
|
||||||
export let template: KanbanTemplate | undefined = undefined
|
export let space: Ref<SpaceWithStates>
|
||||||
export let space: KanbanTemplateSpace | undefined = undefined
|
export let ofAttribute: Ref<Attribute<Status>> = task.attribute.State
|
||||||
|
export let doneOfAttribute: Ref<Attribute<Status>> = task.attribute.DoneState
|
||||||
export let states: State[] = []
|
export let states: State[] = []
|
||||||
export let wonStates: DoneState[] = []
|
export let wonStates: DoneState[] = []
|
||||||
export let lostStates: DoneState[] = []
|
export let lostStates: DoneState[] = []
|
||||||
@ -86,12 +86,8 @@
|
|||||||
|
|
||||||
await client.updateDoc(state._class, state.space, state._id, { color })
|
await client.updateDoc(state._class, state.space, state._id, { color })
|
||||||
}
|
}
|
||||||
const spaceEditor = (space as KanbanTemplateSpace)?.editor
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if spaceEditor}
|
|
||||||
<Component is={spaceEditor} props={{ template }} />
|
|
||||||
{/if}
|
|
||||||
<div class="flex-no-shrink flex-between trans-title uppercase">
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
<Label label={task.string.ActiveStates} />
|
<Label label={task.string.ActiveStates} />
|
||||||
<CircleButton
|
<CircleButton
|
||||||
@ -102,15 +98,15 @@
|
|||||||
task.component.CreateStatePopup,
|
task.component.CreateStatePopup,
|
||||||
{
|
{
|
||||||
space,
|
space,
|
||||||
template,
|
ofAttribute,
|
||||||
_class: template !== undefined ? task.class.StateTemplate : task.class.State
|
_class: task.class.State
|
||||||
},
|
},
|
||||||
undefined
|
undefined
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-col mt-3">
|
<div class="flex-col flex-no-shrink mt-3">
|
||||||
{#each states as state, i}
|
{#each states as state, i}
|
||||||
{@const color = getPlatformColorDef(state.color ?? getColorNumberByText(state.name), $themeStore.dark)}
|
{@const color = getPlatformColorDef(state.color ?? getColorNumberByText(state.name), $themeStore.dark)}
|
||||||
{#if state}
|
{#if state}
|
||||||
@ -155,7 +151,7 @@
|
|||||||
onDelete: () => dispatch('delete', { state }),
|
onDelete: () => dispatch('delete', { state }),
|
||||||
showDelete: states.length > 1,
|
showDelete: states.length > 1,
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
showPopup(task.component.CreateStatePopup, { status: state, template }, undefined)
|
showPopup(task.component.CreateStatePopup, { status: state, space, ofAttribute }, undefined)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
eventToHTMLElement(ev),
|
eventToHTMLElement(ev),
|
||||||
@ -169,7 +165,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-col mt-9">
|
<div class="flex-col flex-no-shrink mt-9">
|
||||||
<div class="flex-no-shrink flex-between trans-title uppercase">
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
<Label label={task.string.DoneStatesWon} />
|
<Label label={task.string.DoneStatesWon} />
|
||||||
<CircleButton
|
<CircleButton
|
||||||
@ -180,8 +176,8 @@
|
|||||||
task.component.CreateStatePopup,
|
task.component.CreateStatePopup,
|
||||||
{
|
{
|
||||||
space,
|
space,
|
||||||
template,
|
ofAttribute: doneOfAttribute,
|
||||||
_class: template !== undefined ? task.class.WonStateTemplate : task.class.WonState
|
_class: task.class.WonState
|
||||||
},
|
},
|
||||||
undefined
|
undefined
|
||||||
)
|
)
|
||||||
@ -215,7 +211,11 @@
|
|||||||
onDelete: () => dispatch('delete', { state }),
|
onDelete: () => dispatch('delete', { state }),
|
||||||
showDelete: wonStates.length > 1,
|
showDelete: wonStates.length > 1,
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
showPopup(task.component.CreateStatePopup, { status: state, template }, undefined)
|
showPopup(
|
||||||
|
task.component.CreateStatePopup,
|
||||||
|
{ status: state, space, ofAttribute: doneOfAttribute },
|
||||||
|
undefined
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
eventToHTMLElement(ev),
|
eventToHTMLElement(ev),
|
||||||
@ -230,7 +230,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-9">
|
<div class="mt-9 flex-no-shrink">
|
||||||
<div class="flex-no-shrink flex-between trans-title uppercase">
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
<Label label={task.string.DoneStatesLost} />
|
<Label label={task.string.DoneStatesLost} />
|
||||||
<CircleButton
|
<CircleButton
|
||||||
@ -241,8 +241,8 @@
|
|||||||
task.component.CreateStatePopup,
|
task.component.CreateStatePopup,
|
||||||
{
|
{
|
||||||
space,
|
space,
|
||||||
template,
|
ofAttribute: doneOfAttribute,
|
||||||
_class: template !== undefined ? task.class.LostStateTemplate : task.class.LostState
|
_class: task.class.LostState
|
||||||
},
|
},
|
||||||
undefined
|
undefined
|
||||||
)
|
)
|
||||||
@ -276,7 +276,11 @@
|
|||||||
onDelete: () => dispatch('delete', { state }),
|
onDelete: () => dispatch('delete', { state }),
|
||||||
showDelete: lostStates.length > 1,
|
showDelete: lostStates.length > 1,
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
showPopup(task.component.CreateStatePopup, { status: state, template }, undefined)
|
showPopup(
|
||||||
|
task.component.CreateStatePopup,
|
||||||
|
{ status: state, space, ofAttribute: doneOfAttribute },
|
||||||
|
undefined
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
eventToHTMLElement(ev),
|
eventToHTMLElement(ev),
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
|
||||||
const elements: HTMLElement[] = []
|
const elements: HTMLElement[] = []
|
||||||
let selected: number | undefined
|
let selected: number | undefined
|
||||||
@ -95,7 +96,11 @@
|
|||||||
const spaceEditor = space.editor
|
const spaceEditor = space.editor
|
||||||
|
|
||||||
function add (_class: Ref<Class<StateTemplate | DoneStateTemplate>>) {
|
function add (_class: Ref<Class<StateTemplate | DoneStateTemplate>>) {
|
||||||
|
const ofAttribute = hierarchy.isDerived(_class, task.class.DoneStateTemplate)
|
||||||
|
? space.doneAttribute
|
||||||
|
: space.ofAttribute
|
||||||
showPopup(task.component.CreateStateTemplatePopup, {
|
showPopup(task.component.CreateStateTemplatePopup, {
|
||||||
|
ofAttribute,
|
||||||
space,
|
space,
|
||||||
template,
|
template,
|
||||||
_class
|
_class
|
||||||
@ -103,7 +108,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function edit (status: StateTemplate) {
|
function edit (status: StateTemplate) {
|
||||||
showPopup(task.component.CreateStateTemplatePopup, { status, template, space })
|
const ofAttribute = hierarchy.isDerived(status._class, task.class.DoneStateTemplate)
|
||||||
|
? space.doneAttribute
|
||||||
|
: space.ofAttribute
|
||||||
|
showPopup(task.component.CreateStateTemplatePopup, { status, template, space, ofAttribute })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -14,38 +14,50 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import { Attribute, Ref, Status } from '@hcengineering/core'
|
||||||
import { Resources } from '@hcengineering/platform'
|
import { Resources } from '@hcengineering/platform'
|
||||||
import { SpaceWithStates } from '@hcengineering/task'
|
import { SpaceWithStates } from '@hcengineering/task'
|
||||||
import { showPopup } from '@hcengineering/ui'
|
import { showPopup } from '@hcengineering/ui'
|
||||||
import AssignedTasks from './components/AssignedTasks.svelte'
|
import AssignedTasks from './components/AssignedTasks.svelte'
|
||||||
|
import CreateStatePopup from './components/CreateStatePopup.svelte'
|
||||||
|
import CreateStateTemplatePopup from './components/CreateStateTemplatePopup.svelte'
|
||||||
|
import Dashboard from './components/Dashboard.svelte'
|
||||||
|
import DueDateEditor from './components/DueDateEditor.svelte'
|
||||||
|
import KanbanTemplatePresenter from './components/KanbanTemplatePresenter.svelte'
|
||||||
|
import StatusTableView from './components/StatusTableView.svelte'
|
||||||
|
import TaskHeader from './components/TaskHeader.svelte'
|
||||||
|
import TaskPresenter from './components/TaskPresenter.svelte'
|
||||||
import KanbanTemplateEditor from './components/kanban/KanbanTemplateEditor.svelte'
|
import KanbanTemplateEditor from './components/kanban/KanbanTemplateEditor.svelte'
|
||||||
import KanbanTemplateSelector from './components/kanban/KanbanTemplateSelector.svelte'
|
import KanbanTemplateSelector from './components/kanban/KanbanTemplateSelector.svelte'
|
||||||
import KanbanView from './components/kanban/KanbanView.svelte'
|
import KanbanView from './components/kanban/KanbanView.svelte'
|
||||||
import DoneStateEditor from './components/state/DoneStateEditor.svelte'
|
import DoneStateEditor from './components/state/DoneStateEditor.svelte'
|
||||||
import DoneStatePresenter from './components/state/DoneStatePresenter.svelte'
|
import DoneStatePresenter from './components/state/DoneStatePresenter.svelte'
|
||||||
|
import DoneStateRefPresenter from './components/state/DoneStateRefPresenter.svelte'
|
||||||
import EditStatuses from './components/state/EditStatuses.svelte'
|
import EditStatuses from './components/state/EditStatuses.svelte'
|
||||||
import StateEditor from './components/state/StateEditor.svelte'
|
import StateEditor from './components/state/StateEditor.svelte'
|
||||||
import StatePresenter from './components/state/StatePresenter.svelte'
|
import StatePresenter from './components/state/StatePresenter.svelte'
|
||||||
import StatusTableView from './components/StatusTableView.svelte'
|
import StateRefPresenter from './components/state/StateRefPresenter.svelte'
|
||||||
import TaskHeader from './components/TaskHeader.svelte'
|
|
||||||
import TaskPresenter from './components/TaskPresenter.svelte'
|
|
||||||
import KanbanTemplatePresenter from './components/KanbanTemplatePresenter.svelte'
|
|
||||||
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
|
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
|
||||||
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
|
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
|
||||||
import Todos from './components/todos/Todos.svelte'
|
|
||||||
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
|
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
|
||||||
import Dashboard from './components/Dashboard.svelte'
|
import Todos from './components/todos/Todos.svelte'
|
||||||
import DoneStateRefPresenter from './components/state/DoneStateRefPresenter.svelte'
|
|
||||||
import StateRefPresenter from './components/state/StateRefPresenter.svelte'
|
|
||||||
import DueDateEditor from './components/DueDateEditor.svelte'
|
|
||||||
import CreateStatePopup from './components/CreateStatePopup.svelte'
|
|
||||||
import CreateStateTemplatePopup from './components/CreateStateTemplatePopup.svelte'
|
|
||||||
|
|
||||||
export { default as AssigneePresenter } from './components/AssigneePresenter.svelte'
|
export { default as AssigneePresenter } from './components/AssigneePresenter.svelte'
|
||||||
export { StateRefPresenter }
|
export { StateRefPresenter }
|
||||||
|
|
||||||
async function editStatuses (object: SpaceWithStates): Promise<void> {
|
async function editStatuses (
|
||||||
showPopup(EditStatuses, { _id: object._id, spaceClass: object._class }, 'float')
|
object: SpaceWithStates,
|
||||||
|
ev: Event,
|
||||||
|
props: {
|
||||||
|
ofAttribute: Ref<Attribute<Status>>
|
||||||
|
doneOfAttribute: Ref<Attribute<Status>>
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
showPopup(
|
||||||
|
EditStatuses,
|
||||||
|
{ _id: object._id, ofAttribute: props.ofAttribute, doneOfAttribute: props.doneOfAttribute },
|
||||||
|
'float'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StatesBarPosition = 'start' | 'middle' | 'end' | undefined
|
export type StatesBarPosition = 'start' | 'middle' | 'end' | undefined
|
||||||
|
@ -158,6 +158,8 @@ export interface KanbanTemplateSpace extends Space {
|
|||||||
name: IntlString
|
name: IntlString
|
||||||
description: IntlString
|
description: IntlString
|
||||||
icon: AnyComponent
|
icon: AnyComponent
|
||||||
|
ofAttribute: Ref<Attribute<State>>
|
||||||
|
doneAttribute?: Ref<Attribute<DoneState>>
|
||||||
editor?: AnyComponent
|
editor?: AnyComponent
|
||||||
attachedToClass: Ref<Class<Doc>>
|
attachedToClass: Ref<Class<Doc>>
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,17 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { Class, Data, DocumentQuery, IdMap, Ref, SortingOrder, Status, TxOperations } from '@hcengineering/core'
|
import {
|
||||||
|
Attribute,
|
||||||
|
Class,
|
||||||
|
Data,
|
||||||
|
DocumentQuery,
|
||||||
|
IdMap,
|
||||||
|
Ref,
|
||||||
|
SortingOrder,
|
||||||
|
Status,
|
||||||
|
TxOperations
|
||||||
|
} from '@hcengineering/core'
|
||||||
import { LexoDecimal, LexoNumeralSystem36, LexoRank } from 'lexorank'
|
import { LexoDecimal, LexoNumeralSystem36, LexoRank } from 'lexorank'
|
||||||
import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket'
|
import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket'
|
||||||
import task, { DoneState, DoneStateTemplate, KanbanTemplate, SpaceWithStates, State } from '.'
|
import task, { DoneState, DoneStateTemplate, KanbanTemplate, SpaceWithStates, State } from '.'
|
||||||
@ -86,11 +96,13 @@ export async function createState<T extends Status> (
|
|||||||
*/
|
*/
|
||||||
export async function createStates (
|
export async function createStates (
|
||||||
client: TxOperations,
|
client: TxOperations,
|
||||||
|
ofAttribute: Ref<Attribute<Status>>,
|
||||||
|
doneAtrtribute?: Ref<Attribute<DoneState>>,
|
||||||
templateId?: Ref<KanbanTemplate>
|
templateId?: Ref<KanbanTemplate>
|
||||||
): Promise<[Ref<Status>[], Ref<DoneState>[]]> {
|
): Promise<[Ref<Status>[], Ref<DoneState>[]]> {
|
||||||
if (templateId === undefined) {
|
if (templateId === undefined) {
|
||||||
const state = await createState(client, task.class.State, {
|
const state = await createState(client, task.class.State, {
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
name: 'New State',
|
name: 'New State',
|
||||||
color: 9
|
color: 9
|
||||||
})
|
})
|
||||||
@ -99,13 +111,13 @@ export async function createStates (
|
|||||||
|
|
||||||
doneStates.push(
|
doneStates.push(
|
||||||
await createState(client, task.class.WonState, {
|
await createState(client, task.class.WonState, {
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute: doneAtrtribute ?? ofAttribute,
|
||||||
name: 'Won'
|
name: 'Won'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
doneStates.push(
|
doneStates.push(
|
||||||
await createState(client, task.class.LostState, {
|
await createState(client, task.class.LostState, {
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute: doneAtrtribute ?? ofAttribute,
|
||||||
name: 'Lost'
|
name: 'Lost'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -131,7 +143,7 @@ export async function createStates (
|
|||||||
for (const state of tmplStates) {
|
for (const state of tmplStates) {
|
||||||
states.push(
|
states.push(
|
||||||
await createState(client, task.class.State, {
|
await createState(client, task.class.State, {
|
||||||
ofAttribute: task.attribute.State,
|
ofAttribute,
|
||||||
color: state.color,
|
color: state.color,
|
||||||
description: state.description,
|
description: state.description,
|
||||||
name: state.name
|
name: state.name
|
||||||
@ -157,7 +169,7 @@ export async function createStates (
|
|||||||
|
|
||||||
doneStates.push(
|
doneStates.push(
|
||||||
await createState(client, cl, {
|
await createState(client, cl, {
|
||||||
ofAttribute: task.attribute.DoneState,
|
ofAttribute: doneAtrtribute ?? ofAttribute,
|
||||||
description: state.description,
|
description: state.description,
|
||||||
name: state.name
|
name: state.name
|
||||||
})
|
})
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15Z"
|
d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15Z"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if statusIcon.count && statusIcon.index}
|
{#if statusIcon.count && statusIcon.index}
|
||||||
<path
|
<path
|
||||||
d="M 4.5 4.5 L 9 4.5 A 4.5 4.5 0 {statusIcon.index > (statusIcon.count - 1) / 2 ? 1 : 0} 1 {Math.cos(
|
d="M 4.5 4.5 L 9 4.5 A 4.5 4.5 0 {statusIcon.index > (statusIcon.count - 1) / 2 ? 1 : 0} 1 {Math.cos(
|
||||||
@ -66,7 +65,11 @@
|
|||||||
transform="translate(3.5,3.5)"
|
transform="translate(3.5,3.5)"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<circle cx="8" cy="8" r="4" fill="var(--theme-error-color)" opacity=".15" />
|
<path
|
||||||
|
d="M 4.5 4.5 L 9 4.5 A 4.5 4.5 0 1 1 {Math.cos(Math.PI - 0.01) * 4.5 + 4.5} {Math.sin(Math.PI - 0.01) * 4.5 +
|
||||||
|
4.5} Z"
|
||||||
|
transform="translate(3.5,3.5)"
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if category._id === tracker.issueStatusCategory.Completed}
|
{:else if category._id === tracker.issueStatusCategory.Completed}
|
||||||
<path
|
<path
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
statuses = getStates(_space, $statusStore).filter((p) => p.category === tracker.issueStatusCategory.Started)
|
statuses = getStates(_space, $statusStore).filter((p) => p.category === tracker.issueStatusCategory.Started)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateCategory (status: WithLookup<IssueStatus>, statuses: IssueStatus[]) {
|
async function updateCategory (_space: Project | undefined, status: WithLookup<IssueStatus>, statuses: IssueStatus[]) {
|
||||||
if (status.$lookup?.category) {
|
if (status.$lookup?.category) {
|
||||||
category = status.$lookup.category
|
category = status.$lookup.category
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: updateCategory(value, statuses)
|
$: updateCategory(_space, value, statuses)
|
||||||
$: icon = category?.icon
|
$: icon = category?.icon
|
||||||
$: color = value.color !== undefined ? value.color : category !== undefined ? category.color : -1
|
$: color = value.color !== undefined ? value.color : category !== undefined ? category.color : -1
|
||||||
</script>
|
</script>
|
||||||
|
@ -117,7 +117,7 @@
|
|||||||
return {
|
return {
|
||||||
id: s._id,
|
id: s._id,
|
||||||
component: StatusPresenter,
|
component: StatusPresenter,
|
||||||
props: { value: s, size: 'small' },
|
props: { value: s, size: 'small', space: value.space },
|
||||||
isSelected: selectedStatus?._id === s._id ?? false
|
isSelected: selectedStatus?._id === s._id ?? false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-presenter flex-gap-1-5">
|
<div class="flex-presenter flex-gap-1-5">
|
||||||
{#each statuses as value, i}
|
{#each statuses as value, i (value._id)}
|
||||||
{#if value && i < 5}
|
{#if value && i < 5}
|
||||||
<div>
|
<div>
|
||||||
<IssueStatusIcon {space} {value} size={'small'} />
|
<IssueStatusIcon {space} {value} size={'small'} />
|
||||||
|
@ -13,27 +13,27 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { Doc, FindResult, IdMap, Ref, RefTo, Space, Status } from '@hcengineering/core'
|
import core, { Doc, FindResult, IdMap, Ref, RefTo, Space, Status, toIdMap } from '@hcengineering/core'
|
||||||
import { translate } from '@hcengineering/platform'
|
import { translate } from '@hcengineering/platform'
|
||||||
import presentation, { createQuery, getClient } from '@hcengineering/presentation'
|
import presentation, { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import task, { SpaceWithStates } from '@hcengineering/task'
|
import task, { SpaceWithStates } from '@hcengineering/task'
|
||||||
import ui, {
|
import ui, {
|
||||||
addNotification,
|
|
||||||
deviceOptionsStore,
|
|
||||||
EditWithIcon,
|
EditWithIcon,
|
||||||
Icon,
|
Icon,
|
||||||
IconCheck,
|
IconCheck,
|
||||||
IconSearch,
|
IconSearch,
|
||||||
Label,
|
Label,
|
||||||
Loading,
|
Loading,
|
||||||
|
addNotification,
|
||||||
|
deviceOptionsStore,
|
||||||
resizeObserver,
|
resizeObserver,
|
||||||
themeStore
|
themeStore
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { Filter } from '@hcengineering/view'
|
import { Filter } from '@hcengineering/view'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { buildConfigLookup, getPresenter } from '../../utils'
|
|
||||||
import view from '../../plugin'
|
|
||||||
import { FILTER_DEBOUNCE_MS, FilterRemovedNotification, sortFilterValues, statusStore } from '../..'
|
import { FILTER_DEBOUNCE_MS, FilterRemovedNotification, sortFilterValues, statusStore } from '../..'
|
||||||
|
import view from '../../plugin'
|
||||||
|
import { buildConfigLookup, getPresenter } from '../../utils'
|
||||||
|
|
||||||
export let filter: Filter
|
export let filter: Filter
|
||||||
export let space: Ref<Space> | undefined = undefined
|
export let space: Ref<Space> | undefined = undefined
|
||||||
@ -76,11 +76,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (space !== undefined) {
|
if (space !== undefined) {
|
||||||
const _space = await client.findOne(core.class.Space, { _id: space })
|
const _space = await client.findOne(task.class.SpaceWithStates, { _id: space as Ref<SpaceWithStates> })
|
||||||
if (_space) {
|
if (_space) {
|
||||||
values = (_space as any)[filter.key.key]
|
const targetClass = (filter.key.attribute.type as RefTo<Status>).to
|
||||||
.map((p: Ref<Status>) => statusStore.get(p))
|
const key = hierarchy.isDerived(targetClass, task.class.DoneState) ? 'doneStates' : 'states'
|
||||||
.filter((p: Status) => p !== undefined)
|
values = (_space as any)[key].map((p: Ref<Status>) => statusStore.get(p)).filter((p: Status) => p !== undefined)
|
||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
targets.add(value?._id)
|
targets.add(value?._id)
|
||||||
}
|
}
|
||||||
@ -89,13 +89,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
values = []
|
const statuses: Status[] = []
|
||||||
for (const status of statusStore.values()) {
|
for (const status of statusStore.values()) {
|
||||||
if (hierarchy.isDerived(status._class, targetClass)) {
|
if (hierarchy.isDerived(status._class, targetClass) && status.ofAttribute === filter.key.attribute._id) {
|
||||||
values.push(status)
|
statuses.push(status)
|
||||||
targets.add(status._id)
|
targets.add(status._id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
values = await sort(statuses)
|
||||||
}
|
}
|
||||||
if (targets.has(undefined)) {
|
if (targets.has(undefined)) {
|
||||||
values.unshift(undefined)
|
values.unshift(undefined)
|
||||||
@ -120,6 +121,26 @@
|
|||||||
objectsPromise = undefined
|
objectsPromise = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sort (statuses: Status[]): Promise<Status[]> {
|
||||||
|
const categories = toIdMap(await client.findAll(core.class.StatusCategory, {}))
|
||||||
|
statuses.sort((a, b) => {
|
||||||
|
if (a.category !== undefined && b.category !== undefined && a.category !== b.category) {
|
||||||
|
const aCat = categories.get(a.category)
|
||||||
|
const bCat = categories.get(b.category)
|
||||||
|
if (aCat !== undefined && bCat !== undefined) {
|
||||||
|
return aCat.order - bCat.order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_space != null) {
|
||||||
|
const aIndex = _space.states.findIndex((s) => s === a._id)
|
||||||
|
const bIndex = _space.states.findIndex((s) => s === b._id)
|
||||||
|
return aIndex - bIndex
|
||||||
|
}
|
||||||
|
return a.name.localeCompare(b.name)
|
||||||
|
})
|
||||||
|
return statuses
|
||||||
|
}
|
||||||
|
|
||||||
function isSelected (value: Doc | undefined | null, values: any[]): boolean {
|
function isSelected (value: Doc | undefined | null, values: any[]): boolean {
|
||||||
return values.includes(value?._id ?? value)
|
return values.includes(value?._id ?? value)
|
||||||
}
|
}
|
||||||
@ -182,7 +203,14 @@
|
|||||||
<div class="flex-row-center">
|
<div class="flex-row-center">
|
||||||
{#if value}
|
{#if value}
|
||||||
{#key value._id}
|
{#key value._id}
|
||||||
<svelte:component this={attribute.presenter} {value} {...attribute.props} disabled oneLine />
|
<svelte:component
|
||||||
|
this={attribute.presenter}
|
||||||
|
{value}
|
||||||
|
{...attribute.props}
|
||||||
|
{space}
|
||||||
|
disabled
|
||||||
|
oneLine
|
||||||
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
{:else}
|
{:else}
|
||||||
<Label label={ui.string.NotSelected} />
|
<Label label={ui.string.NotSelected} />
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
<SearchEdit bind:value={search} on:change={() => dispatch('search', search)} />
|
<SearchEdit bind:value={search} on:change={() => dispatch('search', search)} />
|
||||||
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
||||||
<div class="buttons-divider" />
|
<div class="buttons-divider" />
|
||||||
<FilterButton {_class} />
|
<FilterButton {_class} space={spaceId} />
|
||||||
</div>
|
</div>
|
||||||
<div class="ac-header-full medium-gap">
|
<div class="ac-header-full medium-gap">
|
||||||
<ViewletSettingButton bind:viewOptions bind:viewlet />
|
<ViewletSettingButton bind:viewOptions bind:viewlet />
|
||||||
|
Loading…
Reference in New Issue
Block a user