mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-10 09:22:23 +00:00
Add auto-start functionality and related triggers for processes (#8478)
This commit is contained in:
parent
d2bdf88249
commit
507078d7ac
@ -11,7 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import card, { type Card, type MasterTag } from '@hcengineering/card'
|
||||
import card, { type Tag, type Card, type MasterTag } from '@hcengineering/card'
|
||||
import contact, { type Employee } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AccountRole,
|
||||
@ -68,11 +68,14 @@ export class TProcess extends TDoc implements Process {
|
||||
@Prop(TypeString(), core.string.Description)
|
||||
description!: string
|
||||
|
||||
@Prop(TypeRef(card.class.MasterTag), core.string.Name)
|
||||
masterTag!: Ref<MasterTag>
|
||||
@Prop(TypeRef(card.class.MasterTag), card.string.MasterTag)
|
||||
masterTag!: Ref<MasterTag | Tag>
|
||||
|
||||
@Prop(ArrOf(TypeRef(process.class.State)), process.string.States)
|
||||
states!: Ref<State>[]
|
||||
|
||||
@Prop(TypeBoolean(), process.string.StartAutomatically)
|
||||
autoStart: boolean | undefined
|
||||
}
|
||||
|
||||
@Model(process.class.Execution, core.class.Doc, DOMAIN_PROCESS)
|
||||
|
@ -33,6 +33,7 @@
|
||||
"@hcengineering/model": "^0.6.11",
|
||||
"@hcengineering/model-process": "^0.6.0",
|
||||
"@hcengineering/process": "^0.6.0",
|
||||
"@hcengineering/card": "^0.6.0",
|
||||
"@hcengineering/server-process": "^0.6.0",
|
||||
"@hcengineering/server-core": "^0.6.1"
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import card from '@hcengineering/card'
|
||||
import core, { type Doc } from '@hcengineering/core'
|
||||
import { Mixin, type Builder } from '@hcengineering/model'
|
||||
import { TMethod, TProcessFunction } from '@hcengineering/model-process'
|
||||
@ -19,8 +20,8 @@ import process from '@hcengineering/process'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
import serverProcess, {
|
||||
type ExecuteFunc,
|
||||
type MethodImpl,
|
||||
type FuncImpl,
|
||||
type MethodImpl,
|
||||
type TransformFunc
|
||||
} from '@hcengineering/server-process'
|
||||
|
||||
@ -110,6 +111,24 @@ export function createModel (builder: Builder): void {
|
||||
isAsync: true
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverProcess.trigger.OnCardCreate,
|
||||
txMatch: {
|
||||
_class: core.class.TxCreateDoc,
|
||||
objectClass: card.class.Card
|
||||
},
|
||||
isAsync: true
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverProcess.trigger.OnTagAdd,
|
||||
txMatch: {
|
||||
_class: core.class.TxMixin,
|
||||
objectClass: card.class.Card
|
||||
},
|
||||
isAsync: true
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverProcess.trigger.OnExecutionCreate,
|
||||
txMatch: {
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "První pracovní den po",
|
||||
"FallbackValueError": "Zobrazit chybu, pokud není k dispozici",
|
||||
"Required": "Povinné",
|
||||
"StartAutomatically": "Spustit automaticky",
|
||||
"Error": "Chyba",
|
||||
"Continue": "Pokračovat"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Erste Arbeitstag nach",
|
||||
"FallbackValueError": "Fehler anzeigen, wenn leer",
|
||||
"Required": "Erforderlich",
|
||||
"StartAutomatically": "Automatisch starten",
|
||||
"Error": "Fehler",
|
||||
"Continue": "Fortsetzen"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "First working day after",
|
||||
"FallbackValueError": "Show error if empty",
|
||||
"Required": "Required",
|
||||
"StartAutomatically": "Start automatically",
|
||||
"Error": "Error",
|
||||
"Continue": "Continue"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Primer día de trabajo después",
|
||||
"FallbackValueError": "Mostrar error si está vacío",
|
||||
"Required": "Requerido",
|
||||
"StartAutomatically": "Iniciar automáticamente",
|
||||
"Error": "Error",
|
||||
"Continue": "Continuar"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Premier jour de travail après",
|
||||
"FallbackValueError": "Afficher l'erreur si vide",
|
||||
"Required": "Requis",
|
||||
"StartAutomatically": "Démarrer automatiquement",
|
||||
"Error": "Erreur",
|
||||
"Continue": "Continuer"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Primo giorno lavorativo dopo",
|
||||
"FallbackValueError": "Mostra errore se vuoto",
|
||||
"Required": "Obbligatorio",
|
||||
"StartAutomatically": "Avvia automaticamente",
|
||||
"Error": "Errore",
|
||||
"Continue": "Continua"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Primeiro Dia de Trabalho Após",
|
||||
"FallbackValueError": "Mostrar erro se vazio",
|
||||
"Required": "Obrigatório",
|
||||
"StartAutomatically": "Iniciar automaticamente",
|
||||
"Error": "Erro",
|
||||
"Continue": "Continuar"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "Первый рабочий день после",
|
||||
"FallbackValueError": "Показывать ошибку, если недоступно",
|
||||
"Required": "Обязательно",
|
||||
"StartAutomatically": "Запускать автоматически",
|
||||
"Error": "Ошибка",
|
||||
"Continue": "Продолжить"
|
||||
},
|
||||
|
@ -43,6 +43,7 @@
|
||||
"FirstWorkingDayAfter": "在之后的第一个工作日",
|
||||
"FallbackValueError": "显示错误,如果为空",
|
||||
"Required": "必需",
|
||||
"StartAutomatically": "自动启动",
|
||||
"Error": "错误",
|
||||
"Continue": "继续"
|
||||
},
|
||||
|
@ -29,6 +29,7 @@
|
||||
IconDescription,
|
||||
navigate,
|
||||
NavItem,
|
||||
ToggleWithLabel,
|
||||
Scroller,
|
||||
secondNavSeparators,
|
||||
Separator,
|
||||
@ -77,6 +78,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function saveAutoStart (e: CustomEvent<boolean>): Promise<void> {
|
||||
if (value !== undefined) {
|
||||
await client.update(value, { autoStart: e.detail })
|
||||
}
|
||||
}
|
||||
|
||||
async function addState (): Promise<void> {
|
||||
if (value === undefined) return
|
||||
const prevState = states[states.length - 1]
|
||||
@ -160,6 +167,13 @@
|
||||
<EditBox bind:value={value.name} on:change={saveName} placeholder={process.string.Untitled} />
|
||||
<ButtonIcon icon={IconDelete} size="small" kind="secondary" on:click={handleDelete} />
|
||||
</div>
|
||||
<div>
|
||||
<ToggleWithLabel
|
||||
on={value.autoStart ?? false}
|
||||
on:change={saveAutoStart}
|
||||
label={process.string.StartAutomatically}
|
||||
/>
|
||||
</div>
|
||||
<div class="hulyComponent-content flex-col-center">
|
||||
<div class="flex-col-center">
|
||||
{#each sortedStates as state (state._id)}
|
||||
|
@ -89,6 +89,7 @@ export default mergeIds(processId, process, {
|
||||
FirstWorkingDayAfter: '' as IntlString,
|
||||
FallbackValueError: '' as IntlString,
|
||||
Required: '' as IntlString,
|
||||
StartAutomatically: '' as IntlString,
|
||||
Continue: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -11,7 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Card, MasterTag } from '@hcengineering/card'
|
||||
import { Card, MasterTag, Tag } from '@hcengineering/card'
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Class, Doc, DocumentUpdate, ObjQueryType, Ref, Tx } from '@hcengineering/core'
|
||||
import { Asset, IntlString, Plugin, plugin } from '@hcengineering/platform'
|
||||
@ -25,10 +25,11 @@ import { AttributeCategory } from '@hcengineering/view'
|
||||
export const processId = 'process' as Plugin
|
||||
|
||||
export interface Process extends Doc {
|
||||
masterTag: Ref<MasterTag>
|
||||
masterTag: Ref<MasterTag | Tag>
|
||||
name: string
|
||||
description: string
|
||||
states: Ref<State>[]
|
||||
autoStart?: boolean
|
||||
}
|
||||
|
||||
export interface Execution extends Doc {
|
||||
|
@ -25,6 +25,7 @@ import core, {
|
||||
Timestamp,
|
||||
Tx,
|
||||
TxCreateDoc,
|
||||
TxMixin,
|
||||
TxProcessor,
|
||||
TxRemoveDoc,
|
||||
TxUpdateDoc
|
||||
@ -635,6 +636,63 @@ export function FirstWorkingDayAfter (val: Timestamp): Timestamp {
|
||||
return val
|
||||
}
|
||||
|
||||
export async function OnCardCreate (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
|
||||
const res: Tx[] = []
|
||||
for (const tx of txes) {
|
||||
if (tx._class !== core.class.TxCreateDoc) continue
|
||||
const createTx = tx as TxCreateDoc<Card>
|
||||
if (!control.hierarchy.isDerived(createTx.objectClass, card.class.Card)) continue
|
||||
const ancestors = control.hierarchy
|
||||
.getAncestors(createTx.objectClass)
|
||||
.filter((p) => control.hierarchy.isDerived(p, card.class.Card))
|
||||
|
||||
const processes = control.modelDb.findAllSync(process.class.Process, {
|
||||
masterTag: { $in: ancestors },
|
||||
autoStart: true
|
||||
})
|
||||
for (const proc of processes) {
|
||||
res.push(
|
||||
control.txFactory.createTxCreateDoc(process.class.Execution, core.space.Workspace, {
|
||||
process: proc._id,
|
||||
currentState: null,
|
||||
card: createTx.objectId,
|
||||
done: false,
|
||||
rollback: {},
|
||||
currentToDo: null,
|
||||
assignee: null
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
export async function OnTagAdd (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
|
||||
const res: Tx[] = []
|
||||
for (const tx of txes) {
|
||||
if (tx._class !== core.class.TxMixin) continue
|
||||
const mixinTx = tx as TxMixin<Card, Card>
|
||||
if (!control.hierarchy.isDerived(mixinTx.objectClass, card.class.Card)) continue
|
||||
if (Object.keys(mixinTx.attributes).length !== 0) continue
|
||||
|
||||
const processes = control.modelDb.findAllSync(process.class.Process, { masterTag: mixinTx.mixin, autoStart: true })
|
||||
for (const proc of processes) {
|
||||
res.push(
|
||||
control.txFactory.createTxCreateDoc(process.class.Execution, core.space.Workspace, {
|
||||
process: proc._id,
|
||||
currentState: null,
|
||||
card: mixinTx.objectId,
|
||||
done: false,
|
||||
rollback: {},
|
||||
currentToDo: null,
|
||||
assignee: null
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
export async function OnExecutionContinue (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
|
||||
const res: Tx[] = []
|
||||
for (const tx of txes) {
|
||||
@ -679,6 +737,8 @@ export default async () => ({
|
||||
FirstWorkingDayAfter
|
||||
},
|
||||
trigger: {
|
||||
OnCardCreate,
|
||||
OnTagAdd,
|
||||
OnExecutionCreate,
|
||||
OnStateRemove,
|
||||
OnProcessRemove,
|
||||
|
@ -46,6 +46,8 @@ export default plugin(serverProcessId, {
|
||||
FirstWorkingDayAfter: '' as Resource<TransformFunc>
|
||||
},
|
||||
trigger: {
|
||||
OnCardCreate: '' as Resource<TriggerFunc>,
|
||||
OnTagAdd: '' as Resource<TriggerFunc>,
|
||||
OnExecutionCreate: '' as Resource<TriggerFunc>,
|
||||
OnStateRemove: '' as Resource<TriggerFunc>,
|
||||
OnProcessRemove: '' as Resource<TriggerFunc>,
|
||||
|
Loading…
Reference in New Issue
Block a user