mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-11 21:11:57 +00:00
UBERF-4786 (#4285)
This commit is contained in:
parent
d35cd21f06
commit
d6291c7d70
@ -102,6 +102,7 @@ async function genVacansyApplicants (
|
|||||||
members: [],
|
members: [],
|
||||||
archived: false,
|
archived: false,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
|
classic: true,
|
||||||
// TODO: Fix me.
|
// TODO: Fix me.
|
||||||
statuses: states.map((s) => {
|
statuses: states.map((s) => {
|
||||||
return { _id: s, taskType: '' as Ref<TaskType> }
|
return { _id: s, taskType: '' as Ref<TaskType> }
|
||||||
|
@ -58,7 +58,8 @@ async function createDefaultProjectType (tx: TxOperations): Promise<Ref<ProjectT
|
|||||||
name: 'Default board',
|
name: 'Default board',
|
||||||
descriptor: board.descriptors.BoardType,
|
descriptor: board.descriptors.BoardType,
|
||||||
description: '',
|
description: '',
|
||||||
tasks: []
|
tasks: [],
|
||||||
|
classic: true
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,8 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
name: 'Default funnel',
|
name: 'Default funnel',
|
||||||
descriptor: lead.descriptors.FunnelType,
|
descriptor: lead.descriptors.FunnelType,
|
||||||
description: '',
|
description: '',
|
||||||
tasks: []
|
tasks: [],
|
||||||
|
classic: true
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,8 @@ async function createDefaultKanbanTemplate (tx: TxOperations): Promise<Ref<Proje
|
|||||||
name: 'Default vacancy',
|
name: 'Default vacancy',
|
||||||
descriptor: recruit.descriptors.VacancyType,
|
descriptor: recruit.descriptors.VacancyType,
|
||||||
description: '',
|
description: '',
|
||||||
tasks: []
|
tasks: [],
|
||||||
|
classic: true
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,8 @@ import {
|
|||||||
TypeString,
|
TypeString,
|
||||||
UX,
|
UX,
|
||||||
type Builder,
|
type Builder,
|
||||||
type MigrationClient
|
type MigrationClient,
|
||||||
|
ReadOnly
|
||||||
} from '@hcengineering/model'
|
} from '@hcengineering/model'
|
||||||
import attachment from '@hcengineering/model-attachment'
|
import attachment from '@hcengineering/model-attachment'
|
||||||
import chunter from '@hcengineering/model-chunter'
|
import chunter from '@hcengineering/model-chunter'
|
||||||
@ -106,6 +107,7 @@ export class TTask extends TAttachedDoc implements Task {
|
|||||||
|
|
||||||
@Prop(TypeRef(task.class.TaskType), task.string.TaskType)
|
@Prop(TypeRef(task.class.TaskType), task.string.TaskType)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
|
@ReadOnly()
|
||||||
kind!: Ref<TaskType>
|
kind!: Ref<TaskType>
|
||||||
|
|
||||||
@Prop(TypeString(), task.string.TaskNumber)
|
@Prop(TypeString(), task.string.TaskNumber)
|
||||||
@ -203,6 +205,9 @@ export class TProjectType extends TSpace implements ProjectType {
|
|||||||
|
|
||||||
@Prop(TypeRef(core.class.Class), getEmbeddedLabel('Target Class'))
|
@Prop(TypeRef(core.class.Class), getEmbeddedLabel('Target Class'))
|
||||||
targetClass!: Ref<Class<Project>>
|
targetClass!: Ref<Class<Project>>
|
||||||
|
|
||||||
|
@Prop(TypeBoolean(), getEmbeddedLabel('Classic'))
|
||||||
|
classic!: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.TaskType, core.class.Doc, DOMAIN_TASK)
|
@Model(task.class.TaskType, core.class.Doc, DOMAIN_TASK)
|
||||||
@ -506,7 +511,7 @@ export function createModel (builder: Builder): void {
|
|||||||
icon: task.icon.TaskState,
|
icon: task.icon.TaskState,
|
||||||
color: PaletteColorIndexes.Porpoise,
|
color: PaletteColorIndexes.Porpoise,
|
||||||
defaultStatusName: 'New state',
|
defaultStatusName: 'New state',
|
||||||
order: 0
|
order: 1
|
||||||
},
|
},
|
||||||
task.statusCategory.Active
|
task.statusCategory.Active
|
||||||
)
|
)
|
||||||
@ -520,7 +525,7 @@ export function createModel (builder: Builder): void {
|
|||||||
icon: task.icon.TaskState,
|
icon: task.icon.TaskState,
|
||||||
color: PaletteColorIndexes.Grass,
|
color: PaletteColorIndexes.Grass,
|
||||||
defaultStatusName: 'Won',
|
defaultStatusName: 'Won',
|
||||||
order: 0
|
order: 2
|
||||||
},
|
},
|
||||||
task.statusCategory.Won
|
task.statusCategory.Won
|
||||||
)
|
)
|
||||||
@ -534,7 +539,7 @@ export function createModel (builder: Builder): void {
|
|||||||
icon: task.icon.TaskState,
|
icon: task.icon.TaskState,
|
||||||
color: PaletteColorIndexes.Coin,
|
color: PaletteColorIndexes.Coin,
|
||||||
defaultStatusName: 'Lost',
|
defaultStatusName: 'Lost',
|
||||||
order: 0
|
order: 3
|
||||||
},
|
},
|
||||||
task.statusCategory.Lost
|
task.statusCategory.Lost
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { TxOperations, type Class, type Doc, type Ref } from '@hcengineering/core'
|
import { TxOperations, type Class, type Doc, type Ref, toIdMap } from '@hcengineering/core'
|
||||||
import {
|
import {
|
||||||
createOrUpdate,
|
createOrUpdate,
|
||||||
tryMigrate,
|
tryMigrate,
|
||||||
@ -39,6 +39,26 @@ export async function createSequence (tx: TxOperations, _class: Ref<Class<Doc>>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function reorderStates (_client: MigrationUpgradeClient): Promise<void> {
|
||||||
|
const client = new TxOperations(_client, core.account.System)
|
||||||
|
const states = toIdMap(await client.findAll(core.class.Status, {}))
|
||||||
|
const order = [
|
||||||
|
task.statusCategory.UnStarted,
|
||||||
|
task.statusCategory.Active,
|
||||||
|
task.statusCategory.Won,
|
||||||
|
task.statusCategory.Lost
|
||||||
|
]
|
||||||
|
const taskTypes = await client.findAll(task.class.TaskType, {})
|
||||||
|
for (const taskType of taskTypes) {
|
||||||
|
const statuses = [...taskType.statuses].sort((a, b) => {
|
||||||
|
const aIndex = order.indexOf(states.get(a)?.category ?? task.statusCategory.UnStarted)
|
||||||
|
const bIndex = order.indexOf(states.get(b)?.category ?? task.statusCategory.UnStarted)
|
||||||
|
return aIndex - bIndex
|
||||||
|
})
|
||||||
|
await client.diffUpdate(taskType, { statuses })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function createDefaultSequence (tx: TxOperations): Promise<void> {
|
async function createDefaultSequence (tx: TxOperations): Promise<void> {
|
||||||
const current = await tx.findOne(core.class.Space, {
|
const current = await tx.findOne(core.class.Space, {
|
||||||
_id: task.space.Sequence
|
_id: task.space.Sequence
|
||||||
@ -92,6 +112,18 @@ export const taskOperation: MigrateOperation = {
|
|||||||
func: async (client) => {
|
func: async (client) => {
|
||||||
await client.update(DOMAIN_SPACE, { space: core.space.Model }, { space: core.space.Space })
|
await client.update(DOMAIN_SPACE, { space: core.space.Model }, { space: core.space.Space })
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: 'classicProjectTypes',
|
||||||
|
func: async (client) => {
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_SPACE,
|
||||||
|
{ _class: task.class.ProjectType, classic: { $exists: false } },
|
||||||
|
{
|
||||||
|
classic: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
@ -113,6 +145,11 @@ export const taskOperation: MigrateOperation = {
|
|||||||
task.category.TaskTag
|
task.category.TaskTag
|
||||||
)
|
)
|
||||||
|
|
||||||
await tryUpgrade(client, taskId, [])
|
await tryUpgrade(client, taskId, [
|
||||||
|
{
|
||||||
|
state: 'reorderStates',
|
||||||
|
func: reorderStates
|
||||||
|
}
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,8 @@ async function createDefaultProject (tx: TxOperations): Promise<void> {
|
|||||||
name: 'Classic project',
|
name: 'Classic project',
|
||||||
descriptor: tracker.descriptors.ProjectType,
|
descriptor: tracker.descriptors.ProjectType,
|
||||||
description: '',
|
description: '',
|
||||||
tasks: []
|
tasks: [],
|
||||||
|
classic: true
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -88,7 +89,8 @@ async function createDefaultProject (tx: TxOperations): Promise<void> {
|
|||||||
name: 'Base project',
|
name: 'Base project',
|
||||||
descriptor: tracker.descriptors.ProjectType,
|
descriptor: tracker.descriptors.ProjectType,
|
||||||
description: '',
|
description: '',
|
||||||
tasks: []
|
tasks: [],
|
||||||
|
classic: false
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,8 @@
|
|||||||
"StatusChange": "Status changed",
|
"StatusChange": "Status changed",
|
||||||
"TaskCreated": "Task created",
|
"TaskCreated": "Task created",
|
||||||
"TaskType": "Task type",
|
"TaskType": "Task type",
|
||||||
"ManageProjects": "Project types"
|
"ManageProjects": "Project types",
|
||||||
|
"CreateProjectType": "Create project type",
|
||||||
|
"ClassicProject": "Classic project"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -81,6 +81,8 @@
|
|||||||
"StatusChange": "Статус изменен",
|
"StatusChange": "Статус изменен",
|
||||||
"TaskCreated": "Создана задача",
|
"TaskCreated": "Создана задача",
|
||||||
"TaskType": "Тип задачи",
|
"TaskType": "Тип задачи",
|
||||||
"ManageProjects": "Управление проектами"
|
"ManageProjects": "Управление проектами",
|
||||||
|
"CreateProjectType": "Создать тип проекта",
|
||||||
|
"ClassicProject": "Классический проект"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,17 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Attribute, Class, IdMap, Ref, Status, generateId } from '@hcengineering/core'
|
import { Class, IdMap, Ref, Status, generateId } from '@hcengineering/core'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import { DocPopup, createQuery, getClient } from '@hcengineering/presentation'
|
import { DocPopup, getClient } from '@hcengineering/presentation'
|
||||||
import { Project, ProjectType, Task, getStates } from '@hcengineering/task'
|
import { Task, TaskType } from '@hcengineering/task'
|
||||||
import { ObjectPresenter, statusStore } from '@hcengineering/view-resources'
|
import { ObjectPresenter, statusStore } from '@hcengineering/view-resources'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { typeStore } from '..'
|
import { taskTypeStore } from '..'
|
||||||
import task from '../plugin'
|
|
||||||
|
|
||||||
export let value: Task | Task[]
|
export let value: Task | Task[]
|
||||||
export let width: 'medium' | 'large' | 'full' = 'medium'
|
export let width: 'medium' | 'large' | 'full' = 'medium'
|
||||||
export let placeholder: IntlString
|
export let placeholder: IntlString
|
||||||
export let ofAttribute: Ref<Attribute<Status>>
|
|
||||||
export let _class: Ref<Class<Status>>
|
export let _class: Ref<Class<Status>>
|
||||||
export let embedded: boolean = false
|
export let embedded: boolean = false
|
||||||
|
|
||||||
@ -43,35 +41,26 @@
|
|||||||
: undefined
|
: undefined
|
||||||
: value.status
|
: value.status
|
||||||
|
|
||||||
$: _space = Array.isArray(value)
|
$: kind = Array.isArray(value)
|
||||||
? value.every((v) => v.space === (value as Array<Task>)[0].space)
|
? value.every((v) => v.kind === (value as Array<Task>)[0].kind)
|
||||||
? value[0].space
|
? value[0].kind
|
||||||
: undefined
|
: undefined
|
||||||
: value.space
|
: value.kind
|
||||||
|
|
||||||
let project: Project | undefined
|
function updateStatuses (taskTypes: IdMap<TaskType>, store: IdMap<Status>, kind: Ref<TaskType> | undefined): void {
|
||||||
|
if (kind === undefined) {
|
||||||
const query = createQuery()
|
statuses = []
|
||||||
$: _space
|
|
||||||
? query.query(task.class.Project, { _id: _space as Ref<Project> }, (res) => {
|
|
||||||
project = res[0]
|
|
||||||
})
|
|
||||||
: (project = undefined)
|
|
||||||
|
|
||||||
function updateStatuses (
|
|
||||||
space: Project | undefined,
|
|
||||||
types: IdMap<ProjectType>,
|
|
||||||
store: IdMap<Status>,
|
|
||||||
allStatuses: Status[]
|
|
||||||
): void {
|
|
||||||
if (space === undefined) {
|
|
||||||
statuses = allStatuses.filter((p) => p.ofAttribute === ofAttribute)
|
|
||||||
} else {
|
} else {
|
||||||
statuses = getStates(space, types, store)
|
if (kind !== undefined) {
|
||||||
|
const type = taskTypes.get(kind)
|
||||||
|
if (type !== undefined) {
|
||||||
|
statuses = type.statuses.map((p) => store.get(p)).filter((p) => p !== undefined) as Status[]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: updateStatuses(project, $typeStore, $statusStore.byId, $statusStore.array)
|
$: updateStatuses($taskTypeStore, $statusStore.byId, kind)
|
||||||
|
|
||||||
let statuses: Status[] = []
|
let statuses: Status[] = []
|
||||||
</script>
|
</script>
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
<!--
|
||||||
|
// 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Ref, generateId } from '@hcengineering/core'
|
||||||
|
import { Card, getClient } from '@hcengineering/presentation'
|
||||||
|
import { ProjectTypeDescriptor, createProjectType } from '@hcengineering/task'
|
||||||
|
import { DropdownLabelsIntl, EditBox, ToggleWithLabel } from '@hcengineering/ui'
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import task from '../../plugin'
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
let name: string = ''
|
||||||
|
let classic: boolean = true
|
||||||
|
|
||||||
|
let descriptor: ProjectTypeDescriptor | undefined = undefined
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
async function createType (): Promise<void> {
|
||||||
|
if (descriptor === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await createProjectType(
|
||||||
|
client,
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
descriptor: descriptor._id,
|
||||||
|
description: '',
|
||||||
|
tasks: [],
|
||||||
|
classic
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
generateId()
|
||||||
|
)
|
||||||
|
dispatch('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
const descriptors = client.getModel().findAllSync(task.class.ProjectTypeDescriptor, {})
|
||||||
|
const items = descriptors.map((it) => ({
|
||||||
|
label: it.name,
|
||||||
|
id: it._id
|
||||||
|
}))
|
||||||
|
|
||||||
|
function selectType (evt: CustomEvent<Ref<ProjectTypeDescriptor>>): void {
|
||||||
|
descriptor = descriptors.find((it) => it._id === evt.detail)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
label={task.string.CreateProjectType}
|
||||||
|
canSave={name.trim().length > 0 && descriptor !== undefined}
|
||||||
|
okAction={createType}
|
||||||
|
on:close={() => {
|
||||||
|
dispatch('close')
|
||||||
|
}}
|
||||||
|
on:changeContent
|
||||||
|
>
|
||||||
|
<div class="flex-col flex-gap-2">
|
||||||
|
<EditBox bind:value={name} placeholder={task.string.ProjectType} />
|
||||||
|
<DropdownLabelsIntl {items} on:selected={selectType} />
|
||||||
|
<ToggleWithLabel label={task.string.ClassicProject} bind:on={classic} />
|
||||||
|
</div>
|
||||||
|
</Card>
|
@ -14,46 +14,12 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { generateId } from '@hcengineering/core'
|
import { Button, IconAdd, showPopup } from '@hcengineering/ui'
|
||||||
import { Button, IconAdd, Menu, getEventPopupPositionElement, showPopup } from '@hcengineering/ui'
|
import CreateProjectType from './CreateProjectType.svelte'
|
||||||
|
|
||||||
import { translate } from '@hcengineering/platform'
|
function open () {
|
||||||
import { getClient } from '@hcengineering/presentation'
|
showPopup(CreateProjectType, {}, 'top')
|
||||||
import task, { ProjectTypeDescriptor, createProjectType } from '@hcengineering/task'
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
async function createType (descriptor: ProjectTypeDescriptor): Promise<void> {
|
|
||||||
const descriptorName = await translate(descriptor.name, {})
|
|
||||||
|
|
||||||
await createProjectType(
|
|
||||||
client,
|
|
||||||
{
|
|
||||||
name: `New ${descriptorName} project type`,
|
|
||||||
descriptor: descriptor._id,
|
|
||||||
description: '',
|
|
||||||
tasks: []
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
generateId()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function chooseProjectType (evt: MouseEvent): Promise<void> {
|
|
||||||
const descriptors = client.getModel().findAllSync(task.class.ProjectTypeDescriptor, {})
|
|
||||||
showPopup(
|
|
||||||
Menu,
|
|
||||||
{
|
|
||||||
actions: descriptors.map((it) => ({
|
|
||||||
label: it.name,
|
|
||||||
action: () => {
|
|
||||||
void createType(it)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
getEventPopupPositionElement(evt)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Button id="new-project-type" icon={IconAdd} kind={'link'} size="small" on:click={chooseProjectType} />
|
<Button id="new-project-type" icon={IconAdd} kind={'link'} size="small" on:click={open} />
|
||||||
|
@ -75,7 +75,9 @@ export default mergeIds(taskId, task, {
|
|||||||
StatusPopupTitle: '' as IntlString,
|
StatusPopupTitle: '' as IntlString,
|
||||||
NameAlreadyExists: '' as IntlString,
|
NameAlreadyExists: '' as IntlString,
|
||||||
StatusChange: '' as IntlString,
|
StatusChange: '' as IntlString,
|
||||||
TaskCreated: '' as IntlString
|
TaskCreated: '' as IntlString,
|
||||||
|
CreateProjectType: '' as IntlString,
|
||||||
|
ClassicProject: '' as IntlString
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
AssigneeRequired: '' as IntlString
|
AssigneeRequired: '' as IntlString
|
||||||
|
@ -173,6 +173,9 @@ export interface ProjectType extends Space {
|
|||||||
|
|
||||||
// A mixin for project
|
// A mixin for project
|
||||||
targetClass: Ref<Class<Project>>
|
targetClass: Ref<Class<Project>>
|
||||||
|
|
||||||
|
// disable automation workflow
|
||||||
|
classic: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,7 +255,8 @@ export async function createProjectType (
|
|||||||
members: [],
|
members: [],
|
||||||
archived: false,
|
archived: false,
|
||||||
statuses: calculateStatuses({ tasks: _tasks, statuses: [] }, tasksData, []),
|
statuses: calculateStatuses({ tasks: _tasks, statuses: [] }, tasksData, []),
|
||||||
targetClass: targetProjectClassId
|
targetClass: targetProjectClassId,
|
||||||
|
classic: data.classic
|
||||||
},
|
},
|
||||||
_id
|
_id
|
||||||
)
|
)
|
||||||
|
@ -86,10 +86,10 @@ test.describe('contact tests', () => {
|
|||||||
await page.getByRole('button', { name: 'Notifications' }).click()
|
await page.getByRole('button', { name: 'Notifications' }).click()
|
||||||
// Click text=Vacancies
|
// Click text=Vacancies
|
||||||
await page.locator('#new-project-type').click()
|
await page.locator('#new-project-type').click()
|
||||||
await page.getByRole('button', { name: 'Recruiting', exact: true }).click()
|
|
||||||
await page.locator('#navGroup-statuses').getByText('New Recruiting project type').first().click()
|
|
||||||
|
|
||||||
// TODO: Need rework.
|
// TODO: Need rework.
|
||||||
|
// await page.getByRole('button', { name: 'Recruiting', exact: true }).click()
|
||||||
|
// await page.locator('#navGroup-statuses').getByText('New Recruiting project type').first().click()
|
||||||
|
|
||||||
// // Click #create-template div
|
// // Click #create-template div
|
||||||
// await page.click('#create-template div')
|
// await page.click('#create-template div')
|
||||||
// const tid = 'template-' + generateId()
|
// const tid = 'template-' + generateId()
|
||||||
|
Loading…
Reference in New Issue
Block a user