mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-25 20:42:56 +03:00
Add members to space type for easy management members, and add autojo… (#5612)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
fa3df9981d
commit
8f52663a11
@ -75,8 +75,7 @@ export class TSpace extends TDoc implements Space {
|
|||||||
@Prop(ArrOf(TypeRef(core.class.Account)), core.string.Owners)
|
@Prop(ArrOf(TypeRef(core.class.Account)), core.string.Owners)
|
||||||
owners?: Ref<Account>[]
|
owners?: Ref<Account>[]
|
||||||
|
|
||||||
@Prop(TypeBoolean(), getEmbeddedLabel('Auto-Join members'))
|
@Prop(TypeBoolean(), core.string.AutoJoin)
|
||||||
@Hidden() // let's hide it for now
|
|
||||||
autoJoin?: boolean
|
autoJoin?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +118,12 @@ export class TSpaceType extends TDoc implements SpaceType {
|
|||||||
|
|
||||||
@Prop(Collection(core.class.Role), core.string.Roles)
|
@Prop(Collection(core.class.Role), core.string.Roles)
|
||||||
roles!: CollectionSize<Role>
|
roles!: CollectionSize<Role>
|
||||||
|
|
||||||
|
@Prop(ArrOf(TypeRef(core.class.Account)), core.string.Members)
|
||||||
|
members!: Arr<Ref<Account>>
|
||||||
|
|
||||||
|
@Prop(TypeBoolean(), core.string.AutoJoin)
|
||||||
|
autoJoin?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(core.class.Role, core.class.AttachedDoc, DOMAIN_MODEL)
|
@Model(core.class.Role, core.class.AttachedDoc, DOMAIN_MODEL)
|
||||||
|
@ -89,6 +89,14 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
|
trigger: serverContact.trigger.OnSpaceTypeMembers,
|
||||||
|
txMatch: {
|
||||||
|
objectClass: core.class.SpaceType,
|
||||||
|
_class: core.class.TxUpdateDoc
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
builder.mixin(
|
builder.mixin(
|
||||||
contact.templateField.CurrentEmployeeName,
|
contact.templateField.CurrentEmployeeName,
|
||||||
templates.class.TemplateField,
|
templates.class.TemplateField,
|
||||||
|
@ -58,6 +58,8 @@
|
|||||||
"DeleteObjectDescription": "Grants users ability to delete objects in the space",
|
"DeleteObjectDescription": "Grants users ability to delete objects in the space",
|
||||||
"ForbidDeleteObjectDescription": "Forbid users deleting objects in the space",
|
"ForbidDeleteObjectDescription": "Forbid users deleting objects in the space",
|
||||||
"UpdateSpaceDescription": "Grants users ability to update the space",
|
"UpdateSpaceDescription": "Grants users ability to update the space",
|
||||||
"ArchiveSpaceDescription": "Grants users ability to archive the space"
|
"ArchiveSpaceDescription": "Grants users ability to archive the space",
|
||||||
|
"AutoJoin": "Auto join",
|
||||||
|
"AutoJoinDescr": "Automatically join new employees to this space"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,21 @@
|
|||||||
"StatusCategory": "Categoría de estado",
|
"StatusCategory": "Categoría de estado",
|
||||||
"Account": "Cuenta",
|
"Account": "Cuenta",
|
||||||
"Rank": "Rango",
|
"Rank": "Rango",
|
||||||
"Owners": "Propietarios"
|
"Owners": "Propietarios",
|
||||||
|
"Permission": "Permiso",
|
||||||
|
"CreateObject": "Crear objeto",
|
||||||
|
"UpdateObject": "Actualizar objeto",
|
||||||
|
"DeleteObject": "Eliminar objeto",
|
||||||
|
"ForbidDeleteObject": "Prohibir eliminar objeto",
|
||||||
|
"UpdateSpace": "Actualizar espacio",
|
||||||
|
"ArchiveSpace": "Archivar espacio",
|
||||||
|
"CreateObjectDescription": "Concede a los usuarios la capacidad de crear objetos en el espacio",
|
||||||
|
"UpdateObjectDescription": "Concede a los usuarios la capacidad de actualizar objetos en el espacio",
|
||||||
|
"DeleteObjectDescription": "Concede a los usuarios la capacidad de eliminar objetos en el espacio",
|
||||||
|
"ForbidDeleteObjectDescription": "Prohíbe a los usuarios eliminar objetos en el espacio",
|
||||||
|
"UpdateSpaceDescription": "Concede a los usuarios la capacidad de actualizar el espacio",
|
||||||
|
"ArchiveSpaceDescription": "Concede a los usuarios la capacidad de archivar el espacio",
|
||||||
|
"AutoJoin": "Auto unirse",
|
||||||
|
"AutoJoinDescr": "Unirse automáticamente a los nuevos empleados a este espacio"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,21 @@
|
|||||||
"StatusCategory": "Categoria de estado",
|
"StatusCategory": "Categoria de estado",
|
||||||
"Account": "Conta",
|
"Account": "Conta",
|
||||||
"Rank": "Ranking",
|
"Rank": "Ranking",
|
||||||
"Owners": "Proprietários"
|
"Owners": "Proprietários",
|
||||||
|
"Permission": "Permissão",
|
||||||
|
"CreateObject": "Criar objeto",
|
||||||
|
"UpdateObject": "Atualizar objeto",
|
||||||
|
"DeleteObject": "Apagar objeto",
|
||||||
|
"ForbidDeleteObject": "Proibir apagar objeto",
|
||||||
|
"UpdateSpace": "Atualizar espaço",
|
||||||
|
"ArchiveSpace": "Arquivar espaço",
|
||||||
|
"CreateObjectDescription": "Concede aos usuários a capacidade de criar objetos no espaço",
|
||||||
|
"UpdateObjectDescription": "Concede aos usuários a capacidade de atualizar objetos no espaço",
|
||||||
|
"DeleteObjectDescription": "Concede aos usuários a capacidade de apagar objetos no espaço",
|
||||||
|
"ForbidDeleteObjectDescription": "Proíbe aos usuários a capacidade de apagar objetos no espaço",
|
||||||
|
"UpdateSpaceDescription": "Concede aos usuários a capacidade de atualizar o espaço",
|
||||||
|
"ArchiveSpaceDescription": "Concede aos usuários a capacidade de arquivar o espaço",
|
||||||
|
"AutoJoin": "Auto adesão",
|
||||||
|
"AutoJoinDescr": "Adesão automática de novos funcionários a este espaço"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@
|
|||||||
"DeleteObjectDescription": "Дает пользователям разрешение удалять объекты в пространстве",
|
"DeleteObjectDescription": "Дает пользователям разрешение удалять объекты в пространстве",
|
||||||
"ForbidDeleteObjectDescription": "Запрещает пользователям удалять объекты в пространстве",
|
"ForbidDeleteObjectDescription": "Запрещает пользователям удалять объекты в пространстве",
|
||||||
"UpdateSpaceDescription": "Дает пользователям разрешение обновлять пространство",
|
"UpdateSpaceDescription": "Дает пользователям разрешение обновлять пространство",
|
||||||
"ArchiveSpaceDescription": "Дает пользователям разрешение архивировать пространство"
|
"ArchiveSpaceDescription": "Дает пользователям разрешение архивировать пространство",
|
||||||
|
"AutoJoin": "Автоприсоединение",
|
||||||
|
"AutoJoinDescr": "Автоматически присоединять новых сотрудников к этому пространству"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,6 +401,8 @@ export interface SpaceType extends Doc {
|
|||||||
name: string
|
name: string
|
||||||
shortDescription?: string
|
shortDescription?: string
|
||||||
descriptor: Ref<SpaceTypeDescriptor>
|
descriptor: Ref<SpaceTypeDescriptor>
|
||||||
|
members?: Ref<Account>[] // this members will be added automatically to new space, also change this fiield will affect existing spaces
|
||||||
|
autoJoin?: boolean // if true, all new users will be added to space automatically
|
||||||
targetClass: Ref<Class<Space>> // A dynamic mixin for Spaces to hold custom attributes and roles assignment of the space type
|
targetClass: Ref<Class<Space>> // A dynamic mixin for Spaces to hold custom attributes and roles assignment of the space type
|
||||||
roles: CollectionSize<Role>
|
roles: CollectionSize<Role>
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,9 @@ export default plugin(coreId, {
|
|||||||
DeleteObjectDescription: '' as IntlString,
|
DeleteObjectDescription: '' as IntlString,
|
||||||
ForbidDeleteObjectDescription: '' as IntlString,
|
ForbidDeleteObjectDescription: '' as IntlString,
|
||||||
UpdateSpaceDescription: '' as IntlString,
|
UpdateSpaceDescription: '' as IntlString,
|
||||||
ArchiveSpaceDescription: '' as IntlString
|
ArchiveSpaceDescription: '' as IntlString,
|
||||||
|
AutoJoin: '' as IntlString,
|
||||||
|
AutoJoinDescr: '' as IntlString
|
||||||
},
|
},
|
||||||
descriptor: {
|
descriptor: {
|
||||||
SpacesType: '' as Ref<SpaceTypeDescriptor>
|
SpacesType: '' as Ref<SpaceTypeDescriptor>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import { LabelAndProps } from '../types'
|
import { LabelAndProps } from '../types'
|
||||||
import { tooltip } from '../tooltips'
|
import { tooltip } from '../tooltips'
|
||||||
|
|
||||||
|
export let id: string | undefined = undefined
|
||||||
export let on: boolean = false
|
export let on: boolean = false
|
||||||
export let disabled: boolean = false
|
export let disabled: boolean = false
|
||||||
export let showTooltip: LabelAndProps | undefined = undefined
|
export let showTooltip: LabelAndProps | undefined = undefined
|
||||||
@ -24,7 +25,7 @@
|
|||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label class="toggle" use:tooltip={showTooltip}>
|
<label {id} class="toggle" use:tooltip={showTooltip} class:disabled>
|
||||||
<input
|
<input
|
||||||
class="chBox"
|
class="chBox"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -47,6 +48,12 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
.chBox {
|
.chBox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
@ -67,9 +74,6 @@
|
|||||||
background: var(--theme-toggle-on-sw-color);
|
background: var(--theme-toggle-on-sw-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:not(:disabled) + .toggle-switch {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
&:disabled + .toggle-switch {
|
&:disabled + .toggle-switch {
|
||||||
filter: grayscale(70%);
|
filter: grayscale(70%);
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
export let label: IntlString
|
export let label: IntlString
|
||||||
export let value: Ref<Account>[]
|
export let value: Ref<Account>[]
|
||||||
export let onChange: ((refs: Ref<Account>[]) => void) | undefined
|
export let onChange: ((refs: Ref<Account>[]) => void | Promise<void>) | undefined
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
export let kind: ButtonKind = 'link'
|
export let kind: ButtonKind = 'link'
|
||||||
export let size: ButtonSize = 'large'
|
export let size: ButtonSize = 'large'
|
||||||
|
@ -51,7 +51,6 @@ export default mergeIds(contactId, contact, {
|
|||||||
CopyToClipboard: '' as IntlString,
|
CopyToClipboard: '' as IntlString,
|
||||||
ViewFullProfile: '' as IntlString,
|
ViewFullProfile: '' as IntlString,
|
||||||
Member: '' as IntlString,
|
Member: '' as IntlString,
|
||||||
Members: '' as IntlString,
|
|
||||||
NoMembers: '' as IntlString,
|
NoMembers: '' as IntlString,
|
||||||
AddMember: '' as IntlString,
|
AddMember: '' as IntlString,
|
||||||
KickEmployee: '' as IntlString,
|
KickEmployee: '' as IntlString,
|
||||||
|
@ -263,7 +263,8 @@ export const contactPlugin = plugin(contactId, {
|
|||||||
Position: '' as IntlString,
|
Position: '' as IntlString,
|
||||||
For: '' as IntlString,
|
For: '' as IntlString,
|
||||||
SelectUsers: '' as IntlString,
|
SelectUsers: '' as IntlString,
|
||||||
AddGuest: '' as IntlString
|
AddGuest: '' as IntlString,
|
||||||
|
Members: '' as IntlString
|
||||||
},
|
},
|
||||||
viewlet: {
|
viewlet: {
|
||||||
TableMember: '' as Ref<Viewlet>,
|
TableMember: '' as Ref<Viewlet>,
|
||||||
|
@ -118,6 +118,7 @@
|
|||||||
private: isPrivate,
|
private: isPrivate,
|
||||||
members,
|
members,
|
||||||
owners,
|
owners,
|
||||||
|
autoJoin,
|
||||||
archived: false,
|
archived: false,
|
||||||
icon,
|
icon,
|
||||||
color
|
color
|
||||||
@ -146,6 +147,9 @@
|
|||||||
if (teamspaceData.color !== teamspace?.color) {
|
if (teamspaceData.color !== teamspace?.color) {
|
||||||
update.color = teamspaceData.color
|
update.color = teamspaceData.color
|
||||||
}
|
}
|
||||||
|
if (teamspaceData.autoJoin !== teamspace?.autoJoin) {
|
||||||
|
update.autoJoin = teamspaceData.autoJoin
|
||||||
|
}
|
||||||
if (teamspaceData.members.length !== teamspace?.members.length) {
|
if (teamspaceData.members.length !== teamspace?.members.length) {
|
||||||
update.members = teamspaceData.members
|
update.members = teamspaceData.members
|
||||||
} else {
|
} else {
|
||||||
@ -236,6 +240,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
||||||
|
membersChanged = true
|
||||||
// If a member was removed we need to remove it from any roles assignments as well
|
// If a member was removed we need to remove it from any roles assignments as well
|
||||||
const newMembersSet = new Set(newMembers)
|
const newMembersSet = new Set(newMembers)
|
||||||
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
||||||
@ -257,6 +262,21 @@
|
|||||||
rolesAssignment[roleId] = newMembers
|
rolesAssignment[roleId] = newMembers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let autoJoin = teamspace?.autoJoin ?? spaceType?.autoJoin ?? false
|
||||||
|
|
||||||
|
$: setDefaultMembers(spaceType)
|
||||||
|
|
||||||
|
let membersChanged: boolean = false
|
||||||
|
|
||||||
|
function setDefaultMembers (typeType: SpaceType | undefined): void {
|
||||||
|
if (typeType === undefined) return
|
||||||
|
if (membersChanged) return
|
||||||
|
if (teamspace !== undefined) return
|
||||||
|
autoJoin = typeType.autoJoin ?? false
|
||||||
|
if (typeType.members === undefined || typeType.members.length === 0) return
|
||||||
|
members = typeType.members
|
||||||
|
}
|
||||||
|
|
||||||
$: canSave =
|
$: canSave =
|
||||||
name.trim().length > 0 &&
|
name.trim().length > 0 &&
|
||||||
!(members.length === 0 && isPrivate) &&
|
!(members.length === 0 && isPrivate) &&
|
||||||
@ -366,7 +386,7 @@
|
|||||||
<Label label={presentation.string.MakePrivate} />
|
<Label label={presentation.string.MakePrivate} />
|
||||||
<span><Label label={presentation.string.MakePrivateDescription} /></span>
|
<span><Label label={presentation.string.MakePrivateDescription} /></span>
|
||||||
</div>
|
</div>
|
||||||
<Toggle bind:on={isPrivate} disabled={!isPrivate && members.length === 0} />
|
<Toggle id={'teamspace-private'} bind:on={isPrivate} disabled={!isPrivate && members.length === 0} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
@ -383,6 +403,14 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="antiGrid-row">
|
||||||
|
<div class="antiGrid-row__header withDesciption">
|
||||||
|
<Label label={core.string.AutoJoin} />
|
||||||
|
<span><Label label={core.string.AutoJoinDescr} /></span>
|
||||||
|
</div>
|
||||||
|
<Toggle bind:on={autoJoin} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{#each roles as role}
|
{#each roles as role}
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
<div class="antiGrid-row__header">
|
<div class="antiGrid-row__header">
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
import lead, { Funnel } from '@hcengineering/lead'
|
import lead, { Funnel } from '@hcengineering/lead'
|
||||||
import presentation, { getClient, SpaceCreateCard } from '@hcengineering/presentation'
|
import presentation, { getClient, SpaceCreateCard } from '@hcengineering/presentation'
|
||||||
import task, { ProjectType } from '@hcengineering/task'
|
import task, { ProjectType } from '@hcengineering/task'
|
||||||
import ui, { Component, EditBox, Grid, Label, ToggleWithLabel } from '@hcengineering/ui'
|
import ui, { Component, EditBox, Label, Toggle, ToggleWithLabel } from '@hcengineering/ui'
|
||||||
import { deepEqual } from 'fast-equals'
|
import { deepEqual } from 'fast-equals'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
|
||||||
@ -99,6 +99,7 @@
|
|||||||
private: isPrivate,
|
private: isPrivate,
|
||||||
archived: false,
|
archived: false,
|
||||||
members,
|
members,
|
||||||
|
autoJoin,
|
||||||
owners,
|
owners,
|
||||||
type: typeId
|
type: typeId
|
||||||
})
|
})
|
||||||
@ -111,7 +112,11 @@
|
|||||||
if (isNew) {
|
if (isNew) {
|
||||||
await createFunnel()
|
await createFunnel()
|
||||||
} else if (funnel !== undefined && spaceType?.targetClass !== undefined) {
|
} else if (funnel !== undefined && spaceType?.targetClass !== undefined) {
|
||||||
await client.diffUpdate<Funnel>(funnel, { name, description, members, owners, private: isPrivate }, Date.now())
|
await client.diffUpdate<Funnel>(
|
||||||
|
funnel,
|
||||||
|
{ name, description, members, owners, private: isPrivate, autoJoin },
|
||||||
|
Date.now()
|
||||||
|
)
|
||||||
|
|
||||||
if (!deepEqual(rolesAssignment, getRolesAssignment())) {
|
if (!deepEqual(rolesAssignment, getRolesAssignment())) {
|
||||||
await client.updateMixin(
|
await client.updateMixin(
|
||||||
@ -133,6 +138,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
||||||
|
membersChanged = true
|
||||||
// If a member was removed we need to remove it from any roles assignments as well
|
// If a member was removed we need to remove it from any roles assignments as well
|
||||||
const newMembersSet = new Set(newMembers)
|
const newMembersSet = new Set(newMembers)
|
||||||
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
||||||
@ -156,6 +162,21 @@
|
|||||||
|
|
||||||
$: canSave =
|
$: canSave =
|
||||||
name.trim().length > 0 && members.length > 0 && owners.length > 0 && owners.some((o) => members.includes(o))
|
name.trim().length > 0 && members.length > 0 && owners.length > 0 && owners.some((o) => members.includes(o))
|
||||||
|
|
||||||
|
let autoJoin = funnel?.autoJoin ?? spaceType?.autoJoin ?? false
|
||||||
|
|
||||||
|
$: setDefaultMembers(spaceType)
|
||||||
|
|
||||||
|
let membersChanged: boolean = false
|
||||||
|
|
||||||
|
function setDefaultMembers (typeType: SpaceType | undefined): void {
|
||||||
|
if (typeType === undefined) return
|
||||||
|
if (membersChanged) return
|
||||||
|
if (funnel !== undefined) return
|
||||||
|
autoJoin = typeType.autoJoin ?? false
|
||||||
|
if (typeType.members === undefined || typeType.members.length === 0) return
|
||||||
|
members = typeType.members
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SpaceCreateCard
|
<SpaceCreateCard
|
||||||
@ -167,27 +188,37 @@
|
|||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Grid column={1} rowGap={1.5}>
|
<div class="antiGrid-row">
|
||||||
<EditBox label={leadRes.string.FunnelName} bind:value={name} placeholder={leadRes.string.FunnelName} autoFocus />
|
<EditBox label={leadRes.string.FunnelName} bind:value={name} placeholder={leadRes.string.FunnelName} autoFocus />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="antiGrid-row">
|
||||||
<ToggleWithLabel
|
<ToggleWithLabel
|
||||||
label={presentation.string.MakePrivate}
|
label={presentation.string.MakePrivate}
|
||||||
description={presentation.string.MakePrivateDescription}
|
description={presentation.string.MakePrivateDescription}
|
||||||
bind:on={isPrivate}
|
bind:on={isPrivate}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="antiGrid-row">
|
||||||
|
<div class="antiGrid-row__header">
|
||||||
|
<Label label={task.string.ProjectType} />
|
||||||
|
</div>
|
||||||
<Component
|
<Component
|
||||||
is={task.component.ProjectTypeSelector}
|
is={task.component.ProjectTypeSelector}
|
||||||
disabled={!isNew}
|
disabled={!isNew}
|
||||||
props={{
|
props={{
|
||||||
descriptors: [leadRes.descriptors.FunnelType],
|
descriptors: [leadRes.descriptors.FunnelType],
|
||||||
type: typeId,
|
type: typeId,
|
||||||
|
kind: 'regular',
|
||||||
|
size: 'large',
|
||||||
disabled: funnel !== undefined
|
disabled: funnel !== undefined
|
||||||
}}
|
}}
|
||||||
on:change={(evt) => {
|
on:change={(evt) => {
|
||||||
typeId = evt.detail
|
typeId = evt.detail
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</div>
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
<div class="antiGrid-row__header">
|
<div class="antiGrid-row__header">
|
||||||
<Label label={core.string.Owners} />
|
<Label label={core.string.Owners} />
|
||||||
@ -201,7 +232,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="antiGrid-row mt-4">
|
<div class="antiGrid-row">
|
||||||
<div class="antiGrid-row__header">
|
<div class="antiGrid-row__header">
|
||||||
<Label label={leadRes.string.Members} />
|
<Label label={leadRes.string.Members} />
|
||||||
</div>
|
</div>
|
||||||
@ -214,6 +245,13 @@
|
|||||||
size={'large'}
|
size={'large'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="antiGrid-row">
|
||||||
|
<div class="antiGrid-row__header withDesciption">
|
||||||
|
<Label label={core.string.AutoJoin} />
|
||||||
|
<span><Label label={core.string.AutoJoinDescr} /></span>
|
||||||
|
</div>
|
||||||
|
<Toggle bind:on={autoJoin} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{#each roles as role}
|
{#each roles as role}
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
EditBox,
|
EditBox,
|
||||||
FocusHandler,
|
FocusHandler,
|
||||||
IconAttachment,
|
IconAttachment,
|
||||||
|
Label,
|
||||||
|
Toggle,
|
||||||
createFocusManager,
|
createFocusManager,
|
||||||
showPopup
|
showPopup
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
@ -61,13 +63,25 @@
|
|||||||
let issueTemplates: IssueTemplate[] = []
|
let issueTemplates: IssueTemplate[] = []
|
||||||
let fullDescription: string = ''
|
let fullDescription: string = ''
|
||||||
|
|
||||||
|
let members = [getCurrentAccount()._id]
|
||||||
|
let membersChanged: boolean = false
|
||||||
|
|
||||||
|
$: setDefaultMembers(typeType)
|
||||||
|
|
||||||
|
function setDefaultMembers (typeType: ProjectType | undefined): void {
|
||||||
|
if (typeType === undefined) return
|
||||||
|
if (membersChanged) return
|
||||||
|
if (typeType.members === undefined || typeType.members.length === 0) return
|
||||||
|
members = typeType.members
|
||||||
|
}
|
||||||
|
|
||||||
export let company: Ref<Organization> | undefined
|
export let company: Ref<Organization> | undefined
|
||||||
export let preserveCompany: boolean = false
|
export let preserveCompany: boolean = false
|
||||||
|
|
||||||
let vacancyData: Data<VacancyClass> = {
|
let vacancyData: Data<VacancyClass> = {
|
||||||
archived: false,
|
archived: false,
|
||||||
description: '',
|
description: '',
|
||||||
members: [getCurrentAccount()._id],
|
members,
|
||||||
name: '',
|
name: '',
|
||||||
number: 0,
|
number: 0,
|
||||||
private: false,
|
private: false,
|
||||||
@ -219,7 +233,8 @@
|
|||||||
archived: false,
|
archived: false,
|
||||||
number: (incResult as any).object.sequence,
|
number: (incResult as any).object.sequence,
|
||||||
company,
|
company,
|
||||||
members: [getCurrentAccount()._id],
|
members,
|
||||||
|
autoJoin: typeType.autoJoin ?? false,
|
||||||
owners: [getCurrentAccount()._id],
|
owners: [getCurrentAccount()._id],
|
||||||
type: typeId
|
type: typeId
|
||||||
},
|
},
|
||||||
@ -365,6 +380,16 @@
|
|||||||
extraProps={{ showNavigate: false }}
|
extraProps={{ showNavigate: false }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<AccountArrayEditor
|
||||||
|
bind:value={members}
|
||||||
|
label={contact.string.Members}
|
||||||
|
onChange={() => {
|
||||||
|
membersChanged = true
|
||||||
|
}}
|
||||||
|
kind={'regular'}
|
||||||
|
size={'large'}
|
||||||
|
/>
|
||||||
|
|
||||||
{#each roles as role}
|
{#each roles as role}
|
||||||
<AccountArrayEditor
|
<AccountArrayEditor
|
||||||
value={rolesAssignment?.[role._id] ?? []}
|
value={rolesAssignment?.[role._id] ?? []}
|
||||||
|
@ -13,9 +13,11 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { type SpaceType, type SpaceTypeDescriptor } from '@hcengineering/core'
|
import contact from '@hcengineering/contact'
|
||||||
import { ButtonIcon, IconSquareExpand, ModernButton, ModernEditbox, TextArea } from '@hcengineering/ui'
|
import { AccountArrayEditor } from '@hcengineering/contact-resources'
|
||||||
|
import core, { Account, Ref, type SpaceType, type SpaceTypeDescriptor } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
|
import { ButtonIcon, IconSquareExpand, Label, ModernButton, ModernEditbox, TextArea, Toggle } from '@hcengineering/ui'
|
||||||
|
|
||||||
import settingRes from '../../../plugin'
|
import settingRes from '../../../plugin'
|
||||||
|
|
||||||
@ -50,6 +52,33 @@
|
|||||||
|
|
||||||
await client.update(type, { [field]: value })
|
await client.update(type, { [field]: value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function changeMembers (members: Ref<Account>[]): Promise<void> {
|
||||||
|
if (disabled || type === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const push = new Set<Ref<Account>>(members)
|
||||||
|
const pull = new Set<Ref<Account>>()
|
||||||
|
for (const member of type.members ?? []) {
|
||||||
|
if (!push.has(member)) {
|
||||||
|
pull.add(member)
|
||||||
|
} else {
|
||||||
|
push.delete(member)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (push.size === 0 && pull.size === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const ops = client.apply(`typeMembers_${type._id}`)
|
||||||
|
for (const pushMem of push) {
|
||||||
|
ops.update(type, { $push: { members: pushMem } })
|
||||||
|
}
|
||||||
|
for (const pullMem of pull) {
|
||||||
|
ops.update(type, { $pull: { members: pullMem } })
|
||||||
|
}
|
||||||
|
await ops.commit()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if descriptor !== undefined}
|
{#if descriptor !== undefined}
|
||||||
@ -90,6 +119,24 @@
|
|||||||
attributeUpdated('shortDescription', shortDescription)
|
attributeUpdated('shortDescription', shortDescription)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<div class="flex-between">
|
||||||
|
<AccountArrayEditor
|
||||||
|
value={type?.members ?? []}
|
||||||
|
label={contact.string.Members}
|
||||||
|
onChange={changeMembers}
|
||||||
|
readonly={disabled}
|
||||||
|
/>
|
||||||
|
<div class="flex-row-center flex-gap-2">
|
||||||
|
<Label label={core.string.AutoJoin} />
|
||||||
|
<Toggle
|
||||||
|
on={type?.autoJoin ?? false}
|
||||||
|
on:change={(evt) => {
|
||||||
|
attributeUpdated('autoJoin', evt.detail)
|
||||||
|
}}
|
||||||
|
{disabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<slot name="extra" />
|
<slot name="extra" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -76,7 +76,9 @@
|
|||||||
let defaultStatus: Ref<IssueStatus> | undefined = project?.defaultIssueStatus
|
let defaultStatus: Ref<IssueStatus> | undefined = project?.defaultIssueStatus
|
||||||
let rolesAssignment: RolesAssignment | undefined
|
let rolesAssignment: RolesAssignment | undefined
|
||||||
|
|
||||||
let changeIdentityRef: HTMLElement
|
let typeId: Ref<ProjectType> | undefined = project?.type
|
||||||
|
$: typeType = typeId !== undefined ? $typeStore.get(typeId) : undefined
|
||||||
|
let autoJoin = project?.autoJoin ?? typeType?.autoJoin ?? false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@ -100,6 +102,7 @@
|
|||||||
members,
|
members,
|
||||||
owners,
|
owners,
|
||||||
archived: false,
|
archived: false,
|
||||||
|
autoJoin,
|
||||||
identifier: identifier.toUpperCase(),
|
identifier: identifier.toUpperCase(),
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
defaultAssignee: defaultAssignee ?? undefined,
|
defaultAssignee: defaultAssignee ?? undefined,
|
||||||
@ -155,6 +158,9 @@
|
|||||||
if (projectData.defaultTimeReportDay !== project?.defaultTimeReportDay) {
|
if (projectData.defaultTimeReportDay !== project?.defaultTimeReportDay) {
|
||||||
update.defaultTimeReportDay = projectData.defaultTimeReportDay
|
update.defaultTimeReportDay = projectData.defaultTimeReportDay
|
||||||
}
|
}
|
||||||
|
if (projectData.autoJoin !== project?.autoJoin) {
|
||||||
|
update.autoJoin = projectData.autoJoin
|
||||||
|
}
|
||||||
if (projectData.members.length !== project?.members.length) {
|
if (projectData.members.length !== project?.members.length) {
|
||||||
update.members = projectData.members
|
update.members = projectData.members
|
||||||
} else {
|
} else {
|
||||||
@ -195,8 +201,16 @@
|
|||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeId: Ref<ProjectType> | undefined = project?.type
|
$: setDefaultMembers(typeType)
|
||||||
$: typeType = typeId !== undefined ? $typeStore.get(typeId) : undefined
|
|
||||||
|
function setDefaultMembers (typeType: ProjectType | undefined): void {
|
||||||
|
if (typeType === undefined) return
|
||||||
|
if (membersChanged) return
|
||||||
|
if (project !== undefined) return
|
||||||
|
autoJoin = typeType.autoJoin ?? false
|
||||||
|
if (typeType.members === undefined || typeType.members.length === 0) return
|
||||||
|
members = typeType.members
|
||||||
|
}
|
||||||
|
|
||||||
function findTaskTypes (typeId: Ref<SpaceType>): TaskType[] {
|
function findTaskTypes (typeId: Ref<SpaceType>): TaskType[] {
|
||||||
return Array.from($taskTypeStore.values()).filter(
|
return Array.from($taskTypeStore.values()).filter(
|
||||||
@ -254,6 +268,8 @@
|
|||||||
dispatch('close', id)
|
dispatch('close', id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let membersChanged: boolean = false
|
||||||
|
|
||||||
$: projectsQuery.query(tracker.class.Project, { _id: { $nin: project ? [project._id] : [] } }, (res) => {
|
$: projectsQuery.query(tracker.class.Project, { _id: { $nin: project ? [project._id] : [] } }, (res) => {
|
||||||
projectsIdentifiers = new Set(res.map(({ identifier }) => identifier))
|
projectsIdentifiers = new Set(res.map(({ identifier }) => identifier))
|
||||||
})
|
})
|
||||||
@ -296,6 +312,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
||||||
|
membersChanged = true
|
||||||
// If a member was removed we need to remove it from any roles assignments as well
|
// If a member was removed we need to remove it from any roles assignments as well
|
||||||
const newMembersSet = new Set(newMembers)
|
const newMembersSet = new Set(newMembers)
|
||||||
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
||||||
@ -382,7 +399,7 @@
|
|||||||
<Label label={tracker.string.Identifier} />
|
<Label label={tracker.string.Identifier} />
|
||||||
<span><Label label={tracker.string.UsedInIssueIDs} /></span>
|
<span><Label label={tracker.string.UsedInIssueIDs} /></span>
|
||||||
</div>
|
</div>
|
||||||
<div bind:this={changeIdentityRef} class="padding flex-row-center relative">
|
<div class="padding flex-row-center relative">
|
||||||
<EditBox
|
<EditBox
|
||||||
id="project-identifier"
|
id="project-identifier"
|
||||||
bind:value={identifier}
|
bind:value={identifier}
|
||||||
@ -483,7 +500,7 @@
|
|||||||
<Label label={presentation.string.MakePrivate} />
|
<Label label={presentation.string.MakePrivate} />
|
||||||
<span><Label label={presentation.string.MakePrivateDescription} /></span>
|
<span><Label label={presentation.string.MakePrivateDescription} /></span>
|
||||||
</div>
|
</div>
|
||||||
<Toggle bind:on={isPrivate} disabled={!isPrivate && members.length === 0} />
|
<Toggle id={'project-private'} bind:on={isPrivate} disabled={!isPrivate && members.length === 0} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
@ -499,6 +516,14 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="antiGrid-row">
|
||||||
|
<div class="antiGrid-row__header withDesciption">
|
||||||
|
<Label label={core.string.AutoJoin} />
|
||||||
|
<span><Label label={core.string.AutoJoinDescr} /></span>
|
||||||
|
</div>
|
||||||
|
<Toggle bind:on={autoJoin} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{#each roles as role}
|
{#each roles as role}
|
||||||
<div class="antiGrid-row">
|
<div class="antiGrid-row">
|
||||||
<div class="antiGrid-row__header">
|
<div class="antiGrid-row__header">
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
import { CheckBox, resizeObserver } from '@hcengineering/ui'
|
import { CheckBox, resizeObserver } from '@hcengineering/ui'
|
||||||
import BooleanPresenter from './BooleanPresenter.svelte'
|
import BooleanPresenter from './BooleanPresenter.svelte'
|
||||||
|
|
||||||
export let value: boolean
|
export let value: boolean | null | undefined
|
||||||
export let withoutUndefined: boolean = false
|
export let withoutUndefined: boolean = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<BooleanPresenter value={true} />
|
<BooleanPresenter value={true} />
|
||||||
{#if value}
|
{#if value}
|
||||||
<div class="check">
|
<div class="check">
|
||||||
<CheckBox checked={value} kind={'primary'} />
|
<CheckBox checked kind={'primary'} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@ -39,9 +39,9 @@
|
|||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div class="menu-item" on:click={() => dispatch('close', 2)}>
|
<div class="menu-item" on:click={() => dispatch('close', 2)}>
|
||||||
<BooleanPresenter value={false} />
|
<BooleanPresenter value={false} />
|
||||||
{#if withoutUndefined ? !value : !value}
|
{#if withoutUndefined ? !value : value === false}
|
||||||
<div class="check">
|
<div class="check">
|
||||||
<CheckBox checked={withoutUndefined ? !value : !value} kind={'primary'} />
|
<CheckBox checked kind={'primary'} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@ -50,9 +50,9 @@
|
|||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div class="menu-item" on:click={() => dispatch('close', 3)}>
|
<div class="menu-item" on:click={() => dispatch('close', 3)}>
|
||||||
<BooleanPresenter value={undefined} />
|
<BooleanPresenter value={undefined} />
|
||||||
{#if value === undefined}
|
{#if value == null}
|
||||||
<div class="check">
|
<div class="check">
|
||||||
<CheckBox checked={value === undefined} kind={'primary'} />
|
<CheckBox checked kind={'primary'} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { BooleanIcon, Label } from '@hcengineering/ui'
|
import { BooleanIcon, Label } from '@hcengineering/ui'
|
||||||
import { getBooleanLabel } from '../utils'
|
import { getBooleanLabel } from '../utils'
|
||||||
|
|
||||||
export let value: any
|
export let value: boolean | null | undefined
|
||||||
export let inline: boolean = false
|
export let inline: boolean = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -591,7 +591,7 @@ function getLookup (
|
|||||||
return current !== undefined ? [current, parent, false] : undefined
|
return current !== undefined ? [current, parent, false] : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBooleanLabel (value: boolean | undefined): IntlString {
|
export function getBooleanLabel (value: boolean | undefined | null): IntlString {
|
||||||
if (value === true) return plugin.string.LabelYes
|
if (value === true) return plugin.string.LabelYes
|
||||||
if (value === false) return plugin.string.LabelNo
|
if (value === false) return plugin.string.LabelNo
|
||||||
return plugin.string.LabelNA
|
return plugin.string.LabelNA
|
||||||
|
@ -29,10 +29,12 @@ import contact, {
|
|||||||
getName
|
getName
|
||||||
} from '@hcengineering/contact'
|
} from '@hcengineering/contact'
|
||||||
import core, {
|
import core, {
|
||||||
|
Account,
|
||||||
Class,
|
Class,
|
||||||
Doc,
|
Doc,
|
||||||
Hierarchy,
|
Hierarchy,
|
||||||
Ref,
|
Ref,
|
||||||
|
SpaceType,
|
||||||
Tx,
|
Tx,
|
||||||
TxCreateDoc,
|
TxCreateDoc,
|
||||||
TxMixin,
|
TxMixin,
|
||||||
@ -46,6 +48,38 @@ import { getMetadata } from '@hcengineering/platform'
|
|||||||
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
||||||
import { workbenchId } from '@hcengineering/workbench'
|
import { workbenchId } from '@hcengineering/workbench'
|
||||||
|
|
||||||
|
export async function OnSpaceTypeMembers (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
||||||
|
const ctx = tx as TxUpdateDoc<SpaceType>
|
||||||
|
const result: Tx[] = []
|
||||||
|
const newMember = ctx.operations.$push?.members as Ref<Account>
|
||||||
|
if (newMember !== undefined) {
|
||||||
|
const spaces = await control.findAll(core.class.Space, { type: ctx.objectId })
|
||||||
|
for (const space of spaces) {
|
||||||
|
if (space.members.includes(newMember)) continue
|
||||||
|
const pushTx = control.txFactory.createTxUpdateDoc(space._class, space.space, space._id, {
|
||||||
|
$push: {
|
||||||
|
members: newMember
|
||||||
|
}
|
||||||
|
})
|
||||||
|
result.push(pushTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const oldMember = ctx.operations.$pull?.members as Ref<Account>
|
||||||
|
if (ctx.operations.$pull?.members !== undefined) {
|
||||||
|
const spaces = await control.findAll(core.class.Space, { type: ctx.objectId })
|
||||||
|
for (const space of spaces) {
|
||||||
|
if (!space.members.includes(oldMember)) continue
|
||||||
|
const pullTx = control.txFactory.createTxUpdateDoc(space._class, space.space, space._id, {
|
||||||
|
$pull: {
|
||||||
|
members: oldMember
|
||||||
|
}
|
||||||
|
})
|
||||||
|
result.push(pullTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
export async function OnEmployeeCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
export async function OnEmployeeCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
||||||
const mixinTx = tx as TxMixin<Person, Employee>
|
const mixinTx = tx as TxMixin<Person, Employee>
|
||||||
if (mixinTx.attributes.active !== true) return []
|
if (mixinTx.attributes.active !== true) return []
|
||||||
@ -305,7 +339,8 @@ export default async () => ({
|
|||||||
OnEmployeeCreate,
|
OnEmployeeCreate,
|
||||||
OnPersonAccountCreate,
|
OnPersonAccountCreate,
|
||||||
OnContactDelete,
|
OnContactDelete,
|
||||||
OnChannelUpdate
|
OnChannelUpdate,
|
||||||
|
OnSpaceTypeMembers
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
PersonHTMLPresenter: personHTMLPresenter,
|
PersonHTMLPresenter: personHTMLPresenter,
|
||||||
|
@ -33,7 +33,8 @@ export default plugin(serverContactId, {
|
|||||||
OnContactDelete: '' as Resource<TriggerFunc>,
|
OnContactDelete: '' as Resource<TriggerFunc>,
|
||||||
OnChannelUpdate: '' as Resource<TriggerFunc>,
|
OnChannelUpdate: '' as Resource<TriggerFunc>,
|
||||||
OnEmployeeCreate: '' as Resource<TriggerFunc>,
|
OnEmployeeCreate: '' as Resource<TriggerFunc>,
|
||||||
OnPersonAccountCreate: '' as Resource<TriggerFunc>
|
OnPersonAccountCreate: '' as Resource<TriggerFunc>,
|
||||||
|
OnSpaceTypeMembers: '' as Resource<TriggerFunc>
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
PersonHTMLPresenter: '' as Resource<Presenter>,
|
PersonHTMLPresenter: '' as Resource<Presenter>,
|
||||||
|
@ -30,7 +30,7 @@ export class DocumentsPage extends CommonPage {
|
|||||||
readonly inputModalNewTeamspaceDescription = (): Locator =>
|
readonly inputModalNewTeamspaceDescription = (): Locator =>
|
||||||
this.formNewTeamspace().locator('div[id="teamspace-description"] input')
|
this.formNewTeamspace().locator('div[id="teamspace-description"] input')
|
||||||
|
|
||||||
readonly inputModalNewTeamspacePrivate = (): Locator => this.formNewTeamspace().locator('div.antiGrid label.toggle')
|
readonly inputModalNewTeamspacePrivate = (): Locator => this.formNewTeamspace().locator('[id="teamspace-private"]')
|
||||||
readonly buttonModalNewTeamspaceCreate = (): Locator => this.formNewTeamspace().locator('button[type="submit"]')
|
readonly buttonModalNewTeamspaceCreate = (): Locator => this.formNewTeamspace().locator('button[type="submit"]')
|
||||||
readonly buttonModalEditTeamspaceTitle = (): Locator =>
|
readonly buttonModalEditTeamspaceTitle = (): Locator =>
|
||||||
this.formEditTeamspace().locator('div[id="teamspace-title"] input')
|
this.formEditTeamspace().locator('div[id="teamspace-title"] input')
|
||||||
@ -38,8 +38,7 @@ export class DocumentsPage extends CommonPage {
|
|||||||
readonly buttonModalEditTeamspaceDescription = (): Locator =>
|
readonly buttonModalEditTeamspaceDescription = (): Locator =>
|
||||||
this.formEditTeamspace().locator('div[id="teamspace-description"] input')
|
this.formEditTeamspace().locator('div[id="teamspace-description"] input')
|
||||||
|
|
||||||
readonly buttonModalEditTeamspacePrivate = (): Locator =>
|
readonly buttonModalEditTeamspacePrivate = (): Locator => this.formEditTeamspace().locator('[id="teamspace-private"]')
|
||||||
this.formEditTeamspace().locator('div.antiGrid label.toggle')
|
|
||||||
|
|
||||||
readonly buttonModalEditTeamspaceSave = (): Locator => this.formEditTeamspace().locator('button[type="submit"]')
|
readonly buttonModalEditTeamspaceSave = (): Locator => this.formEditTeamspace().locator('button[type="submit"]')
|
||||||
readonly buttonModalEditTeamspaceClose = (): Locator => this.formEditTeamspace().locator('button#card-close')
|
readonly buttonModalEditTeamspaceClose = (): Locator => this.formEditTeamspace().locator('button#card-close')
|
||||||
|
@ -16,7 +16,7 @@ export class EditProjectPage extends CommonTrackerPage {
|
|||||||
this.page.locator('form[id="tracker:string:EditProject"] div[id="project-description"] input')
|
this.page.locator('form[id="tracker:string:EditProject"] div[id="project-description"] input')
|
||||||
|
|
||||||
buttonChooseIcon = (): Locator => this.page.locator('div.antiGrid-row button.only-icon')
|
buttonChooseIcon = (): Locator => this.page.locator('div.antiGrid-row button.only-icon')
|
||||||
buttonMakePrivate = (): Locator => this.page.locator('div.antiGrid-row span.toggle-switch')
|
buttonMakePrivate = (): Locator => this.page.locator('[id="project-private"]')
|
||||||
buttonSaveProject = (): Locator => this.page.locator('form[id="tracker:string:EditProject"] button[type="submit"]')
|
buttonSaveProject = (): Locator => this.page.locator('form[id="tracker:string:EditProject"] button[type="submit"]')
|
||||||
buttonIcons = (): Locator => this.page.locator('form[id="view:string:ChooseIcon"] div.float-left > button')
|
buttonIcons = (): Locator => this.page.locator('form[id="view:string:ChooseIcon"] div.float-left > button')
|
||||||
buttonSaveIcons = (): Locator =>
|
buttonSaveIcons = (): Locator =>
|
||||||
|
@ -12,7 +12,7 @@ export class NewProjectPage extends CommonTrackerPage {
|
|||||||
inputIdentifier = (): Locator => this.page.locator('div[id="project-identifier"] input')
|
inputIdentifier = (): Locator => this.page.locator('div[id="project-identifier"] input')
|
||||||
inputDescription = (): Locator => this.page.locator('div[id="project-description"] input')
|
inputDescription = (): Locator => this.page.locator('div[id="project-description"] input')
|
||||||
buttonChooseIcon = (): Locator => this.page.locator('div.antiGrid-row button.only-icon')
|
buttonChooseIcon = (): Locator => this.page.locator('div.antiGrid-row button.only-icon')
|
||||||
buttonMakePrivate = (): Locator => this.page.locator('div.antiGrid-row span.toggle-switch')
|
buttonMakePrivate = (): Locator => this.page.locator('[id="project-private"]')
|
||||||
buttonCreateProject = (): Locator => this.page.locator('form[id="tracker:string:NewProject"] button[type="submit"]')
|
buttonCreateProject = (): Locator => this.page.locator('form[id="tracker:string:NewProject"] button[type="submit"]')
|
||||||
projectTypeButton = (): Locator =>
|
projectTypeButton = (): Locator =>
|
||||||
this.page.locator('div[class*="header"]', { hasText: 'Project type' }).locator('xpath=..').locator('button')
|
this.page.locator('div[class*="header"]', { hasText: 'Project type' }).locator('xpath=..').locator('button')
|
||||||
|
Loading…
Reference in New Issue
Block a user