mirror of
https://github.com/hcengineering/platform.git
synced 2025-01-03 00:43:59 +03:00
States fix (#3690)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
2df68a46b1
commit
8b1a488725
@ -41,7 +41,7 @@ import workbench, { Application } from '@hcengineering/model-workbench'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import type { AnyComponent } from '@hcengineering/ui'
|
||||
import board from './plugin'
|
||||
import { State } from '@hcengineering/task'
|
||||
import { DoneState, State } from '@hcengineering/task'
|
||||
|
||||
export { boardId } from '@hcengineering/board'
|
||||
export { boardOperation } from './migration'
|
||||
@ -103,6 +103,9 @@ export class TCard extends TTask implements Card {
|
||||
|
||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: board.attribute.State })
|
||||
declare status: Ref<State>
|
||||
|
||||
@Prop(TypeRef(task.class.DoneState), task.string.TaskStateDone, { _id: board.attribute.DoneState })
|
||||
declare doneState: Ref<DoneState>
|
||||
}
|
||||
|
||||
@Model(board.class.MenuPage, core.class.Doc, DOMAIN_MODEL)
|
||||
|
@ -42,7 +42,7 @@ import view, { createAction, actionTemplates as viewTemplates } from '@hcenginee
|
||||
import workbench from '@hcengineering/model-workbench'
|
||||
import notification from '@hcengineering/notification'
|
||||
import setting from '@hcengineering/setting'
|
||||
import { State } from '@hcengineering/task'
|
||||
import { DoneState, State } from '@hcengineering/task'
|
||||
import { ViewOptionsModel } from '@hcengineering/view'
|
||||
import lead from './plugin'
|
||||
|
||||
@ -84,6 +84,9 @@ export class TLead extends TTask implements Lead {
|
||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: lead.attribute.State })
|
||||
declare status: Ref<State>
|
||||
|
||||
@Prop(TypeRef(task.class.DoneState), task.string.TaskStateDone, { _id: lead.attribute.DoneState })
|
||||
declare doneState: Ref<DoneState>
|
||||
|
||||
declare space: Ref<Funnel>
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ import {
|
||||
recruitId
|
||||
} from '@hcengineering/recruit'
|
||||
import setting from '@hcengineering/setting'
|
||||
import { State } from '@hcengineering/task'
|
||||
import { DoneState, State } from '@hcengineering/task'
|
||||
import { KeyBinding, ViewOptionsModel } from '@hcengineering/view'
|
||||
import recruit from './plugin'
|
||||
import { createReviewModel, reviewTableConfig, reviewTableOptions } from './review'
|
||||
@ -167,6 +167,9 @@ export class TApplicant extends TTask implements Applicant {
|
||||
|
||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: recruit.attribute.State })
|
||||
declare status: Ref<State>
|
||||
|
||||
@Prop(TypeRef(task.class.DoneState), task.string.TaskStateDone, { _id: recruit.attribute.DoneState })
|
||||
declare doneState: Ref<DoneState>
|
||||
}
|
||||
|
||||
@Model(recruit.class.ApplicantMatch, core.class.AttachedDoc, DOMAIN_TASK)
|
||||
@ -1196,23 +1199,17 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
createAction(builder, {
|
||||
action: view.actionImpl.ValueSelector,
|
||||
actionPopup: view.component.ValueSelector,
|
||||
action: task.actionImpl.SelectStatus,
|
||||
actionPopup: task.component.StatusSelector,
|
||||
actionProps: {
|
||||
attribute: 'status',
|
||||
_class: task.class.State,
|
||||
query: {},
|
||||
searchField: 'name',
|
||||
// should match space
|
||||
fillQuery: { space: 'space' },
|
||||
// Only apply for same vacancy
|
||||
docMatches: ['space'],
|
||||
ofAttribute: recruit.attribute.State,
|
||||
placeholder: task.string.TaskState
|
||||
},
|
||||
label: task.string.TaskState,
|
||||
icon: task.icon.TaskState,
|
||||
keyBinding: [],
|
||||
input: 'none',
|
||||
keyBinding: ['keyS->keyS'],
|
||||
input: 'any',
|
||||
category: recruit.category.Recruit,
|
||||
target: recruit.class.Applicant,
|
||||
context: {
|
||||
@ -1221,24 +1218,19 @@ export function createModel (builder: Builder): void {
|
||||
group: 'edit'
|
||||
}
|
||||
})
|
||||
|
||||
createAction(builder, {
|
||||
action: view.actionImpl.ValueSelector,
|
||||
actionPopup: view.component.ValueSelector,
|
||||
action: task.actionImpl.SelectStatus,
|
||||
actionPopup: task.component.StatusSelector,
|
||||
actionProps: {
|
||||
attribute: 'doneState',
|
||||
_class: task.class.DoneState,
|
||||
query: {},
|
||||
searchField: 'name',
|
||||
// should match space
|
||||
fillQuery: { space: 'space' },
|
||||
// Only apply for same vacancy
|
||||
docMatches: ['space'],
|
||||
ofAttribute: recruit.attribute.DoneState,
|
||||
placeholder: task.string.DoneState
|
||||
},
|
||||
label: task.string.DoneState,
|
||||
icon: task.icon.TaskState,
|
||||
keyBinding: [],
|
||||
input: 'none',
|
||||
keyBinding: ['keyS->keyD'],
|
||||
input: 'any',
|
||||
category: recruit.category.Recruit,
|
||||
target: recruit.class.Applicant,
|
||||
context: {
|
||||
@ -1247,6 +1239,7 @@ export function createModel (builder: Builder): void {
|
||||
group: 'edit'
|
||||
}
|
||||
})
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
|
@ -240,21 +240,21 @@ async function fixStatusAttributes (client: MigrationClient): Promise<void> {
|
||||
const space = map.get(oldStatus.space)
|
||||
if (space !== undefined) {
|
||||
try {
|
||||
const isDone = oldStatus._class === task.class.DoneState
|
||||
const isDone = client.hierarchy.isDerived(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: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: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:DoneState' as Ref<Attribute<State>>)
|
||||
: ('board:attribute:State' as Ref<Attribute<State>>)
|
||||
}
|
||||
if (space._class === ('tracker:class:Project' as Ref<Class<Space>>)) {
|
||||
|
@ -34,7 +34,8 @@ export default mergeIds(taskId, task, {
|
||||
TodoItemMarkDone: '' as ViewAction,
|
||||
TodoItemMarkUnDone: '' as ViewAction,
|
||||
ArchiveSpace: '' as ViewAction,
|
||||
UnarchiveSpace: '' as ViewAction
|
||||
UnarchiveSpace: '' as ViewAction,
|
||||
SelectStatus: '' as ViewAction
|
||||
},
|
||||
category: {
|
||||
Task: '' as Ref<ActionCategory>,
|
||||
@ -57,7 +58,8 @@ export default mergeIds(taskId, task, {
|
||||
TaskHeader: '' as AnyComponent,
|
||||
Dashboard: '' as AnyComponent,
|
||||
StateRefPresenter: '' as AnyComponent,
|
||||
DoneStateRefPresenter: '' as AnyComponent
|
||||
DoneStateRefPresenter: '' as AnyComponent,
|
||||
StatusSelector: '' as AnyComponent
|
||||
},
|
||||
space: {
|
||||
TasksPublic: '' as Ref<Space>
|
||||
|
@ -1541,8 +1541,13 @@ export function createModel (builder: Builder): void {
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: tracker.actionImpl.SelectStatus,
|
||||
actionPopup: tracker.component.StatusSelector,
|
||||
action: task.actionImpl.SelectStatus,
|
||||
actionPopup: task.component.StatusSelector,
|
||||
actionProps: {
|
||||
_class: tracker.class.IssueStatus,
|
||||
ofAttribute: tracker.attribute.IssueStatus,
|
||||
placeholder: tracker.string.Status
|
||||
},
|
||||
label: tracker.string.Status,
|
||||
icon: tracker.icon.CategoryBacklog,
|
||||
keyBinding: ['keyS->keyS'],
|
||||
|
@ -54,8 +54,7 @@ export default mergeIds(trackerId, tracker, {
|
||||
IssueStatistics: '' as AnyComponent,
|
||||
TimeSpendReportPopup: '' as AnyComponent,
|
||||
NotificationIssuePresenter: '' as AnyComponent,
|
||||
MilestoneFilter: '' as AnyComponent,
|
||||
StatusSelector: '' as AnyComponent
|
||||
MilestoneFilter: '' as AnyComponent
|
||||
},
|
||||
app: {
|
||||
Tracker: '' as Ref<Application>
|
||||
@ -78,7 +77,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
IssueCategory: '' as Ref<ObjectSearchCategory>
|
||||
},
|
||||
actionImpl: {
|
||||
SelectStatus: '' as ViewAction,
|
||||
Move: '' as ViewAction,
|
||||
CopyToClipboard: '' as ViewAction,
|
||||
EditWorkflowStatuses: '' as ViewAction,
|
||||
|
@ -1,24 +1,29 @@
|
||||
<script lang="ts">
|
||||
import core, { DocumentQuery, FindOptions, SortingOrder } from '@hcengineering/core'
|
||||
import core, { Attribute, Class, DocumentQuery, FindOptions, Ref, SortingOrder, Status } from '@hcengineering/core'
|
||||
import { ObjectPopup, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Issue, IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import { Label, resizeObserver } from '@hcengineering/ui'
|
||||
import { ObjectPresenter } from '@hcengineering/view-resources'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import task from '../plugin'
|
||||
import { SpaceWithStates, Task } from '@hcengineering/task'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
|
||||
export let value: Issue | Issue[]
|
||||
const queryOptions: FindOptions<IssueStatus> = {
|
||||
export let value: Task | Task[]
|
||||
export let placeholder: IntlString
|
||||
export let ofAttribute: Ref<Attribute<Status>>
|
||||
export let _class: Ref<Class<Status>>
|
||||
|
||||
const queryOptions: FindOptions<Status> = {
|
||||
lookup: {
|
||||
category: core.class.StatusCategory
|
||||
},
|
||||
sort: { category: SortingOrder.Ascending, name: SortingOrder.Ascending }
|
||||
}
|
||||
const placeholder = tracker.string.SetStatus
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
const h = client.getHierarchy()
|
||||
const changeStatus = async (newStatus: any) => {
|
||||
if (newStatus === undefined) {
|
||||
dispatch('close', undefined)
|
||||
@ -26,10 +31,11 @@
|
||||
}
|
||||
const docs = Array.isArray(value) ? value : [value]
|
||||
|
||||
const changed = (d: Issue) => d.status !== newStatus
|
||||
const changed = (d: Task) => d.status !== newStatus
|
||||
const field = h.isDerived(_class, task.class.DoneState) ? 'doneState' : 'status'
|
||||
await Promise.all(
|
||||
docs.filter(changed).map((it) => {
|
||||
return client.update(it, { status: newStatus })
|
||||
return client.update(it, { [field]: newStatus })
|
||||
})
|
||||
)
|
||||
|
||||
@ -37,31 +43,36 @@
|
||||
}
|
||||
|
||||
$: current = Array.isArray(value)
|
||||
? value.every((v) => v.status === (value as Array<Issue>)[0].status)
|
||||
? (value as Array<Issue>)[0].status
|
||||
? value.every((v) => v.status === (value as Array<Task>)[0].status)
|
||||
? (value as Array<Task>)[0].status
|
||||
: undefined
|
||||
: value.status
|
||||
|
||||
let finalQuery: DocumentQuery<IssueStatus> = {}
|
||||
let finalQuery: DocumentQuery<Status> = {}
|
||||
|
||||
let docMatch = true
|
||||
|
||||
$: _space = Array.isArray(value)
|
||||
? value.every((v) => v.space === (value as Array<Issue>)[0].space)
|
||||
? (value as Array<Issue>)[0].space
|
||||
? value.every((v) => v.space === (value as Array<Task>)[0].space)
|
||||
? (value as Array<Task>)[0].space
|
||||
: undefined
|
||||
: value.space
|
||||
|
||||
let project: Project | undefined
|
||||
let project: SpaceWithStates | undefined
|
||||
|
||||
const query = createQuery()
|
||||
$: _space ? query.query(tracker.class.Project, { _id: _space }, (res) => (project = res[0])) : (project = undefined)
|
||||
$: _space
|
||||
? query.query(task.class.SpaceWithStates, { _id: _space as Ref<SpaceWithStates> }, (res) => (project = res[0]))
|
||||
: (project = undefined)
|
||||
|
||||
function updateQuery (space: Project | undefined): void {
|
||||
function updateQuery (space: SpaceWithStates | undefined): void {
|
||||
if (space === undefined) {
|
||||
finalQuery = { ofAttribute: tracker.attribute.IssueStatus }
|
||||
finalQuery = { ofAttribute }
|
||||
} else {
|
||||
finalQuery = { ofAttribute: tracker.attribute.IssueStatus, _id: { $in: space.states } }
|
||||
finalQuery = {
|
||||
ofAttribute,
|
||||
_id: { $in: !h.isDerived(_class, task.class.DoneState) ? space.states : space?.doneStates }
|
||||
}
|
||||
}
|
||||
docMatch = true
|
||||
}
|
||||
@ -71,7 +82,7 @@
|
||||
|
||||
{#if docMatch}
|
||||
<ObjectPopup
|
||||
_class={tracker.class.IssueStatus}
|
||||
{_class}
|
||||
docQuery={finalQuery}
|
||||
options={queryOptions}
|
||||
allowDeselect={true}
|
@ -14,9 +14,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Attribute, Ref, Status } from '@hcengineering/core'
|
||||
import { Resources } from '@hcengineering/platform'
|
||||
import { SpaceWithStates } from '@hcengineering/task'
|
||||
import { Attribute, Class, Ref, Status } from '@hcengineering/core'
|
||||
import { IntlString, Resources } from '@hcengineering/platform'
|
||||
import { SpaceWithStates, Task } from '@hcengineering/task'
|
||||
import { showPopup } from '@hcengineering/ui'
|
||||
import AssignedTasks from './components/AssignedTasks.svelte'
|
||||
import CreateStatePopup from './components/CreateStatePopup.svelte'
|
||||
@ -41,6 +41,7 @@ import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
|
||||
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
|
||||
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
|
||||
import Todos from './components/todos/Todos.svelte'
|
||||
import StatusSelector from './components/StatusSelector.svelte'
|
||||
|
||||
export { default as AssigneePresenter } from './components/AssigneePresenter.svelte'
|
||||
export { StateRefPresenter }
|
||||
@ -60,6 +61,22 @@ async function editStatuses (
|
||||
)
|
||||
}
|
||||
|
||||
async function selectStatus (
|
||||
doc: Task | Task[],
|
||||
ev: any,
|
||||
props: {
|
||||
ofAttribute: Ref<Attribute<Status>>
|
||||
placeholder: IntlString
|
||||
_class: Ref<Class<Status>>
|
||||
}
|
||||
): Promise<void> {
|
||||
showPopup(
|
||||
StatusSelector,
|
||||
{ value: doc, ofAttribute: props.ofAttribute, _class: props._class, placeholder: props.placeholder },
|
||||
'top'
|
||||
)
|
||||
}
|
||||
|
||||
export type StatesBarPosition = 'start' | 'middle' | 'end' | undefined
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
@ -85,9 +102,11 @@ export default async (): Promise<Resources> => ({
|
||||
TodoItemsPopup,
|
||||
DueDateEditor,
|
||||
CreateStatePopup,
|
||||
CreateStateTemplatePopup
|
||||
CreateStateTemplatePopup,
|
||||
StatusSelector
|
||||
},
|
||||
actionImpl: {
|
||||
EditStatuses: editStatuses
|
||||
EditStatuses: editStatuses,
|
||||
SelectStatus: selectStatus
|
||||
}
|
||||
})
|
||||
|
@ -75,7 +75,6 @@ import SetDueDateActionPopup from './components/SetDueDateActionPopup.svelte'
|
||||
import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte'
|
||||
import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte'
|
||||
import Statuses from './components/workflow/Statuses.svelte'
|
||||
import StatusSelector from './components/issues/StatusSelector.svelte'
|
||||
import {
|
||||
getIssueId,
|
||||
getIssueTitle,
|
||||
@ -208,10 +207,6 @@ async function move (issues: Issue | Issue[]): Promise<void> {
|
||||
showPopup(MoveIssues, { selected: issues }, 'top')
|
||||
}
|
||||
|
||||
async function selectStatus (doc: Issue | Issue[]): Promise<void> {
|
||||
showPopup(StatusSelector, { value: doc }, 'top')
|
||||
}
|
||||
|
||||
async function editWorkflowStatuses (project: Project | undefined): Promise<void> {
|
||||
if (project !== undefined) {
|
||||
showPopup(Statuses, { projectId: project._id, projectClass: project._class }, 'top')
|
||||
@ -478,8 +473,7 @@ export default async (): Promise<Resources> => ({
|
||||
PriorityFilterValuePresenter,
|
||||
StatusFilterValuePresenter,
|
||||
ProjectFilterValuePresenter,
|
||||
ComponentFilterValuePresenter,
|
||||
StatusSelector
|
||||
ComponentFilterValuePresenter
|
||||
},
|
||||
completion: {
|
||||
IssueQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) =>
|
||||
@ -502,7 +496,6 @@ export default async (): Promise<Resources> => ({
|
||||
IsProjectJoined: async (project: Project) => !project.private || project.members.includes(getCurrentAccount()._id)
|
||||
},
|
||||
actionImpl: {
|
||||
SelectStatus: selectStatus,
|
||||
Move: move,
|
||||
EditWorkflowStatuses: editWorkflowStatuses,
|
||||
EditProject: editProject,
|
||||
|
Loading…
Reference in New Issue
Block a user