mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-03 22:38:20 +00:00
728 lines
19 KiB
TypeScript
728 lines
19 KiB
TypeScript
//
|
|
// Copyright © 2023 Hardcore Engineering Inc.
|
|
//
|
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License. You may
|
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
//
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import contact from '@hcengineering/contact'
|
|
import { type Builder } from '@hcengineering/model'
|
|
import core from '@hcengineering/model-core'
|
|
import task from '@hcengineering/model-task'
|
|
import view, { actionTemplates, createAction } from '@hcengineering/model-view'
|
|
import workbench, { createNavigateAction } from '@hcengineering/model-workbench'
|
|
import { type IntlString } from '@hcengineering/platform'
|
|
import { TrackerEvents, trackerId } from '@hcengineering/tracker'
|
|
import { type KeyBinding } from '@hcengineering/view'
|
|
import tracker from './plugin'
|
|
|
|
import tags from '@hcengineering/tags'
|
|
import { defaultPriorities, issuePriorities } from '@hcengineering/tracker-resources/src/types'
|
|
|
|
function createGotoSpecialAction (
|
|
builder: Builder,
|
|
id: string,
|
|
key: KeyBinding,
|
|
label: IntlString,
|
|
query?: Record<string, string | null>
|
|
): void {
|
|
createNavigateAction(builder, key, label, tracker.app.Tracker, {
|
|
application: trackerId,
|
|
mode: 'space',
|
|
spaceSpecial: id,
|
|
spaceClass: tracker.class.Project,
|
|
query
|
|
})
|
|
}
|
|
export function createActions (builder: Builder, issuesId: string, componentsId: string, myIssuesId: string): void {
|
|
createGotoSpecialAction(builder, issuesId, 'keyG->keyE', tracker.string.GotoIssues)
|
|
createGotoSpecialAction(builder, issuesId, 'keyG->keyA', tracker.string.GotoActive, { mode: 'active' })
|
|
createGotoSpecialAction(builder, issuesId, 'keyG->keyB', tracker.string.GotoBacklog, { mode: 'backlog' })
|
|
createGotoSpecialAction(builder, componentsId, 'keyG->keyC', tracker.string.GotoComponents)
|
|
createNavigateAction(builder, 'keyG->keyM', tracker.string.GotoMyIssues, tracker.app.Tracker, {
|
|
application: trackerId,
|
|
mode: 'special',
|
|
special: myIssuesId
|
|
})
|
|
|
|
createAction(builder, {
|
|
action: workbench.actionImpl.Navigate,
|
|
actionProps: {
|
|
mode: 'app',
|
|
application: trackerId
|
|
},
|
|
label: tracker.string.GotoTrackerApplication,
|
|
icon: view.icon.ArrowRight,
|
|
input: 'none',
|
|
category: view.category.Navigation,
|
|
target: core.class.Doc,
|
|
context: {
|
|
mode: ['workbench', 'browser', 'editor', 'panel', 'popup']
|
|
}
|
|
})
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.EditWorkflowStatuses,
|
|
label: tracker.string.EditWorkflowStatuses,
|
|
icon: view.icon.Statuses,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Project,
|
|
override: [task.action.EditStatuses],
|
|
query: {},
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.EditWorkflowStatuses
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.EditProject,
|
|
label: tracker.string.EditProject,
|
|
icon: contact.icon.Edit,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Project,
|
|
visibilityTester: view.function.CanEditSpace,
|
|
query: {},
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.EditProject
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.DeleteProject,
|
|
label: workbench.string.Archive,
|
|
icon: view.icon.Archive,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Project,
|
|
visibilityTester: view.function.CanArchiveSpace,
|
|
query: {
|
|
archived: false
|
|
},
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
group: 'edit'
|
|
},
|
|
analyticsEvent: TrackerEvents.ProjectArchived,
|
|
override: [view.action.Archive, view.action.Delete]
|
|
},
|
|
tracker.action.DeleteProject
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.DeleteProject,
|
|
label: workbench.string.Delete,
|
|
icon: view.icon.Delete,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Project,
|
|
visibilityTester: view.function.CanDeleteSpace,
|
|
query: {
|
|
archived: true
|
|
},
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
group: 'edit'
|
|
},
|
|
analyticsEvent: TrackerEvents.ProjectDeleted,
|
|
override: [view.action.Archive, view.action.Delete]
|
|
},
|
|
tracker.action.DeleteProjectClean
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.DeleteIssue,
|
|
label: workbench.string.Delete,
|
|
icon: view.icon.Delete,
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
group: 'remove'
|
|
},
|
|
visibilityTester: view.function.CanDeleteObject,
|
|
override: [view.action.Delete],
|
|
analyticsEvent: TrackerEvents.IssueDeleted
|
|
},
|
|
tracker.action.DeleteIssue
|
|
)
|
|
|
|
builder.createDoc(
|
|
view.class.ActionCategory,
|
|
core.space.Model,
|
|
{ label: tracker.string.TrackerApplication, visible: true },
|
|
tracker.category.Tracker
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.CreateIssue,
|
|
element: 'top'
|
|
},
|
|
label: tracker.string.NewIssue,
|
|
icon: tracker.icon.NewIssue,
|
|
keyBinding: ['keyC'],
|
|
input: 'none',
|
|
category: tracker.category.Tracker,
|
|
target: core.class.Doc,
|
|
context: {
|
|
mode: ['browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'create'
|
|
},
|
|
override: [tracker.action.NewIssueGlobal],
|
|
analyticsEvent: TrackerEvents.NewIssueBindingCalled
|
|
},
|
|
tracker.action.NewIssue
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.CreateIssue,
|
|
element: 'top'
|
|
},
|
|
label: tracker.string.NewIssue,
|
|
icon: tracker.icon.NewIssue,
|
|
input: 'none',
|
|
category: tracker.category.Tracker,
|
|
target: core.class.Doc,
|
|
context: {
|
|
mode: [],
|
|
group: 'create'
|
|
},
|
|
analyticsEvent: TrackerEvents.IssueCreateFromGlobalActionCalled
|
|
},
|
|
tracker.action.NewIssueGlobal
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.CreateIssue,
|
|
element: 'top',
|
|
fillProps: {
|
|
_object: 'parentIssue',
|
|
space: 'space'
|
|
}
|
|
},
|
|
label: tracker.string.NewSubIssue,
|
|
icon: tracker.icon.Subissue,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.NewSubIssue
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.SetParentIssueActionPopup,
|
|
element: 'top',
|
|
fillProps: {
|
|
_objects: 'value'
|
|
}
|
|
},
|
|
label: tracker.string.SetParent,
|
|
icon: tracker.icon.Parent,
|
|
input: 'none',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.SetParent
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.CreateIssue,
|
|
element: 'top',
|
|
fillProps: {
|
|
_object: 'relatedTo',
|
|
space: 'space'
|
|
}
|
|
},
|
|
label: tracker.string.NewRelatedIssue,
|
|
icon: tracker.icon.NewIssue,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: core.class.Doc,
|
|
context: {
|
|
mode: ['context', 'browser', 'editor'],
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.NewRelatedIssue
|
|
)
|
|
|
|
createAction(builder, {
|
|
action: view.actionImpl.ShowPopup,
|
|
actionPopup: tracker.component.SetParentIssueActionPopup,
|
|
actionProps: {
|
|
component: tracker.component.SetParentIssueActionPopup,
|
|
element: 'top',
|
|
fillProps: {
|
|
_object: 'value'
|
|
}
|
|
},
|
|
label: tracker.string.SetParent,
|
|
icon: tracker.icon.Parent,
|
|
input: 'none',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
override: [tracker.action.SetParent],
|
|
context: {
|
|
mode: ['browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
})
|
|
|
|
createAction(builder, {
|
|
...actionTemplates.open,
|
|
actionProps: {
|
|
component: tracker.component.EditIssue
|
|
},
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['browser', 'context'],
|
|
group: 'create'
|
|
},
|
|
override: [view.action.Open]
|
|
})
|
|
|
|
createAction(builder, {
|
|
...actionTemplates.open,
|
|
actionProps: {
|
|
component: tracker.component.EditIssueTemplate
|
|
},
|
|
target: tracker.class.IssueTemplate,
|
|
context: {
|
|
mode: ['browser', 'context'],
|
|
group: 'create'
|
|
},
|
|
override: [view.action.Open]
|
|
})
|
|
|
|
createAction(builder, {
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.TimeSpendReportPopup,
|
|
fillProps: {
|
|
_object: 'issue'
|
|
}
|
|
},
|
|
label: tracker.string.TimeSpendReportAdd,
|
|
icon: tracker.icon.TimeReport,
|
|
input: 'focus',
|
|
keyBinding: ['keyT'],
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
})
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
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'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetStatus
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ValueSelector,
|
|
actionPopup: view.component.ValueSelector,
|
|
actionProps: {
|
|
attribute: 'priority',
|
|
values: defaultPriorities.map((p) => ({ id: p, ...issuePriorities[p] })),
|
|
placeholder: tracker.string.SetPriority
|
|
},
|
|
label: tracker.string.Priority,
|
|
icon: tracker.icon.PriorityHigh,
|
|
keyBinding: ['keyP->keyR'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetPriority
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.AttributeSelector,
|
|
actionPopup: tracker.component.AssigneeEditor,
|
|
actionProps: {
|
|
attribute: 'assignee',
|
|
isAction: true,
|
|
valueKey: 'object'
|
|
// _class: contact.mixin.Employee,
|
|
// query: {},
|
|
// placeholder: tracker.string.AssignTo
|
|
},
|
|
label: tracker.string.Assignee,
|
|
icon: contact.icon.Person,
|
|
keyBinding: ['keyA'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetAssignee
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.AttributeSelector,
|
|
actionPopup: tracker.component.ComponentEditor,
|
|
actionProps: {
|
|
attribute: 'component',
|
|
isAction: true
|
|
},
|
|
label: tracker.string.Component,
|
|
icon: tracker.icon.Component,
|
|
keyBinding: ['keyM->keyT'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetComponent
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.AttributeSelector,
|
|
actionPopup: tracker.component.MilestoneEditor,
|
|
actionProps: {
|
|
attribute: 'milestone',
|
|
isAction: true
|
|
},
|
|
label: tracker.string.Milestone,
|
|
icon: tracker.icon.Milestone,
|
|
keyBinding: ['keyS->keyP'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetMilestone
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tags.component.ObjectsTagsEditorPopup,
|
|
element: 'top',
|
|
fillProps: {
|
|
_objects: 'value'
|
|
}
|
|
},
|
|
label: tracker.string.Labels,
|
|
icon: tags.icon.Tags,
|
|
keyBinding: ['keyL'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetLabels
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.SetDueDateActionPopup,
|
|
props: { mondayStart: true, withTime: false },
|
|
element: 'top',
|
|
fillProps: {
|
|
_objects: 'value'
|
|
}
|
|
},
|
|
label: tracker.string.SetDueDate,
|
|
icon: tracker.icon.DueDate,
|
|
keyBinding: ['keyD'],
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'edit'
|
|
}
|
|
},
|
|
tracker.action.SetDueDate
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.CopyTextToClipboard,
|
|
actionProps: {
|
|
textProvider: tracker.function.GetIssueId
|
|
},
|
|
label: tracker.string.CopyIssueId,
|
|
icon: view.icon.CopyId,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
visibilityTester: view.function.IsClipboardAvailable,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'copy'
|
|
}
|
|
},
|
|
tracker.action.CopyIssueId
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.CopyTextToClipboard,
|
|
actionProps: {
|
|
textProvider: tracker.function.GetIssueTitle
|
|
},
|
|
label: tracker.string.CopyIssueTitle,
|
|
icon: tracker.icon.CopyBranch,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
visibilityTester: view.function.IsClipboardAvailable,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'copy'
|
|
}
|
|
},
|
|
tracker.action.CopyIssueTitle
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.CopyTextToClipboard,
|
|
actionProps: {
|
|
textProvider: tracker.function.GetIssueLink
|
|
},
|
|
label: tracker.string.CopyIssueUrl,
|
|
icon: view.icon.CopyLink,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
visibilityTester: view.function.IsClipboardAvailable,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'copy'
|
|
}
|
|
},
|
|
tracker.action.CopyIssueLink
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.Move,
|
|
label: tracker.string.MoveToProject,
|
|
icon: view.icon.Move,
|
|
input: 'any',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
},
|
|
override: [task.action.Move]
|
|
},
|
|
tracker.action.MoveToProject
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ValueSelector,
|
|
actionPopup: tracker.component.RelationsPopup,
|
|
actionProps: {
|
|
attribute: ''
|
|
},
|
|
label: tracker.string.Relations,
|
|
icon: tracker.icon.Relations,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.Relations
|
|
)
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.CreateIssue,
|
|
element: 'top',
|
|
fillProps: {
|
|
_object: 'originalIssue',
|
|
space: 'space'
|
|
}
|
|
},
|
|
label: tracker.string.Duplicate,
|
|
icon: tracker.icon.Duplicate,
|
|
input: 'focus',
|
|
category: tracker.category.Tracker,
|
|
target: tracker.class.Issue,
|
|
context: {
|
|
mode: ['context', 'browser'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.Duplicate
|
|
)
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: tracker.actionImpl.DeleteMilestone,
|
|
label: view.string.Delete,
|
|
icon: view.icon.Delete,
|
|
keyBinding: ['Meta + Backspace'],
|
|
category: tracker.category.Tracker,
|
|
input: 'any',
|
|
target: tracker.class.Milestone,
|
|
context: { mode: ['context', 'browser'], group: 'remove' },
|
|
visibilityTester: view.function.CanDeleteObject
|
|
},
|
|
tracker.action.DeleteMilestone
|
|
)
|
|
builder.mixin(tracker.class.Milestone, core.class.Class, view.mixin.IgnoreActions, {
|
|
actions: [view.action.Delete]
|
|
})
|
|
|
|
createAction(
|
|
builder,
|
|
{
|
|
action: view.actionImpl.ShowPopup,
|
|
actionProps: {
|
|
component: tracker.component.EditRelatedTargetsPopup,
|
|
element: 'top',
|
|
fillProps: {
|
|
_objects: 'value'
|
|
}
|
|
},
|
|
label: tracker.string.MapRelatedIssues,
|
|
icon: tracker.icon.Relations,
|
|
input: 'none',
|
|
category: tracker.category.Tracker,
|
|
target: core.class.Space,
|
|
query: {
|
|
_class: { $ne: tracker.class.Project }
|
|
},
|
|
context: {
|
|
mode: ['context'],
|
|
application: tracker.app.Tracker,
|
|
group: 'associate'
|
|
}
|
|
},
|
|
tracker.action.EditRelatedTargets
|
|
)
|
|
}
|