mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
Vacancy templates (#2351)
Signed-off-by: muhtimur <timur.mukhamedishin@xored.com>
This commit is contained in:
parent
bd1079cb53
commit
cdbead6584
@ -531,7 +531,8 @@ export function createModel (builder: Builder): void {
|
|||||||
{
|
{
|
||||||
name: recruit.string.Vacancies,
|
name: recruit.string.Vacancies,
|
||||||
description: recruit.string.ManageVacancyStatuses,
|
description: recruit.string.ManageVacancyStatuses,
|
||||||
icon: recruit.component.TemplatesIcon
|
icon: recruit.component.TemplatesIcon,
|
||||||
|
editor: recruit.component.VacancyTemplateEditor
|
||||||
},
|
},
|
||||||
recruit.space.VacancyTemplates
|
recruit.space.VacancyTemplates
|
||||||
)
|
)
|
||||||
|
@ -142,6 +142,8 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Kanba
|
|||||||
kanbanId: recruit.template.DefaultVacancy,
|
kanbanId: recruit.template.DefaultVacancy,
|
||||||
space: recruit.space.VacancyTemplates as Ref<Doc> as Ref<Space>,
|
space: recruit.space.VacancyTemplates as Ref<Doc> as Ref<Space>,
|
||||||
title: 'Default vacancy',
|
title: 'Default vacancy',
|
||||||
|
description: '',
|
||||||
|
shortDescription: '',
|
||||||
states: defaultKanban.states,
|
states: defaultKanban.states,
|
||||||
doneStates: defaultKanban.doneStates
|
doneStates: defaultKanban.doneStates
|
||||||
})
|
})
|
||||||
|
@ -87,7 +87,8 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
OpinionPresenter: '' as AnyComponent,
|
OpinionPresenter: '' as AnyComponent,
|
||||||
NewCandidateHeader: '' as AnyComponent,
|
NewCandidateHeader: '' as AnyComponent,
|
||||||
ApplicantFilter: '' as AnyComponent,
|
ApplicantFilter: '' as AnyComponent,
|
||||||
VacancyList: '' as AnyComponent
|
VacancyList: '' as AnyComponent,
|
||||||
|
VacancyTemplateEditor: '' as AnyComponent
|
||||||
},
|
},
|
||||||
template: {
|
template: {
|
||||||
DefaultVacancy: '' as Ref<KanbanTemplate>,
|
DefaultVacancy: '' as Ref<KanbanTemplate>,
|
||||||
|
@ -163,14 +163,14 @@ export function createModel (builder: Builder): void {
|
|||||||
core.space.Model,
|
core.space.Model,
|
||||||
{
|
{
|
||||||
name: 'statuses',
|
name: 'statuses',
|
||||||
label: setting.string.ManageStatuses,
|
label: setting.string.ManageTemplates,
|
||||||
icon: task.icon.ManageStatuses,
|
icon: task.icon.ManageTemplates,
|
||||||
component: setting.component.ManageStatuses,
|
component: setting.component.ManageTemplates,
|
||||||
group: 'settings-editor',
|
group: 'settings-editor',
|
||||||
secured: false,
|
secured: false,
|
||||||
order: 4000
|
order: 4000
|
||||||
},
|
},
|
||||||
setting.ids.ManageStatuses
|
setting.ids.ManageTemplates
|
||||||
)
|
)
|
||||||
builder.createDoc(
|
builder.createDoc(
|
||||||
setting.class.WorkspaceSettingCategory,
|
setting.class.WorkspaceSettingCategory,
|
||||||
|
@ -180,7 +180,7 @@ export class TIssue extends TTask implements Issue {
|
|||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
name!: string
|
name!: string
|
||||||
|
|
||||||
@Prop(TypeMarkup(), task.string.TaskDescription)
|
@Prop(TypeMarkup(), task.string.Description)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
description!: string
|
description!: string
|
||||||
|
|
||||||
@ -211,6 +211,7 @@ export class TKanbanTemplateSpace extends TDoc implements KanbanTemplateSpace {
|
|||||||
name!: IntlString
|
name!: IntlString
|
||||||
description!: IntlString
|
description!: IntlString
|
||||||
icon!: AnyComponent
|
icon!: AnyComponent
|
||||||
|
editor!: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [task.interface.DocWithRank])
|
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [task.interface.DocWithRank])
|
||||||
@ -244,6 +245,12 @@ export class TKanbanTemplate extends TDoc implements KanbanTemplate {
|
|||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
|
@Prop(TypeString(), task.string.Description)
|
||||||
|
description!: string
|
||||||
|
|
||||||
|
@Prop(TypeString(), task.string.ShortDescription)
|
||||||
|
shortDescription!: string
|
||||||
|
|
||||||
@Prop(Collection(task.class.StateTemplate), task.string.States)
|
@Prop(Collection(task.class.StateTemplate), task.string.States)
|
||||||
statesC!: number
|
statesC!: number
|
||||||
|
|
||||||
@ -347,7 +354,7 @@ export function createModel (builder: Builder): void {
|
|||||||
core.space.Model,
|
core.space.Model,
|
||||||
{
|
{
|
||||||
label: task.string.States,
|
label: task.string.States,
|
||||||
icon: task.icon.ManageStatuses,
|
icon: task.icon.ManageTemplates,
|
||||||
component: task.component.StatusTableView
|
component: task.component.StatusTableView
|
||||||
},
|
},
|
||||||
task.viewlet.StatusTable
|
task.viewlet.StatusTable
|
||||||
@ -381,6 +388,10 @@ export function createModel (builder: Builder): void {
|
|||||||
presenter: task.component.TaskPresenter
|
presenter: task.component.TaskPresenter
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.mixin(task.class.KanbanTemplate, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
|
presenter: task.component.KanbanTemplatePresenter
|
||||||
|
})
|
||||||
|
|
||||||
builder.mixin(task.class.Issue, core.class.Class, view.mixin.ObjectEditor, {
|
builder.mixin(task.class.Issue, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
editor: task.component.EditIssue
|
editor: task.component.EditIssue
|
||||||
})
|
})
|
||||||
|
@ -28,6 +28,8 @@ export interface KanbanTemplateData {
|
|||||||
kanbanId: Ref<KanbanTemplate>
|
kanbanId: Ref<KanbanTemplate>
|
||||||
space: Ref<Space>
|
space: Ref<Space>
|
||||||
title: KanbanTemplate['title']
|
title: KanbanTemplate['title']
|
||||||
|
description?: string
|
||||||
|
shortDescription?: string
|
||||||
states: Pick<StateTemplate, 'title' | 'color'>[]
|
states: Pick<StateTemplate, 'title' | 'color'>[]
|
||||||
doneStates: (Pick<DoneStateTemplate, 'title'> & { isWon: boolean })[]
|
doneStates: (Pick<DoneStateTemplate, 'title'> & { isWon: boolean })[]
|
||||||
}
|
}
|
||||||
@ -157,6 +159,8 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Kanba
|
|||||||
kanbanId: task.template.DefaultProject,
|
kanbanId: task.template.DefaultProject,
|
||||||
space: task.space.ProjectTemplates as Ref<Doc> as Ref<Space>,
|
space: task.space.ProjectTemplates as Ref<Doc> as Ref<Space>,
|
||||||
title: 'Default project',
|
title: 'Default project',
|
||||||
|
description: '',
|
||||||
|
shortDescription: '',
|
||||||
states: defaultKanban.states,
|
states: defaultKanban.states,
|
||||||
doneStates: defaultKanban.doneStates
|
doneStates: defaultKanban.doneStates
|
||||||
})
|
})
|
||||||
|
@ -46,6 +46,7 @@ export default mergeIds(taskId, task, {
|
|||||||
CreateProject: '' as AnyComponent,
|
CreateProject: '' as AnyComponent,
|
||||||
EditIssue: '' as AnyComponent,
|
EditIssue: '' as AnyComponent,
|
||||||
TaskPresenter: '' as AnyComponent,
|
TaskPresenter: '' as AnyComponent,
|
||||||
|
KanbanTemplatePresenter: '' as AnyComponent,
|
||||||
KanbanCard: '' as AnyComponent,
|
KanbanCard: '' as AnyComponent,
|
||||||
TemplatesIcon: '' as AnyComponent,
|
TemplatesIcon: '' as AnyComponent,
|
||||||
StatePresenter: '' as AnyComponent,
|
StatePresenter: '' as AnyComponent,
|
||||||
|
@ -302,6 +302,9 @@ export class TIssueTemplate extends TDoc implements IssueTemplate {
|
|||||||
|
|
||||||
@Prop(Collection(attachment.class.Attachment), tracker.string.Attachments)
|
@Prop(Collection(attachment.class.Attachment), tracker.string.Attachments)
|
||||||
attachments!: number
|
attachments!: number
|
||||||
|
|
||||||
|
@Prop(ArrOf(TypeRef(core.class.TypeRelatedDocument)), tracker.string.RelatedTo)
|
||||||
|
relations!: RelatedDocument[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -397,6 +397,7 @@ input.search {
|
|||||||
.mb-3 { margin-bottom: .75rem; }
|
.mb-3 { margin-bottom: .75rem; }
|
||||||
.mb-4 { margin-bottom: 1rem; }
|
.mb-4 { margin-bottom: 1rem; }
|
||||||
.mb-6 { margin-bottom: 1.5rem; }
|
.mb-6 { margin-bottom: 1.5rem; }
|
||||||
|
.mb-9 { margin-bottom: 2.25rem; }
|
||||||
.mb-10 { margin-bottom: 2.5rem; }
|
.mb-10 { margin-bottom: 2.5rem; }
|
||||||
.mx-1 { margin: 0 .25rem; }
|
.mx-1 { margin: 0 .25rem; }
|
||||||
.mx-2 { margin: 0 .5rem; }
|
.mx-2 { margin: 0 .5rem; }
|
||||||
|
@ -53,4 +53,8 @@
|
|||||||
<symbol id="skills" viewBox="0 0 24 24">
|
<symbol id="skills" viewBox="0 0 24 24">
|
||||||
<path d="M22.8,8.7c0-0.3-0.2-0.6-0.5-0.7L11.8,3.8c-0.2-0.1-0.4-0.1-0.6,0L0.7,8C0.4,8.1,0.2,8.4,0.2,8.7 s0.2,0.6,0.5,0.7L5,11.1v6c0,0.2,0.1,0.4,0.2,0.5l0.5-0.5c-0.5,0.5-0.5,0.5-0.5,0.5l0,0l0,0l0,0l0,0c0,0,0.1,0.1,0.1,0.1 c0.1,0.1,0.2,0.2,0.3,0.3C6,18.3,6.5,18.6,7,19c1.1,0.6,2.7,1.3,4.5,1.3c1.8,0,3.4-0.7,4.5-1.3c0.5-0.3,1-0.6,1.3-0.9 c0.2-0.1,0.3-0.2,0.3-0.3c0,0,0.1-0.1,0.1-0.1l0,0l0,0l0,0l0,0l-0.5-0.5c0.5,0.5,0.5,0.5,0.5,0.5c0.1-0.1,0.2-0.3,0.2-0.5v-6 l3.3-1.3v3.6c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8L22.8,8.7C22.8,8.7,22.8,8.7,22.8,8.7C22.8,8.7,22.8,8.7,22.8,8.7z M16.5,16.8c0,0-0.1,0.1-0.1,0.1c-0.3,0.2-0.6,0.5-1.1,0.8c-0.9,0.6-2.2,1.1-3.7,1.1c-1.5,0-2.8-0.5-3.7-1.1 c-0.5-0.3-0.8-0.5-1.1-0.8c-0.1,0-0.1-0.1-0.1-0.1v-5.1l4.7,1.9c0.2,0.1,0.4,0.1,0.6,0l4.7-1.9V16.8z M11.5,12.1L3,8.7l8.5-3.4 L20,8.7L11.5,12.1z" />
|
<path d="M22.8,8.7c0-0.3-0.2-0.6-0.5-0.7L11.8,3.8c-0.2-0.1-0.4-0.1-0.6,0L0.7,8C0.4,8.1,0.2,8.4,0.2,8.7 s0.2,0.6,0.5,0.7L5,11.1v6c0,0.2,0.1,0.4,0.2,0.5l0.5-0.5c-0.5,0.5-0.5,0.5-0.5,0.5l0,0l0,0l0,0l0,0c0,0,0.1,0.1,0.1,0.1 c0.1,0.1,0.2,0.2,0.3,0.3C6,18.3,6.5,18.6,7,19c1.1,0.6,2.7,1.3,4.5,1.3c1.8,0,3.4-0.7,4.5-1.3c0.5-0.3,1-0.6,1.3-0.9 c0.2-0.1,0.3-0.2,0.3-0.3c0,0,0.1-0.1,0.1-0.1l0,0l0,0l0,0l0,0l-0.5-0.5c0.5,0.5,0.5,0.5,0.5,0.5c0.1-0.1,0.2-0.3,0.2-0.5v-6 l3.3-1.3v3.6c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8L22.8,8.7C22.8,8.7,22.8,8.7,22.8,8.7C22.8,8.7,22.8,8.7,22.8,8.7z M16.5,16.8c0,0-0.1,0.1-0.1,0.1c-0.3,0.2-0.6,0.5-1.1,0.8c-0.9,0.6-2.2,1.1-3.7,1.1c-1.5,0-2.8-0.5-3.7-1.1 c-0.5-0.3-0.8-0.5-1.1-0.8c-0.1,0-0.1-0.1-0.1-0.1v-5.1l4.7,1.9c0.2,0.1,0.4,0.1,0.6,0l4.7-1.9V16.8z M11.5,12.1L3,8.7l8.5-3.4 L20,8.7L11.5,12.1z" />
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="issue" viewBox="0 0 16 16">
|
||||||
|
<path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
|
||||||
|
<ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
|
||||||
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.6 KiB |
@ -54,7 +54,7 @@
|
|||||||
"PersonFirstNamePlaceholder": "John",
|
"PersonFirstNamePlaceholder": "John",
|
||||||
"PersonLastNamePlaceholder": "Appleseed",
|
"PersonLastNamePlaceholder": "Appleseed",
|
||||||
"PersonLocationPlaceholder": "Location",
|
"PersonLocationPlaceholder": "Location",
|
||||||
"ManageVacancyStatuses": "Manage vacancy statuses",
|
"ManageVacancyStatuses": "Manage vacancy templates",
|
||||||
"EditVacancy": "Edit",
|
"EditVacancy": "Edit",
|
||||||
"FullDescription": "Full description",
|
"FullDescription": "Full description",
|
||||||
"CreateReview": "Schedule an Review",
|
"CreateReview": "Schedule an Review",
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"PersonFirstNamePlaceholder": "John",
|
"PersonFirstNamePlaceholder": "John",
|
||||||
"PersonLastNamePlaceholder": "Appleseed",
|
"PersonLastNamePlaceholder": "Appleseed",
|
||||||
"PersonLocationPlaceholder": "Местоположение",
|
"PersonLocationPlaceholder": "Местоположение",
|
||||||
"ManageVacancyStatuses": "Управление статусами вакансии",
|
"ManageVacancyStatuses": "Управление шаблонами вакансии",
|
||||||
"EditVacancy": "Редактировать",
|
"EditVacancy": "Редактировать",
|
||||||
"FullDescription": "Детальное описание",
|
"FullDescription": "Детальное описание",
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ loadMetadata(recruit.icon, {
|
|||||||
CreateCandidate: `${icons}#new-candidate`,
|
CreateCandidate: `${icons}#new-candidate`,
|
||||||
AssignedToMe: `${icons}#assignedToMe`,
|
AssignedToMe: `${icons}#assignedToMe`,
|
||||||
Reviews: `${icons}#reviews`,
|
Reviews: `${icons}#reviews`,
|
||||||
Skills: `${icons}#skills`
|
Skills: `${icons}#skills`,
|
||||||
|
Issue: `${icons}#issue`
|
||||||
})
|
})
|
||||||
|
|
||||||
addStringsLoader(recruitId, async (lang: string) => await import(`../lang/${lang}.json`))
|
addStringsLoader(recruitId, async (lang: string) => await import(`../lang/${lang}.json`))
|
||||||
|
@ -15,10 +15,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
||||||
import contact, { Organization } from '@hcengineering/contact'
|
import contact, { Organization } from '@hcengineering/contact'
|
||||||
import core, { generateId, getCurrentAccount, Ref } from '@hcengineering/core'
|
import core, { FindResult, generateId, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||||
import { Card, getClient, UserBox } from '@hcengineering/presentation'
|
import { Card, createQuery, getClient, UserBox } from '@hcengineering/presentation'
|
||||||
import task, { createKanban, KanbanTemplate } from '@hcengineering/task'
|
import task, { createKanban, KanbanTemplate } from '@hcengineering/task'
|
||||||
import { Button, Component, createFocusManager, EditBox, FocusHandler, IconAttachment } from '@hcengineering/ui'
|
import { Button, Component, createFocusManager, EditBox, FocusHandler, IconAttachment } from '@hcengineering/ui'
|
||||||
|
import tracker, { IssueStatus, IssueTemplate } from '@hcengineering/tracker'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import recruit from '../plugin'
|
import recruit from '../plugin'
|
||||||
import { Vacancy as VacancyClass } from '@hcengineering/recruit'
|
import { Vacancy as VacancyClass } from '@hcengineering/recruit'
|
||||||
@ -28,10 +29,10 @@
|
|||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let name: string = ''
|
let name: string = ''
|
||||||
const description: string = ''
|
let template: KanbanTemplate | undefined
|
||||||
let fullDescription: string = ''
|
|
||||||
let templateId: Ref<KanbanTemplate> | undefined
|
let templateId: Ref<KanbanTemplate> | undefined
|
||||||
let objectId: Ref<VacancyClass> = generateId()
|
let objectId: Ref<VacancyClass> = generateId()
|
||||||
|
let issueTemplates: FindResult<IssueTemplate>
|
||||||
|
|
||||||
export let company: Ref<Organization> | undefined
|
export let company: Ref<Organization> | undefined
|
||||||
export let preserveCompany: boolean = false
|
export let preserveCompany: boolean = false
|
||||||
@ -41,6 +42,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
const templateQ = createQuery()
|
||||||
|
$: templateQ.query(task.class.KanbanTemplate, { _id: templateId }, (result) => {
|
||||||
|
template = result[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
const issueTemplatesQ = createQuery()
|
||||||
|
$: issueTemplatesQ.query(tracker.class.IssueTemplate, { 'relations._id': templateId }, async (result) => {
|
||||||
|
issueTemplates = result
|
||||||
|
})
|
||||||
|
|
||||||
async function createVacancy () {
|
async function createVacancy () {
|
||||||
if (
|
if (
|
||||||
@ -54,9 +64,10 @@
|
|||||||
recruit.class.Vacancy,
|
recruit.class.Vacancy,
|
||||||
core.space.Space,
|
core.space.Space,
|
||||||
{
|
{
|
||||||
|
...template,
|
||||||
name,
|
name,
|
||||||
description,
|
description: template?.shortDescription ?? '',
|
||||||
fullDescription,
|
fullDescription: template?.description ?? '',
|
||||||
private: false,
|
private: false,
|
||||||
archived: false,
|
archived: false,
|
||||||
company,
|
company,
|
||||||
@ -65,6 +76,45 @@
|
|||||||
objectId
|
objectId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for (const issueTemplate of issueTemplates) {
|
||||||
|
const incResult = await client.updateDoc(
|
||||||
|
tracker.class.Team,
|
||||||
|
core.space.Space,
|
||||||
|
issueTemplate.space,
|
||||||
|
{
|
||||||
|
$inc: { sequence: 1 }
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
await client.addCollection(
|
||||||
|
tracker.class.Issue,
|
||||||
|
issueTemplate.space,
|
||||||
|
tracker.ids.NoParent,
|
||||||
|
tracker.class.Issue,
|
||||||
|
'subIssues',
|
||||||
|
{
|
||||||
|
title: issueTemplate.title,
|
||||||
|
description: issueTemplate.description,
|
||||||
|
assignee: issueTemplate.assignee,
|
||||||
|
project: issueTemplate.project,
|
||||||
|
sprint: issueTemplate.sprint,
|
||||||
|
number: (incResult as any).object.sequence,
|
||||||
|
status: '' as Ref<IssueStatus>,
|
||||||
|
priority: issueTemplate.priority,
|
||||||
|
rank: '',
|
||||||
|
comments: 0,
|
||||||
|
subIssues: 0,
|
||||||
|
dueDate: null,
|
||||||
|
parents: [],
|
||||||
|
reportedTime: 0,
|
||||||
|
estimation: issueTemplate.estimation,
|
||||||
|
reports: 0,
|
||||||
|
relations: [{ _id: id, _class: recruit.class.Vacancy }],
|
||||||
|
childInfo: []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await createKanban(client, id, templateId)
|
await createKanban(client, id, templateId)
|
||||||
|
|
||||||
await descriptionBox.createAttachments()
|
await descriptionBox.createAttachments()
|
||||||
@ -117,20 +167,6 @@
|
|||||||
showNavigate={false}
|
showNavigate={false}
|
||||||
create={{ component: contact.component.CreateOrganization, label: contact.string.CreateOrganization }}
|
create={{ component: contact.component.CreateOrganization, label: contact.string.CreateOrganization }}
|
||||||
/>
|
/>
|
||||||
</svelte:fragment>
|
|
||||||
|
|
||||||
<AttachmentStyledBox
|
|
||||||
bind:this={descriptionBox}
|
|
||||||
{objectId}
|
|
||||||
_class={recruit.class.Vacancy}
|
|
||||||
space={objectId}
|
|
||||||
alwaysEdit
|
|
||||||
showButtons={false}
|
|
||||||
maxHeight={'card'}
|
|
||||||
bind:content={fullDescription}
|
|
||||||
placeholder={recruit.string.FullDescription}
|
|
||||||
/>
|
|
||||||
<svelte:fragment slot="pool">
|
|
||||||
<Component
|
<Component
|
||||||
is={task.component.KanbanTemplateSelector}
|
is={task.component.KanbanTemplateSelector}
|
||||||
props={{
|
props={{
|
||||||
@ -143,6 +179,19 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
{#key template?.description}
|
||||||
|
<AttachmentStyledBox
|
||||||
|
bind:this={descriptionBox}
|
||||||
|
{objectId}
|
||||||
|
_class={recruit.class.Vacancy}
|
||||||
|
space={objectId}
|
||||||
|
alwaysEdit
|
||||||
|
showButtons={false}
|
||||||
|
maxHeight={'card'}
|
||||||
|
content={template?.description ?? ''}
|
||||||
|
placeholder={recruit.string.FullDescription}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
<Button
|
<Button
|
||||||
icon={IconAttachment}
|
icon={IconAttachment}
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { AttributesBar, getClient } from '@hcengineering/presentation'
|
||||||
|
import { Button, Component, EditBox, Icon, IconAdd, Label, showPopup } from '@hcengineering/ui'
|
||||||
|
import { StyledTextBox } from '@hcengineering/text-editor'
|
||||||
|
import { KanbanTemplate } from '@hcengineering/task'
|
||||||
|
import { getFiltredKeys } from '@hcengineering/view-resources/src/utils'
|
||||||
|
import tracker from '@hcengineering/tracker'
|
||||||
|
import recruit from '../plugin'
|
||||||
|
|
||||||
|
export let template: KanbanTemplate
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
const customKeys = getFiltredKeys(hierarchy, template._class, []).filter((key) => key.attr.isCustom)
|
||||||
|
|
||||||
|
async function onDescriptionChange (value: string) {
|
||||||
|
await client.update(template, { description: value })
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onShortDescriptionChange (value: string) {
|
||||||
|
await client.update(template, { shortDescription: value })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
|
<Label label={recruit.string.Description} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<EditBox
|
||||||
|
kind={'small-style'}
|
||||||
|
bind:value={template.shortDescription}
|
||||||
|
on:change={() => onShortDescriptionChange(template.shortDescription ?? '')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-9">
|
||||||
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
|
<Label label={recruit.string.FullDescription} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
{#key template._id}
|
||||||
|
<StyledTextBox
|
||||||
|
emphasized
|
||||||
|
alwaysEdit
|
||||||
|
showButtons={false}
|
||||||
|
content={template.description ?? ''}
|
||||||
|
on:value={(evt) => onDescriptionChange(evt.detail)}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="antiSection mt-9 mb-9">
|
||||||
|
<div class="antiSection-header">
|
||||||
|
<div class="antiSection-header__icon">
|
||||||
|
<Icon icon={recruit.icon.Issue} size={'small'} />
|
||||||
|
</div>
|
||||||
|
<span class="antiSection-header__title">
|
||||||
|
<Label label={recruit.string.RelatedIssues} />
|
||||||
|
</span>
|
||||||
|
<div class="buttons-group small-gap">
|
||||||
|
<Button
|
||||||
|
id="add-sub-issue"
|
||||||
|
width="min-content"
|
||||||
|
icon={IconAdd}
|
||||||
|
label={undefined}
|
||||||
|
labelParams={{ subIssues: 0 }}
|
||||||
|
kind={'transparent'}
|
||||||
|
size={'small'}
|
||||||
|
on:click={() => showPopup(tracker.component.CreateIssueTemplate, { relatedTo: template })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-row">
|
||||||
|
<Component is={tracker.component.RelatedIssueTemplates} props={{ object: template }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if customKeys && customKeys.length > 0}
|
||||||
|
<div class="antiSection mb-9">
|
||||||
|
<AttributesBar object={template} _class={template._class} keys={customKeys} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
@ -52,6 +52,7 @@ import VacancyPresenter from './components/VacancyPresenter.svelte'
|
|||||||
import recruit from './plugin'
|
import recruit from './plugin'
|
||||||
import { objectIdProvider, objectLinkProvider, getApplicationTitle } from './utils'
|
import { objectIdProvider, objectLinkProvider, getApplicationTitle } from './utils'
|
||||||
import VacancyList from './components/VacancyList.svelte'
|
import VacancyList from './components/VacancyList.svelte'
|
||||||
|
import VacancyTemplateEditor from './components/VacancyTemplateEditor.svelte'
|
||||||
|
|
||||||
async function createOpinion (object: Doc): Promise<void> {
|
async function createOpinion (object: Doc): Promise<void> {
|
||||||
showPopup(CreateOpinion, { space: object.space, review: object._id })
|
showPopup(CreateOpinion, { space: object.space, review: object._id })
|
||||||
@ -289,7 +290,8 @@ export default async (): Promise<Resources> => ({
|
|||||||
|
|
||||||
ApplicantFilter,
|
ApplicantFilter,
|
||||||
|
|
||||||
VacancyList
|
VacancyList,
|
||||||
|
VacancyTemplateEditor
|
||||||
},
|
},
|
||||||
completion: {
|
completion: {
|
||||||
ApplicationQuery: async (
|
ApplicationQuery: async (
|
||||||
|
@ -131,7 +131,8 @@ const recruit = plugin(recruitId, {
|
|||||||
CreateCandidate: '' as Asset,
|
CreateCandidate: '' as Asset,
|
||||||
AssignedToMe: '' as Asset,
|
AssignedToMe: '' as Asset,
|
||||||
Reviews: '' as Asset,
|
Reviews: '' as Asset,
|
||||||
Skills: '' as Asset
|
Skills: '' as Asset,
|
||||||
|
Issue: '' as Asset
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
VacancyTemplates: '' as Ref<KanbanTemplateSpace>,
|
VacancyTemplates: '' as Ref<KanbanTemplateSpace>,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
"Setting": "Setting",
|
"Setting": "Setting",
|
||||||
"ManageStatuses": "Manage Statuses",
|
"ManageTemplates": "Manage Templates",
|
||||||
"Integrations": "Integrations",
|
"Integrations": "Integrations",
|
||||||
"Support": "Support",
|
"Support": "Support",
|
||||||
"Privacy": "Privacy",
|
"Privacy": "Privacy",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
"Setting": "Настройки",
|
"Setting": "Настройки",
|
||||||
"ManageStatuses": "Управление статусами",
|
"ManageTemplates": "Управление шаблонами",
|
||||||
"Integrations": "Интеграции",
|
"Integrations": "Интеграции",
|
||||||
"Support": "Поддержка",
|
"Support": "Поддержка",
|
||||||
"Privacy": "Конфиденциальность",
|
"Privacy": "Конфиденциальность",
|
||||||
|
@ -61,8 +61,8 @@
|
|||||||
|
|
||||||
<div class="antiComponent">
|
<div class="antiComponent">
|
||||||
<div class="ac-header short divide">
|
<div class="ac-header short divide">
|
||||||
<div class="ac-header__icon"><Icon icon={task.icon.ManageStatuses} size={'medium'} /></div>
|
<div class="ac-header__icon"><Icon icon={task.icon.ManageTemplates} size={'medium'} /></div>
|
||||||
<div class="ac-header__title"><Label label={setting.string.ManageStatuses} /></div>
|
<div class="ac-header__title"><Label label={setting.string.ManageTemplates} /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ac-body columns hScroll">
|
<div class="ac-body columns hScroll">
|
||||||
<div class="ac-column">
|
<div class="ac-column">
|
||||||
@ -75,7 +75,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ac-column max">
|
<div class="ac-column max">
|
||||||
{#if template !== undefined}
|
{#if template !== undefined}
|
||||||
<Component is={task.component.KanbanTemplateEditor} props={{ kanban: template }} on:delete={onDeleteState} />
|
<Component
|
||||||
|
is={task.component.KanbanTemplateEditor}
|
||||||
|
props={{ kanban: template, folder }}
|
||||||
|
on:delete={onDeleteState}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -30,7 +30,7 @@ import Password from './components/Password.svelte'
|
|||||||
import Privacy from './components/Privacy.svelte'
|
import Privacy from './components/Privacy.svelte'
|
||||||
import Profile from './components/Profile.svelte'
|
import Profile from './components/Profile.svelte'
|
||||||
import Settings from './components/Settings.svelte'
|
import Settings from './components/Settings.svelte'
|
||||||
import ManageStatuses from './components/statuses/ManageStatuses.svelte'
|
import ManageTemplates from './components/statuses/ManageTemplates.svelte'
|
||||||
import Support from './components/Support.svelte'
|
import Support from './components/Support.svelte'
|
||||||
import Terms from './components/Terms.svelte'
|
import Terms from './components/Terms.svelte'
|
||||||
import BooleanTypeEditor from './components/typeEditors/BooleanTypeEditor.svelte'
|
import BooleanTypeEditor from './components/typeEditors/BooleanTypeEditor.svelte'
|
||||||
@ -79,7 +79,7 @@ export default async (): Promise<Resources> => ({
|
|||||||
Support,
|
Support,
|
||||||
Privacy,
|
Privacy,
|
||||||
Terms,
|
Terms,
|
||||||
ManageStatuses,
|
ManageTemplates,
|
||||||
ClassSetting,
|
ClassSetting,
|
||||||
StringTypeEditor,
|
StringTypeEditor,
|
||||||
HyperlinkTypeEditor,
|
HyperlinkTypeEditor,
|
||||||
|
@ -85,7 +85,7 @@ export default plugin(settingId, {
|
|||||||
Password: '' as Ref<Doc>,
|
Password: '' as Ref<Doc>,
|
||||||
Setting: '' as Ref<Doc>,
|
Setting: '' as Ref<Doc>,
|
||||||
Integrations: '' as Ref<Doc>,
|
Integrations: '' as Ref<Doc>,
|
||||||
ManageStatuses: '' as Ref<Doc>,
|
ManageTemplates: '' as Ref<Doc>,
|
||||||
Support: '' as Ref<Doc>,
|
Support: '' as Ref<Doc>,
|
||||||
Privacy: '' as Ref<Doc>,
|
Privacy: '' as Ref<Doc>,
|
||||||
Terms: '' as Ref<Doc>,
|
Terms: '' as Ref<Doc>,
|
||||||
@ -108,7 +108,7 @@ export default plugin(settingId, {
|
|||||||
Password: '' as AnyComponent,
|
Password: '' as AnyComponent,
|
||||||
WorkspaceSettings: '' as AnyComponent,
|
WorkspaceSettings: '' as AnyComponent,
|
||||||
Integrations: '' as AnyComponent,
|
Integrations: '' as AnyComponent,
|
||||||
ManageStatuses: '' as AnyComponent,
|
ManageTemplates: '' as AnyComponent,
|
||||||
Support: '' as AnyComponent,
|
Support: '' as AnyComponent,
|
||||||
Privacy: '' as AnyComponent,
|
Privacy: '' as AnyComponent,
|
||||||
Terms: '' as AnyComponent,
|
Terms: '' as AnyComponent,
|
||||||
@ -119,7 +119,7 @@ export default plugin(settingId, {
|
|||||||
Setting: '' as IntlString,
|
Setting: '' as IntlString,
|
||||||
WorkspaceSetting: '' as IntlString,
|
WorkspaceSetting: '' as IntlString,
|
||||||
Integrations: '' as IntlString,
|
Integrations: '' as IntlString,
|
||||||
ManageStatuses: '' as IntlString,
|
ManageTemplates: '' as IntlString,
|
||||||
Support: '' as IntlString,
|
Support: '' as IntlString,
|
||||||
Privacy: '' as IntlString,
|
Privacy: '' as IntlString,
|
||||||
Terms: '' as IntlString,
|
Terms: '' as IntlString,
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<symbol id='todo-uncheck' viewBox="0 0 16 16">
|
<symbol id='todo-uncheck' viewBox="0 0 16 16">
|
||||||
<path d="M8,14.5c-3.6,0-6.5-2.9-6.5-6.5S4.4,1.5,8,1.5s6.5,2.9,6.5,6.5S11.6,14.5,8,14.5z M8,2.5C5,2.5,2.5,5,2.5,8 c0,3,2.5,5.5,5.5,5.5c3,0,5.5-2.5,5.5-5.5C13.5,5,11,2.5,8,2.5z"/>
|
<path d="M8,14.5c-3.6,0-6.5-2.9-6.5-6.5S4.4,1.5,8,1.5s6.5,2.9,6.5,6.5S11.6,14.5,8,14.5z M8,2.5C5,2.5,2.5,5,2.5,8 c0,3,2.5,5.5,5.5,5.5c3,0,5.5-2.5,5.5-5.5C13.5,5,11,2.5,8,2.5z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
<symbol id="manage-statuses" viewBox="0 0 16 16">
|
<symbol id="manage-templates" viewBox="0 0 16 16">
|
||||||
<path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
|
<path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
|
||||||
<ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
|
<ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
|
"Description": "Description",
|
||||||
|
"DescriptionPlaceholder": "Description",
|
||||||
|
"ShortDescription": "Short description",
|
||||||
"StartDate": "Start date",
|
"StartDate": "Start date",
|
||||||
"DueDate": "Due date",
|
"DueDate": "Due date",
|
||||||
"TaskState": "State",
|
"TaskState": "State",
|
||||||
@ -14,7 +17,6 @@
|
|||||||
"Task": "Task",
|
"Task": "Task",
|
||||||
"TaskParent": "Parent",
|
"TaskParent": "Parent",
|
||||||
"IssueName": "Name",
|
"IssueName": "Name",
|
||||||
"TaskDescription": "Description",
|
|
||||||
"TaskComments": "Comments",
|
"TaskComments": "Comments",
|
||||||
"TaskLabels": "Labels",
|
"TaskLabels": "Labels",
|
||||||
"TaskAssignee": "Assignee",
|
"TaskAssignee": "Assignee",
|
||||||
@ -34,7 +36,6 @@
|
|||||||
"CreateProject": "New Project",
|
"CreateProject": "New Project",
|
||||||
"ProjectNamePlaceholder": "Project name",
|
"ProjectNamePlaceholder": "Project name",
|
||||||
"TaskNamePlaceholder": "The boring task",
|
"TaskNamePlaceholder": "The boring task",
|
||||||
"TaskDescriptionPlaceholder": "Description",
|
|
||||||
"TodoDescriptionPlaceholder": "todo...",
|
"TodoDescriptionPlaceholder": "todo...",
|
||||||
"MakePrivate": "Make Private",
|
"MakePrivate": "Make Private",
|
||||||
"MakePrivateDescription": "Only members can see it",
|
"MakePrivateDescription": "Only members can see it",
|
||||||
@ -76,6 +77,7 @@
|
|||||||
"Assigned": "Assigned to me",
|
"Assigned": "Assigned to me",
|
||||||
"TodoItems": "Todos",
|
"TodoItems": "Todos",
|
||||||
"Dashboard": "Dashboard",
|
"Dashboard": "Dashboard",
|
||||||
"AllTime": "All time"
|
"AllTime": "All time",
|
||||||
|
"RelatedIssues": "Related processes"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
|
"Description": "Описание",
|
||||||
|
"DescriptionPlaceholder": "Описание",
|
||||||
|
"ShortDescription": "Короткое описание",
|
||||||
"StartDate": "Начало",
|
"StartDate": "Начало",
|
||||||
"DueDate": "Срок",
|
"DueDate": "Срок",
|
||||||
"TaskState": "Статус",
|
"TaskState": "Статус",
|
||||||
@ -14,7 +17,6 @@
|
|||||||
"Task": "Задача",
|
"Task": "Задача",
|
||||||
"TaskParent": "Родитель",
|
"TaskParent": "Родитель",
|
||||||
"IssueName": "Название",
|
"IssueName": "Название",
|
||||||
"TaskDescription": "Описание",
|
|
||||||
"TaskComments": "Комментарии",
|
"TaskComments": "Комментарии",
|
||||||
"TaskLabels": "Ярлыки",
|
"TaskLabels": "Ярлыки",
|
||||||
"TaskAssignee": "Назначен",
|
"TaskAssignee": "Назначен",
|
||||||
@ -34,7 +36,6 @@
|
|||||||
"CreateProject": "Новый проект",
|
"CreateProject": "Новый проект",
|
||||||
"ProjectNamePlaceholder": "Название проекта",
|
"ProjectNamePlaceholder": "Название проекта",
|
||||||
"TaskNamePlaceholder": "Задача",
|
"TaskNamePlaceholder": "Задача",
|
||||||
"TaskDescriptionPlaceholder": "Описание",
|
|
||||||
"TodoDescriptionPlaceholder": "todo...",
|
"TodoDescriptionPlaceholder": "todo...",
|
||||||
"MakePrivate": "Сделать личным",
|
"MakePrivate": "Сделать личным",
|
||||||
"MakePrivateDescription": "Только пользователи могут видеть это",
|
"MakePrivateDescription": "Только пользователи могут видеть это",
|
||||||
@ -76,6 +77,7 @@
|
|||||||
"Assigned": "Назначения",
|
"Assigned": "Назначения",
|
||||||
"TodoItems": "Todos",
|
"TodoItems": "Todos",
|
||||||
"Dashboard": "Дашборд",
|
"Dashboard": "Дашборд",
|
||||||
"AllTime": "Все время"
|
"AllTime": "Все время",
|
||||||
|
"RelatedIssues": "Связанные процессы"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ loadMetadata(task.icon, {
|
|||||||
Kanban: `${icons}#kanban`,
|
Kanban: `${icons}#kanban`,
|
||||||
TodoCheck: `${icons}#todo-check`,
|
TodoCheck: `${icons}#todo-check`,
|
||||||
TodoUnCheck: `${icons}#todo-uncheck`,
|
TodoUnCheck: `${icons}#todo-uncheck`,
|
||||||
ManageStatuses: `${icons}#manage-statuses`,
|
ManageTemplates: `${icons}#manage-templates`,
|
||||||
TaskState: `${icons}#task-state`,
|
TaskState: `${icons}#task-state`,
|
||||||
Dashboard: `${icons}#dashboard`
|
Dashboard: `${icons}#dashboard`
|
||||||
})
|
})
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
>
|
>
|
||||||
<Label label={task.string.AllTime} />
|
<Label label={task.string.AllTime} />
|
||||||
</div>
|
</div>
|
||||||
{#each values as value, i}
|
{#each values as value}
|
||||||
<div
|
<div
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
<div class="description">
|
<div class="description">
|
||||||
<StyledTextBox
|
<StyledTextBox
|
||||||
bind:content={object.description}
|
bind:content={object.description}
|
||||||
placeholder={plugin.string.TaskDescriptionPlaceholder}
|
placeholder={plugin.string.DescriptionPlaceholder}
|
||||||
on:value={onChangeDescription}
|
on:value={onChangeDescription}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { getClient } from '@hcengineering/presentation'
|
||||||
|
import type { KanbanTemplate } from '@hcengineering/task'
|
||||||
|
import { Label } from '@hcengineering/ui'
|
||||||
|
|
||||||
|
export let value: KanbanTemplate
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const shortLabel = client.getHierarchy().getClass(value._class).shortLabel
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="label nowrap">
|
||||||
|
{#if shortLabel}
|
||||||
|
<Label label={shortLabel} />-{/if}{value.title}</span
|
||||||
|
>
|
@ -18,12 +18,20 @@
|
|||||||
import { Ref, Space, SortingOrder, Class } from '@hcengineering/core'
|
import { Ref, Space, SortingOrder, Class } from '@hcengineering/core'
|
||||||
import core from '@hcengineering/core'
|
import core from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import type { State, DoneStateTemplate, KanbanTemplate, StateTemplate, DoneState } from '@hcengineering/task'
|
import type {
|
||||||
|
State,
|
||||||
|
DoneStateTemplate,
|
||||||
|
KanbanTemplate,
|
||||||
|
StateTemplate,
|
||||||
|
DoneState,
|
||||||
|
KanbanTemplateSpace
|
||||||
|
} from '@hcengineering/task'
|
||||||
import task, { calcRank } from '@hcengineering/task'
|
import task, { calcRank } from '@hcengineering/task'
|
||||||
|
|
||||||
import StatesEditor from '../state/StatesEditor.svelte'
|
import StatesEditor from '../state/StatesEditor.svelte'
|
||||||
|
|
||||||
export let kanban: KanbanTemplate
|
export let kanban: KanbanTemplate
|
||||||
|
export let folder: KanbanTemplateSpace
|
||||||
|
|
||||||
let states: StateTemplate[] = []
|
let states: StateTemplate[] = []
|
||||||
let doneStates: DoneStateTemplate[] = []
|
let doneStates: DoneStateTemplate[] = []
|
||||||
@ -119,6 +127,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<StatesEditor
|
<StatesEditor
|
||||||
|
template={kanban}
|
||||||
|
space={folder}
|
||||||
{states}
|
{states}
|
||||||
{wonStates}
|
{wonStates}
|
||||||
{lostStates}
|
{lostStates}
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<DropdownLabels
|
<DropdownLabels
|
||||||
{focusIndex}
|
{focusIndex}
|
||||||
{items}
|
{items}
|
||||||
icon={task.icon.ManageStatuses}
|
icon={task.icon.ManageTemplates}
|
||||||
bind:selected={selectedItem}
|
bind:selected={selectedItem}
|
||||||
label={plugin.string.States}
|
label={plugin.string.States}
|
||||||
/>
|
/>
|
||||||
|
@ -103,7 +103,7 @@
|
|||||||
<svelte:fragment slot="title">
|
<svelte:fragment slot="title">
|
||||||
<div class="antiTitle icon-wrapper">
|
<div class="antiTitle icon-wrapper">
|
||||||
<div class="wrapped-icon">
|
<div class="wrapped-icon">
|
||||||
<Icon icon={task.icon.ManageStatuses} size={'small'} />
|
<Icon icon={task.icon.ManageTemplates} size={'small'} />
|
||||||
</div>
|
</div>
|
||||||
<div class="title-wrapper">
|
<div class="title-wrapper">
|
||||||
<span class="wrapped-title">
|
<span class="wrapped-title">
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Ref } from '@hcengineering/core'
|
import { Class, Ref } from '@hcengineering/core'
|
||||||
import { AttributeEditor, getClient } from '@hcengineering/presentation'
|
import { AttributeEditor, getClient } from '@hcengineering/presentation'
|
||||||
import type { DoneState, State } from '@hcengineering/task'
|
import type { DoneState, KanbanTemplate, KanbanTemplateSpace, State } from '@hcengineering/task'
|
||||||
import {
|
import {
|
||||||
CircleButton,
|
CircleButton,
|
||||||
IconAdd,
|
IconAdd,
|
||||||
@ -24,7 +24,8 @@
|
|||||||
Label,
|
Label,
|
||||||
showPopup,
|
showPopup,
|
||||||
getPlatformColor,
|
getPlatformColor,
|
||||||
eventToHTMLElement
|
eventToHTMLElement,
|
||||||
|
Component
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { ColorsPopup } from '@hcengineering/view-resources'
|
import { ColorsPopup } from '@hcengineering/view-resources'
|
||||||
@ -34,6 +35,8 @@
|
|||||||
import Won from '../icons/Won.svelte'
|
import Won from '../icons/Won.svelte'
|
||||||
import Lost from '../icons/Lost.svelte'
|
import Lost from '../icons/Lost.svelte'
|
||||||
|
|
||||||
|
export let template: KanbanTemplate | undefined = undefined
|
||||||
|
export let space: KanbanTemplateSpace | undefined = undefined
|
||||||
export let states: State[] = []
|
export let states: State[] = []
|
||||||
export let wonStates: DoneState[] = []
|
export let wonStates: DoneState[] = []
|
||||||
export let lostStates: DoneState[] = []
|
export let lostStates: DoneState[] = []
|
||||||
@ -85,6 +88,9 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if space?.editor}
|
||||||
|
<Component is={space.editor} 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
|
||||||
|
@ -32,6 +32,7 @@ import StatePresenter from './components/state/StatePresenter.svelte'
|
|||||||
import StatusTableView from './components/StatusTableView.svelte'
|
import StatusTableView from './components/StatusTableView.svelte'
|
||||||
import TaskHeader from './components/TaskHeader.svelte'
|
import TaskHeader from './components/TaskHeader.svelte'
|
||||||
import TaskPresenter from './components/TaskPresenter.svelte'
|
import TaskPresenter from './components/TaskPresenter.svelte'
|
||||||
|
import KanbanTemplatePresenter from './components/KanbanTemplatePresenter.svelte'
|
||||||
import TemplatesIcon from './components/TemplatesIcon.svelte'
|
import TemplatesIcon from './components/TemplatesIcon.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'
|
||||||
@ -51,6 +52,7 @@ export default async (): Promise<Resources> => ({
|
|||||||
component: {
|
component: {
|
||||||
CreateProject,
|
CreateProject,
|
||||||
TaskPresenter,
|
TaskPresenter,
|
||||||
|
KanbanTemplatePresenter,
|
||||||
EditIssue,
|
EditIssue,
|
||||||
KanbanCard,
|
KanbanCard,
|
||||||
Dashboard,
|
Dashboard,
|
||||||
|
@ -21,13 +21,14 @@ import { AnyComponent } from '@hcengineering/ui'
|
|||||||
export default mergeIds(taskId, task, {
|
export default mergeIds(taskId, task, {
|
||||||
string: {
|
string: {
|
||||||
CreateProject: '' as IntlString,
|
CreateProject: '' as IntlString,
|
||||||
|
Description: '' as IntlString,
|
||||||
|
DescriptionPlaceholder: '' as IntlString,
|
||||||
|
ShortDescription: '' as IntlString,
|
||||||
ProjectName: '' as IntlString,
|
ProjectName: '' as IntlString,
|
||||||
ProjectNamePlaceholder: '' as IntlString,
|
ProjectNamePlaceholder: '' as IntlString,
|
||||||
TaskCreateLabel: '' as IntlString,
|
TaskCreateLabel: '' as IntlString,
|
||||||
TaskAssignee: '' as IntlString,
|
TaskAssignee: '' as IntlString,
|
||||||
TaskNamePlaceholder: '' as IntlString,
|
TaskNamePlaceholder: '' as IntlString,
|
||||||
TaskDescription: '' as IntlString,
|
|
||||||
TaskDescriptionPlaceholder: '' as IntlString,
|
|
||||||
States: '' as IntlString,
|
States: '' as IntlString,
|
||||||
DoneStates: '' as IntlString,
|
DoneStates: '' as IntlString,
|
||||||
TodoDescriptionPlaceholder: '' as IntlString,
|
TodoDescriptionPlaceholder: '' as IntlString,
|
||||||
@ -67,6 +68,7 @@ export default mergeIds(taskId, task, {
|
|||||||
CantStatusDeleteError: '' as IntlString,
|
CantStatusDeleteError: '' as IntlString,
|
||||||
Archive: '' as IntlString,
|
Archive: '' as IntlString,
|
||||||
Unarchive: '' as IntlString,
|
Unarchive: '' as IntlString,
|
||||||
|
RelatedIssues: '' as IntlString,
|
||||||
|
|
||||||
Tasks: '' as IntlString,
|
Tasks: '' as IntlString,
|
||||||
Assigned: '' as IntlString,
|
Assigned: '' as IntlString,
|
||||||
|
@ -167,6 +167,8 @@ export interface LostStateTemplate extends DoneStateTemplate, LostState {}
|
|||||||
*/
|
*/
|
||||||
export interface KanbanTemplate extends Doc {
|
export interface KanbanTemplate extends Doc {
|
||||||
title: string
|
title: string
|
||||||
|
description?: string
|
||||||
|
shortDescription?: string
|
||||||
statesC: number
|
statesC: number
|
||||||
doneStatesC: number
|
doneStatesC: number
|
||||||
}
|
}
|
||||||
@ -178,6 +180,7 @@ export interface KanbanTemplateSpace extends Doc {
|
|||||||
name: IntlString
|
name: IntlString
|
||||||
description: IntlString
|
description: IntlString
|
||||||
icon: AnyComponent
|
icon: AnyComponent
|
||||||
|
editor?: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,7 +258,7 @@ const task = plugin(taskId, {
|
|||||||
Kanban: '' as Asset,
|
Kanban: '' as Asset,
|
||||||
TodoCheck: '' as Asset,
|
TodoCheck: '' as Asset,
|
||||||
TodoUnCheck: '' as Asset,
|
TodoUnCheck: '' as Asset,
|
||||||
ManageStatuses: '' as Asset,
|
ManageTemplates: '' as Asset,
|
||||||
TaskState: '' as Asset,
|
TaskState: '' as Asset,
|
||||||
Dashboard: '' as Asset
|
Dashboard: '' as Asset
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
"Templates": "Templates",
|
"Templates": "Text Templates",
|
||||||
"TemplatesHeader": "TEMPLATES",
|
"TemplatesHeader": "TEXT TEMPLATES",
|
||||||
"CreateTemplate": "CREATE TEMPLATE",
|
"CreateTemplate": "CREATE TEMPLATE",
|
||||||
"SaveTemplate": "Save template",
|
"SaveTemplate": "Save template",
|
||||||
"EditTemplate": "Edit template",
|
"EditTemplate": "Edit template",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"string": {
|
"string": {
|
||||||
"Cancel": "Отменить",
|
"Cancel": "Отменить",
|
||||||
"Templates": "Шаблоны",
|
"Templates": "Текстовые шаблоны",
|
||||||
"TemplatesHeader": "ШАБЛОНЫ",
|
"TemplatesHeader": "ТЕКСТОВЫЕ ШАБЛОНЫ",
|
||||||
"CreateTemplate": "СОЗДАТЬ ШАБЛОН",
|
"CreateTemplate": "СОЗДАТЬ ШАБЛОН",
|
||||||
"SaveTemplate": "Сохранить шаблон",
|
"SaveTemplate": "Сохранить шаблон",
|
||||||
"EditTemplate": "Редактировать шаблон",
|
"EditTemplate": "Редактировать шаблон",
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { Doc, DocumentQuery } from '@hcengineering/core'
|
||||||
|
import presentation, { createQuery } from '@hcengineering/presentation'
|
||||||
|
import { IssueTemplate } from '@hcengineering/tracker'
|
||||||
|
import { Label, Spinner } from '@hcengineering/ui'
|
||||||
|
import tracker from '../../../plugin'
|
||||||
|
import IssueTemplatePresenter from '../../templates/IssueTemplatePresenter.svelte'
|
||||||
|
|
||||||
|
export let object: Doc
|
||||||
|
|
||||||
|
let templates: IssueTemplate[] = []
|
||||||
|
|
||||||
|
let query: DocumentQuery<IssueTemplate>
|
||||||
|
$: query = { 'relations._id': object._id, 'relations._class': object._class }
|
||||||
|
|
||||||
|
const templatesQ = createQuery()
|
||||||
|
$: templatesQ.query(tracker.class.IssueTemplate, query, async (result) => (templates = result))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-1">
|
||||||
|
{#if templates !== undefined}
|
||||||
|
{#if templates.length > 0}
|
||||||
|
{#each templates as template}
|
||||||
|
<div class="flex-between row p-3">
|
||||||
|
<IssueTemplatePresenter value={template} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
<div class="p-1">
|
||||||
|
<Label label={presentation.string.NoMatchesFound} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<div class="flex-center pt-3">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.row {
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid var(--divider-color);
|
||||||
|
}
|
||||||
|
</style>
|
@ -15,7 +15,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
||||||
import { Employee } from '@hcengineering/contact'
|
import { Employee } from '@hcengineering/contact'
|
||||||
import { Data, generateId, Ref } from '@hcengineering/core'
|
import { Data, Doc, generateId, Ref } from '@hcengineering/core'
|
||||||
import { Card, getClient, KeyedAttribute, SpaceSelector } from '@hcengineering/presentation'
|
import { Card, getClient, KeyedAttribute, SpaceSelector } from '@hcengineering/presentation'
|
||||||
import tags, { TagElement } from '@hcengineering/tags'
|
import tags, { TagElement } from '@hcengineering/tags'
|
||||||
import { IssuePriority, IssueTemplate, Project, Sprint, Team } from '@hcengineering/tracker'
|
import { IssuePriority, IssueTemplate, Project, Sprint, Team } from '@hcengineering/tracker'
|
||||||
@ -35,6 +35,7 @@
|
|||||||
export let assignee: Ref<Employee> | null = null
|
export let assignee: Ref<Employee> | null = null
|
||||||
export let project: Ref<Project> | null = $activeProject ?? null
|
export let project: Ref<Project> | null = $activeProject ?? null
|
||||||
export let sprint: Ref<Sprint> | null = $activeSprint ?? null
|
export let sprint: Ref<Sprint> | null = $activeSprint ?? null
|
||||||
|
export let relatedTo: Doc | undefined
|
||||||
|
|
||||||
let labels: TagElement[] = []
|
let labels: TagElement[] = []
|
||||||
|
|
||||||
@ -50,7 +51,8 @@
|
|||||||
children: [],
|
children: [],
|
||||||
labels: [],
|
labels: [],
|
||||||
comments: 0,
|
comments: 0,
|
||||||
attachments: 0
|
attachments: 0,
|
||||||
|
relations: []
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
@ -92,7 +94,8 @@
|
|||||||
children: object.children,
|
children: object.children,
|
||||||
comments: 0,
|
comments: 0,
|
||||||
attachments: 0,
|
attachments: 0,
|
||||||
labels: labels.map((it) => it._id)
|
labels: labels.map((it) => it._id),
|
||||||
|
relations: relatedTo !== undefined ? [{ _id: relatedTo._id, _class: relatedTo._class }] : []
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.createDoc(tracker.class.IssueTemplate, _space, value, objectId)
|
await client.createDoc(tracker.class.IssueTemplate, _space, value, objectId)
|
||||||
|
@ -19,6 +19,7 @@ import { ObjectSearchResult } from '@hcengineering/presentation'
|
|||||||
import { Issue, Team } from '@hcengineering/tracker'
|
import { Issue, Team } from '@hcengineering/tracker'
|
||||||
import { showPopup } from '@hcengineering/ui'
|
import { showPopup } from '@hcengineering/ui'
|
||||||
import CreateIssue from './components/CreateIssue.svelte'
|
import CreateIssue from './components/CreateIssue.svelte'
|
||||||
|
import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte'
|
||||||
import Inbox from './components/inbox/Inbox.svelte'
|
import Inbox from './components/inbox/Inbox.svelte'
|
||||||
import Active from './components/issues/Active.svelte'
|
import Active from './components/issues/Active.svelte'
|
||||||
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
||||||
@ -83,6 +84,7 @@ import ReportedTimeEditor from './components/issues/timereport/ReportedTimeEdito
|
|||||||
import TimeSpendReport from './components/issues/timereport/TimeSpendReport.svelte'
|
import TimeSpendReport from './components/issues/timereport/TimeSpendReport.svelte'
|
||||||
|
|
||||||
import RelatedIssues from './components/issues/related/RelatedIssues.svelte'
|
import RelatedIssues from './components/issues/related/RelatedIssues.svelte'
|
||||||
|
import RelatedIssueTemplates from './components/issues/related/RelatedIssueTemplates.svelte'
|
||||||
|
|
||||||
import ProjectSelector from './components/ProjectSelector.svelte'
|
import ProjectSelector from './components/ProjectSelector.svelte'
|
||||||
|
|
||||||
@ -196,6 +198,7 @@ export default async (): Promise<Resources> => ({
|
|||||||
IssuePreview,
|
IssuePreview,
|
||||||
RelationsPopup,
|
RelationsPopup,
|
||||||
CreateIssue,
|
CreateIssue,
|
||||||
|
CreateIssueTemplate,
|
||||||
Sprints,
|
Sprints,
|
||||||
SprintPresenter,
|
SprintPresenter,
|
||||||
SprintStatusPresenter,
|
SprintStatusPresenter,
|
||||||
@ -208,6 +211,7 @@ export default async (): Promise<Resources> => ({
|
|||||||
SubIssuesSelector,
|
SubIssuesSelector,
|
||||||
GrowPresenter,
|
GrowPresenter,
|
||||||
RelatedIssues,
|
RelatedIssues,
|
||||||
|
RelatedIssueTemplates,
|
||||||
ProjectSelector,
|
ProjectSelector,
|
||||||
IssueTemplates,
|
IssueTemplates,
|
||||||
IssueTemplatePresenter,
|
IssueTemplatePresenter,
|
||||||
|
@ -258,6 +258,8 @@ export interface IssueTemplate extends Doc, IssueTemplateData {
|
|||||||
// Discussion stuff
|
// Discussion stuff
|
||||||
comments: number
|
comments: number
|
||||||
attachments?: number
|
attachments?: number
|
||||||
|
|
||||||
|
relations?: RelatedDocument[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -385,8 +387,10 @@ export default plugin(trackerId, {
|
|||||||
Tracker: '' as AnyComponent,
|
Tracker: '' as AnyComponent,
|
||||||
TrackerApp: '' as AnyComponent,
|
TrackerApp: '' as AnyComponent,
|
||||||
RelatedIssues: '' as AnyComponent,
|
RelatedIssues: '' as AnyComponent,
|
||||||
|
RelatedIssueTemplates: '' as AnyComponent,
|
||||||
EditIssue: '' as AnyComponent,
|
EditIssue: '' as AnyComponent,
|
||||||
CreateIssue: '' as AnyComponent
|
CreateIssue: '' as AnyComponent,
|
||||||
|
CreateIssueTemplate: '' as AnyComponent
|
||||||
},
|
},
|
||||||
issueStatusCategory: {
|
issueStatusCategory: {
|
||||||
Backlog: '' as Ref<IssueStatusCategory>,
|
Backlog: '' as Ref<IssueStatusCategory>,
|
||||||
|
@ -69,7 +69,7 @@ test.describe('contact tests', () => {
|
|||||||
// Click text=Edit template
|
// Click text=Edit template
|
||||||
})
|
})
|
||||||
|
|
||||||
test('manage-status-templates', async ({ page }) => {
|
test('manage-templates', async ({ page }) => {
|
||||||
// Go to http://localhost:8083/workbench%3Acomponent%3AWorkbenchApp/sanity-ws
|
// Go to http://localhost:8083/workbench%3Acomponent%3AWorkbenchApp/sanity-ws
|
||||||
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws`)
|
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws`)
|
||||||
// Click #profile-button
|
// Click #profile-button
|
||||||
@ -79,8 +79,8 @@ test.describe('contact tests', () => {
|
|||||||
await page.click('button:has-text("Settings")')
|
await page.click('button:has-text("Settings")')
|
||||||
// Click text=Workspace Notifications >> button
|
// Click text=Workspace Notifications >> button
|
||||||
await page.click('text=Workspace Notifications >> button')
|
await page.click('text=Workspace Notifications >> button')
|
||||||
// Click button:has-text("Manage Statuses")
|
// Click button:has-text("Manage Templates")
|
||||||
await page.click('text="Manage Statuses"')
|
await page.click('text="Manage Templates"')
|
||||||
// Click text=Vacancies
|
// Click text=Vacancies
|
||||||
await page.click('text=Vacancies')
|
await page.click('text=Vacancies')
|
||||||
// Click #create-template div
|
// Click #create-template div
|
||||||
|
Loading…
Reference in New Issue
Block a user