Merge remote-tracking branch 'origin/develop' into staging-new

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov
2025-09-15 14:43:35 +07:00
56 changed files with 311 additions and 119 deletions
+1
View File
@@ -4,6 +4,7 @@
VERSION=${VERSION:-"latest"}
docker build -t hardcoreeng/base:${VERSION} -f base.Dockerfile ${DOCKER_EXTRA} .
docker build -t hardcoreeng/base-slim:${VERSION} -f slim.Dockerfile ${DOCKER_EXTRA} .
docker build -t hardcoreeng/rekoni-base:${VERSION} -f rekoni.Dockerfile ${DOCKER_EXTRA} .
docker build -t hardcoreeng/print-base:${VERSION} -f print.Dockerfile ${DOCKER_EXTRA} .
docker build -t hardcoreeng/front-base:${VERSION} -f front.Dockerfile ${DOCKER_EXTRA} .
+1
View File
@@ -4,6 +4,7 @@
VERSION=${VERSION:-"latest"}
docker push hardcoreeng/base:${VERSION}
docker push hardcoreeng/base-slim:${VERSION}
docker push hardcoreeng/rekoni-base:${VERSION}
docker push hardcoreeng/print-base:${VERSION}
docker push hardcoreeng/front-base:${VERSION}
+11
View File
@@ -0,0 +1,11 @@
FROM node:22-slim
RUN apt-get update
RUN apt-get install libjemalloc2 dumb-init
RUN apt-get clean
ENV LD_PRELOAD=libjemalloc.so.2
ENV MALLOC_CONF=dirty_decay_ms:1000,narenas:2,background_thread:true
WORKDIR /usr/src/app
ENV NODE_ENV=production
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1
View File
@@ -44,6 +44,7 @@
"@hcengineering/time": "^0.6.0",
"@hcengineering/setting": "^0.6.17",
"@hcengineering/model-time": "^0.6.0",
"@hcengineering/rank": "^0.6.4",
"@hcengineering/process": "^0.6.0",
"@hcengineering/process-resources": "^0.6.0",
"@hcengineering/model-presentation": "^0.6.0",
+21 -4
View File
@@ -19,6 +19,7 @@ import core, {
DOMAIN_MODEL,
type Doc,
type Domain,
type Rank,
type Ref,
SortingOrder,
type Space,
@@ -26,11 +27,13 @@ import core, {
} from '@hcengineering/core'
import {
type Builder,
Hidden,
Model,
Prop,
ReadOnly,
TypeAny,
TypeBoolean,
TypeRank,
TypeRef,
TypeString,
UX
@@ -134,6 +137,10 @@ export class TTransition extends TDoc implements Transition {
triggerParams!: Record<string, any>
result?: TriggerResult | null
@Prop(TypeRank(), core.string.Rank)
@Hidden()
rank!: Rank
}
@Model(process.class.ExecutionLog, core.class.Doc, DOMAIN_PROCESS_LOG)
@@ -213,8 +220,16 @@ export class TMethod extends TDoc implements Method<Doc> {
@Model(process.class.State, core.class.Doc, DOMAIN_MODEL)
export class TState extends TDoc implements State {
process!: Ref<Process>
title!: string
@Prop(TypeRef(process.class.Process), process.string.Process)
@ReadOnly()
process!: Ref<Process>
@Prop(TypeString(), core.string.Name)
title!: string
@Prop(TypeRank(), core.string.Rank)
@Hidden()
rank!: Rank
}
@Model(process.class.ProcessFunction, core.class.Doc, DOMAIN_MODEL)
@@ -1086,7 +1101,8 @@ export function createModel (builder: Builder): void {
presenter: process.component.ToDoSettingPresenter,
requiredParams: ['_id'],
checkFunction: process.triggerCheck.ToDo,
init: false
init: false,
auto: true
},
process.trigger.OnToDoClose
)
@@ -1101,7 +1117,8 @@ export function createModel (builder: Builder): void {
presenter: process.component.ToDoSettingPresenter,
requiredParams: ['_id'],
checkFunction: process.triggerCheck.ToDo,
init: false
init: false,
auto: true
},
process.trigger.OnToDoRemove
)
+27 -1
View File
@@ -13,7 +13,7 @@
// limitations under the License.
//
import core, { type Client, type Doc, TxOperations } from '@hcengineering/core'
import core, { type Client, type Doc, type Rank, TxOperations } from '@hcengineering/core'
import {
type MigrateOperation,
type MigrationClient,
@@ -21,6 +21,7 @@ import {
tryUpgrade
} from '@hcengineering/model'
import process, { type State, type Step } from '@hcengineering/process'
import { makeRank } from '@hcengineering/rank'
import { processId } from '.'
export const processOperation: MigrateOperation = {
@@ -31,6 +32,11 @@ export const processOperation: MigrateOperation = {
state: 'migrateActionsFromStates',
mode: 'upgrade',
func: migrateActionsFromStates
},
{
state: 'fillStatesRanks',
mode: 'upgrade',
func: fillStatesRanks
}
])
}
@@ -40,6 +46,23 @@ interface OldState extends State {
actions: Step<Doc>[]
}
async function fillStatesRanks (client: Client): Promise<void> {
const txOp = new TxOperations(client, core.account.System)
const states = await client.findAll(process.class.State, { rank: { $exists: false } })
let prevRank: Rank | undefined
for (const state of states) {
prevRank = makeRank(prevRank, undefined)
await txOp.update(state, { rank: prevRank })
}
const transitions = await client.findAll(process.class.Transition, { rank: { $exists: false } })
prevRank = undefined
for (const transition of transitions) {
prevRank = makeRank(prevRank, undefined)
await txOp.update(transition, { rank: prevRank })
}
}
async function migrateActionsFromStates (client: Client): Promise<void> {
const txOp = new TxOperations(client, core.account.System)
const rollbackTransitions = await client.findAll(process.class.Transition, { to: null as any })
@@ -54,10 +77,12 @@ async function migrateActionsFromStates (client: Client): Promise<void> {
arr.push(transition)
transitionsMap.set(transition.to, arr)
}
let prevRank: Rank | undefined
for (const state of states) {
if (state.actions?.length > 0) {
const transitions = transitionsMap.get(state._id) ?? []
if (transitions.length === 0) {
prevRank = makeRank(prevRank, undefined)
await txOp.createDoc(
process.class.Transition,
core.space.Model,
@@ -65,6 +90,7 @@ async function migrateActionsFromStates (client: Client): Promise<void> {
from: null,
to: state._id,
actions: state.actions,
rank: prevRank,
trigger: process.trigger.OnExecutionStart,
triggerParams: {},
process: state.process
+2 -2
View File
@@ -51,12 +51,12 @@ export function createModel (builder: Builder): void {
builder.createModel(TMethodImpl, TFuncImpl, TTriggerImpl)
builder.mixin(process.trigger.OnToDoClose, process.class.Trigger, serverProcess.mixin.TriggerImpl, {
serverCheckFunc: serverProcess.func.CheckToDo,
serverCheckFunc: serverProcess.func.CheckToDoDone,
rollbackFunc: serverProcess.rollbacks.ToDoCloseRollback
})
builder.mixin(process.trigger.OnToDoRemove, process.class.Trigger, serverProcess.mixin.TriggerImpl, {
serverCheckFunc: serverProcess.func.CheckToDo,
serverCheckFunc: serverProcess.func.CheckToDoCancelled,
rollbackFunc: serverProcess.rollbacks.ToDoCancellRollback
})
+4
View File
@@ -261,6 +261,10 @@ export class HulypulseClient implements Disposable {
return
}
if (event.data === 'pong') {
return
}
const msg: PulseIncomingMessage = JSON.parse(event.data.toString())
// Handle incoming messages (Set, Expired, Del)
@@ -114,7 +114,7 @@
kind={'regular'}
size={'small'}
label={document.string.NoParentDocument}
searchField={'name'}
searchField={'title'}
allowDeselect={true}
showNavigate={false}
docProps={{ disabled: true, noUnderline: true }}
@@ -116,7 +116,7 @@
docQuery={{ space }}
kind={'regular'}
size={'small'}
searchField={'name'}
searchField={'title'}
allowDeselect={true}
showNavigate={false}
docProps={{ disabled: true, noUnderline: true }}
@@ -95,7 +95,7 @@
kind={'regular'}
size={'small'}
label={drive.string.Root}
searchField={'name'}
searchField={'title'}
allowDeselect
showNavigate={false}
docProps={{ disabled: true, noUnderline: true }}
@@ -95,7 +95,7 @@
docQuery={{ space }}
kind={'regular'}
size={'small'}
searchField={'name'}
searchField={'title'}
allowDeselect={true}
showNavigate={false}
docProps={{ disabled: true, noUnderline: true }}
+3 -1
View File
@@ -717,10 +717,12 @@ async function checkRecordAvailable (): Promise<void> {
setTimeout(() => {
void checkRecordAvailable()
}, 500)
} else {
} else if (endpoint !== '') {
const res = await fetch(concatLink(endpoint, '/checkRecordAvailable'))
const result = await res.json()
isRecordingAvailable.set(result)
} else {
console.info('office recording is not configured')
}
} catch (err: any) {
Analytics.handleError(err)
@@ -20,6 +20,7 @@
import { Process, State } from '@hcengineering/process'
import { ButtonIcon, getCurrentLocation, Icon, IconAdd, Label, navigate } from '@hcengineering/ui'
import process from '../plugin'
import { makeRank } from '@hcengineering/rank'
export let masterTag: MasterTag
@@ -38,6 +39,7 @@
core.space.Model,
{
process: id,
rank: makeRank(undefined, undefined),
title: await translate(process.string.NewState, {})
},
initState
@@ -47,6 +49,7 @@
from: null,
to: initState,
trigger: process.trigger.OnExecutionStart,
rank: makeRank(undefined, undefined),
actions: [],
triggerParams: {}
})
@@ -13,12 +13,13 @@
// limitations under the License.
-->
<script lang="ts">
import core, { Ref } from '@hcengineering/core'
import core, { Ref, SortingOrder } from '@hcengineering/core'
import { Card, createQuery, getClient } from '@hcengineering/presentation'
import { Process, State, Trigger, TriggerResult } from '@hcengineering/process'
import { Process, State, Transition, Trigger, TriggerResult } from '@hcengineering/process'
import { Component, Dropdown, DropdownIntlItem, DropdownLabelsIntl, Label, ListItem } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import plugin from '../../plugin'
import { makeRank } from '@hcengineering/rank'
export let process: Process
@@ -28,9 +29,16 @@
let result: TriggerResult | null = null
const query = createQuery()
query.query(plugin.class.State, { process: process._id }, (res) => {
states = res
})
query.query(
plugin.class.State,
{ process: process._id },
(res) => {
states = res
},
{
sort: { rank: SortingOrder.Ascending }
}
)
let statesItems: ListItem[] = []
@@ -55,18 +63,39 @@
let params: Record<string, any> = {}
const transitionsQ = createQuery()
let transitions: Transition[] = []
transitionsQ.query(
plugin.class.Transition,
{ process: process._id },
(res) => {
transitions = res
},
{
sort: { rank: SortingOrder.Ascending }
}
)
const triggersItems: DropdownIntlItem[] = triggers.map((p) => ({ label: p.label, id: p._id, icon: p.icon }))
async function save (): Promise<void> {
if (to === undefined || trigger === undefined) {
return
}
const prevTransitions =
transitions.findLast((p) => p.from === from) ?? transitions.length > 0
? transitions[transitions.length - 1]
: undefined
const rank = makeRank(prevTransitions?.rank, undefined)
await client.createDoc(plugin.class.Transition, core.space.Model, {
from,
to,
trigger,
triggerParams: params,
process: process._id,
rank,
result,
actions: []
})
@@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Ref } from '@hcengineering/core'
import { Ref, SortingOrder } from '@hcengineering/core'
import { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
import { Process, State, Transition } from '@hcengineering/process'
import { clearSettingsStore, settingsStore } from '@hcengineering/setting-resources'
@@ -68,13 +68,27 @@
}
})
$: statesQuery.query(process.class.State, { process: _id }, (res) => {
states = res
})
$: statesQuery.query(
process.class.State,
{ process: _id },
(res) => {
states = res
},
{
sort: { rank: SortingOrder.Ascending }
}
)
$: transitionsQ.query(process.class.Transition, { process: _id }, (res) => {
transitions = res
})
$: transitionsQ.query(
process.class.Transition,
{ process: _id },
(res) => {
transitions = res
},
{
sort: { rank: SortingOrder.Ascending }
}
)
async function saveName (): Promise<void> {
if (value !== undefined) {
@@ -151,7 +165,7 @@
</div>
<div class="hulyComponent-content flex-col-center flex-gap-4">
<StatesInlineEditor {states} {readonly} process={value} />
<TransitionsInlineEditor {transitions} {readonly} process={value} />
<TransitionsInlineEditor {readonly} process={value} />
</div>
</div>
</Scroller>
@@ -13,13 +13,15 @@
// limitations under the License.
-->
<script lang="ts">
import core from '@hcengineering/core'
import core, { Doc } from '@hcengineering/core'
import { translate } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import { Process, State } from '@hcengineering/process'
import { Button, IconAdd, Label } from '@hcengineering/ui'
import plugin from '../../plugin'
import StateInlineEditor from './StateInlineEditor.svelte'
import { makeRank } from '@hcengineering/rank'
import { SortableList } from '@hcengineering/view-resources'
export let process: Process
export let states: State[]
@@ -28,11 +30,17 @@
const client = getClient()
async function addState (): Promise<void> {
const rank = makeRank(states.length > 0 ? states[states.length - 1].rank : undefined, undefined)
await client.createDoc(plugin.class.State, core.space.Model, {
process: process._id,
title: await translate(plugin.string.NewState, {})
title: await translate(plugin.string.NewState, {}),
rank
})
}
function toState (doc: Doc): State {
return doc as State
}
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -41,9 +49,11 @@
<div class="header w-full p-4">
<Label label={plugin.string.States} />
</div>
{#each states as state (state._id)}
<StateInlineEditor value={state} />
{/each}
<SortableList _class={plugin.class.State} query={{ process: process._id }} isAddButtonHidden>
<svelte:fragment slot="object" let:value>
<StateInlineEditor value={toState(value)} />
</svelte:fragment>
</SortableList>
{#if !readonly}
<Button kind={'ghost'} width={'100%'} icon={IconAdd} label={plugin.string.AddState} on:click={addState} />
{/if}
@@ -13,16 +13,16 @@
// limitations under the License.
-->
<script lang="ts">
import { Ref } from '@hcengineering/core'
import { Doc, Ref } from '@hcengineering/core'
import { Process, Transition } from '@hcengineering/process'
import { Button, getCurrentLocation, IconAdd, Label, navigate, showPopup } from '@hcengineering/ui'
import plugin from '../../plugin'
import AddTransitionPopup from './AddTransitionPopup.svelte'
import TransitionPresenter from './TransitionPresenter.svelte'
import TriggerPresenter from './TriggerPresenter.svelte'
import { SortableList } from '@hcengineering/view-resources'
export let process: Process
export let transitions: Transition[]
export let readonly: boolean
function addTransition (): void {
@@ -35,6 +35,10 @@
loc.path[6] = id
navigate(loc, true)
}
function toTransition (doc: Doc): Transition {
return doc as Transition
}
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -43,23 +47,26 @@
<div class="header w-full p-4">
<Label label={plugin.string.Transitions} />
</div>
{#each transitions as transition (transition._id)}
<Button
width={'100%'}
kind={'ghost'}
justify={'left'}
on:click={() => {
handleSelect(transition._id)
}}
>
<svelte:fragment slot="content">
<div class="flex-row-center flex-gap-4">
<TransitionPresenter {transition} />
<TriggerPresenter value={transition.trigger} {process} params={transition.triggerParams} withLabel={true} />
</div>
</svelte:fragment>
</Button>
{/each}
<SortableList _class={plugin.class.Transition} query={{ process: process._id }} isAddButtonHidden>
<svelte:fragment slot="object" let:value>
{@const transition = toTransition(value)}
<Button
width={'100%'}
kind={'ghost'}
justify={'left'}
on:click={() => {
handleSelect(transition._id)
}}
>
<svelte:fragment slot="content">
<div class="flex-row-center flex-gap-4">
<TransitionPresenter {transition} />
<TriggerPresenter value={transition.trigger} {process} params={transition.triggerParams} withLabel={true} />
</div>
</svelte:fragment>
</Button>
</svelte:fragment>
</SortableList>
{#if !readonly}
<Button kind={'ghost'} width={'100%'} icon={IconAdd} label={plugin.string.AddTransition} on:click={addTransition} />
{/if}
+3 -1
View File
@@ -12,7 +12,7 @@
// limitations under the License.
import { Card, MasterTag, Tag } from '@hcengineering/card'
import { Association, Class, Client, Doc, DocumentUpdate, ObjQueryType, Ref, Tx, Type } from '@hcengineering/core'
import { Association, Class, Client, Doc, DocumentUpdate, ObjQueryType, Rank, Ref, Tx, Type } from '@hcengineering/core'
import { Asset, IntlString, Plugin, plugin, Resource } from '@hcengineering/platform'
import { ToDo } from '@hcengineering/time'
import { AnyComponent } from '@hcengineering/ui'
@@ -67,6 +67,7 @@ export interface Transition extends Doc {
trigger: Ref<Trigger>
triggerParams: Record<string, any>
result?: TriggerResult | null
rank: Rank
}
export interface ExecutionLog extends Doc {
@@ -131,6 +132,7 @@ Record<string, any>
export interface State extends Doc {
process: Ref<Process>
title: string
rank: Rank
}
export type StepId = string & { __stepId: true }
@@ -15,13 +15,13 @@
<script lang="ts">
import contact, { Employee, formatName } from '@hcengineering/contact'
import { EmployeePresenter } from '@hcengineering/contact-resources'
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
import { Account, AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
import { createQuery } from '@hcengineering/presentation'
import { Breadcrumb, DropdownIntlItem, DropdownLabelsIntl, SearchInput, Header, Scroller } from '@hcengineering/ui'
import { Breadcrumb, DropdownIntlItem, DropdownLabelsIntl, Header, Scroller, SearchInput } from '@hcengineering/ui'
import { onMount } from 'svelte'
import { getAccountClient } from '../utils'
import setting from '../plugin'
import { getAccountClient } from '../utils'
const query = createQuery()
const currentAccount = getCurrentAccount()
@@ -70,6 +70,10 @@
$: ownersCount = employees.filter(
(e) => e.personUuid != null && workspaceMembers[e.personUuid] === AccountRole.Owner
).length
function getItems (role: AccountRole, currentAccount: Account): DropdownIntlItem[] {
return items.filter((i) => i.id === role || hasAccountRole(currentAccount, i.id as AccountRole))
}
</script>
<div class="hulyComponent">
@@ -92,10 +96,12 @@
</div>
<DropdownLabelsIntl
label={setting.string.Role}
disabled={!hasAccountRole(currentAccount, role) || (role === AccountRole.Owner && ownersCount === 1)}
disabled={!hasAccountRole(currentAccount, role) ||
(role === AccountRole.Owner && ownersCount === 1) ||
currentAccount.uuid === personUuid}
kind={'primary'}
size={'medium'}
{items}
items={getItems(role, currentAccount)}
selected={role}
on:selected={(e) => {
void change(personUuid, e.detail)
@@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import core, { AttachedData, FindOptions, type Rank, Ref, SortingOrder } from '@hcengineering/core'
import core, { AttachedData, Doc, FindOptions, type Rank, Ref, SortingOrder } from '@hcengineering/core'
import { ObjectPopup, getClient } from '@hcengineering/presentation'
import { makeRank } from '@hcengineering/task'
import { Issue, IssueDraft } from '@hcengineering/tracker'
@@ -65,7 +65,32 @@
}
$: selected = !Array.isArray(value) ? ('attachedTo' in value ? value.attachedTo : undefined) : undefined
$: ignoreObjects = !Array.isArray(value) ? ('_id' in value ? [value._id] : []) : undefined
$: ignoreObjects = getIgnoreObjects(value)
function getIgnoreObjects (issues: Issue | AttachedData<Issue> | Issue[] | IssueDraft): Ref<Issue>[] {
if (!Array.isArray(issues)) {
const own = '_id' in issues ? issues._id : undefined
const childs = 'childInfo' in issues ? issues.childInfo.map((c) => c.childId) : []
return own !== undefined ? [own, ...childs] : childs
} else {
const res = new Set<Ref<Issue>>()
for (const issue of issues) {
const own = '_id' in issue ? issue._id : undefined
const childs = 'childInfo' in issue ? issue.childInfo.map((c) => c.childId) : []
if (own !== undefined) {
res.add(own)
for (const child of childs) {
res.add(child)
}
} else {
for (const child of childs) {
res.add(child)
}
}
}
return [...res]
}
}
</script>
<ObjectPopup
@@ -60,7 +60,7 @@
let presenter: typeof SvelteComponent | undefined
let objectFactory: ObjectFactory | undefined
let items: FindResult<Doc> | undefined
let items: Doc[] = []
let draggingIndex: number | null = null
let hoveringIndex: number | null = null
@@ -163,9 +163,13 @@
$: isLoading = isPresenterLoading || areItemsloading
$: isSortable = hierarchy.getAllAttributes(_class).has('rank')
$: itemsCount = items?.length ?? 0
$: isVertical = direction === 'column'
$: isDraggable = isSortable && items.length > 1 && !areItemsSorting
</script>
<div class="flex-col">
<div class="flex-col" class:w-full={isVertical}>
{#if label || !isAddButtonHidden}
<div class="flex mb-4">
{#if icon}
@@ -199,10 +203,8 @@
{#if isLoading}
<Loading />
{:else if ($$slots.object ?? presenter) && items}
{@const isVertical = direction === 'column'}
<div class="flex-gap-1" class:flex-col={isVertical} class:flex={!isVertical} class:flex-wrap={!isVertical}>
{#each items as item, index (item._id)}
{@const isDraggable = isSortable && items.length > 1 && !areItemsSorting}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="item"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/front-base:v20250310
FROM hardcoreeng/front-base:v20250902
WORKDIR /app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/model.json ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
@@ -27,15 +27,36 @@ import process, {
import { ExecuteResult, ProcessControl } from '@hcengineering/server-process'
import time, { ToDoPriority } from '@hcengineering/time'
export function CheckToDo (
export async function CheckToDoDone (
control: ProcessControl,
execution: Execution,
params: Record<string, any>,
context: Record<string, any>
): boolean {
): Promise<boolean> {
if (params._id === undefined) return false
if (context.todo === undefined) return false
return context.todo._id === params._id
if (context.todo !== undefined) {
return context.todo._id === params._id
} else {
const todo = await control.client.findOne(process.class.ProcessToDo, { _id: params._id })
if (todo === undefined) return false
return todo.doneOn !== null
}
}
export async function CheckToDoCancelled (
control: ProcessControl,
execution: Execution,
params: Record<string, any>,
context: Record<string, any>
): Promise<boolean> {
if (params._id === undefined) return false
if (context.todo !== undefined) {
return context.todo._id === params._id
} else {
const todo = await control.client.findOne(process.class.ProcessToDo, { _id: params._id })
if (todo === undefined) return false
return todo.doneOn === null
}
}
export async function CheckSubProcessesDone (control: ProcessControl, execution: Execution): Promise<boolean> {
@@ -78,7 +78,8 @@ import {
CreateCard,
AddRelation,
AddTag,
CheckToDo,
CheckToDoDone,
CheckToDoCancelled,
OnCardUpdateCheck,
CheckSubProcessesDone,
CheckTime
@@ -355,7 +356,8 @@ export default async () => ({
CreateCard,
AddRelation,
AddTag,
CheckToDo,
CheckToDoDone,
CheckToDoCancelled,
OnCardUpdateCheck,
CheckSubProcessesDone,
CheckTime
+2 -1
View File
@@ -54,7 +54,8 @@ export default plugin(serverProcessId, {
AddRelation: '' as Resource<ExecuteFunc>,
WaitSubProcess: '' as Resource<ExecuteFunc>,
AddTag: '' as Resource<ExecuteFunc>,
CheckToDo: '' as Resource<CheckFunc>,
CheckToDoDone: '' as Resource<CheckFunc>,
CheckToDoCancelled: '' as Resource<CheckFunc>,
OnCardUpdateCheck: '' as Resource<CheckFunc>,
CheckSubProcessesDone: '' as Resource<CheckFunc>,
CheckTime: '' as Resource<CheckFunc>
-8
View File
@@ -1,8 +0,0 @@
FROM hardcoreeng/base:v20250310
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
EXPOSE 3078
CMD [ "node", "bundle.js" ]
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
RUN npm install -g pnpm
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/front-base:v20250310
FROM hardcoreeng/front-base:v20250902
WORKDIR /app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/front-base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /app
COPY bundle/bundle.js ./
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/front-base:v20250310
FROM hardcoreeng/front-base:v20250902
WORKDIR /app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/print-base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+29 -14
View File
@@ -20,6 +20,7 @@ import core, {
getDiffUpdate,
MeasureContext,
Ref,
SortingOrder,
Tx,
TxProcessor,
TxUpdateDoc,
@@ -134,10 +135,14 @@ async function findTransitions (
execution: Execution
): Promise<Transition | undefined> {
if (record.event === process.trigger.OnExecutionStart) {
const transitions = control.client.getModel().findAllSync(process.class.Transition, {
process: execution.process,
trigger: record.event
})
const transitions = control.client.getModel().findAllSync(
process.class.Transition,
{
process: execution.process,
trigger: record.event
},
{ sort: { rank: SortingOrder.Ascending } }
)
return await pickTransition(control, execution, transitions, record.context)
}
if (record.event === process.trigger.OnExecutionContinue) {
@@ -487,11 +492,17 @@ async function checkParent (execution: Execution, control: ProcessControl): Prom
const _process = control.client.getModel().findObject(parent.process)
if (_process === undefined) return
if (parent.status !== ExecutionStatus.Active) return
const transitions = control.client.getModel().findAllSync(process.class.Transition, {
from: parent.currentState,
process: parent.process,
trigger: process.trigger.OnSubProcessesDone
})
const transitions = control.client.getModel().findAllSync(
process.class.Transition,
{
from: parent.currentState,
process: parent.process,
trigger: process.trigger.OnSubProcessesDone
},
{
sort: { rank: SortingOrder.Ascending }
}
)
const transition = await pickTransition(control, execution, transitions, {})
if (transition === undefined) return
await executeTransition(parent, transition, control)
@@ -499,11 +510,15 @@ async function checkParent (execution: Execution, control: ProcessControl): Prom
async function checkNext (control: ProcessControl, execution: Execution): Promise<boolean> {
const autoTriggers = control.client.getModel().findAllSync(process.class.Trigger, { auto: true })
const transitions = control.client.getModel().findAllSync(process.class.Transition, {
from: execution.currentState,
process: execution.process,
trigger: { $in: autoTriggers.map((it) => it._id) }
})
const transitions = control.client.getModel().findAllSync(
process.class.Transition,
{
from: execution.currentState,
process: execution.process,
trigger: { $in: autoTriggers.map((it) => it._id) }
},
{ sort: { rank: SortingOrder.Ascending } }
)
if (transitions.length > 0) {
const doc = await control.client.findOne(cardPlugin.class.Card, { _id: execution.card })
if (doc !== undefined) {
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
@@ -1,4 +1,4 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./
+1 -1
View File
@@ -1,5 +1,5 @@
FROM hardcoreeng/base:v20250310
FROM hardcoreeng/base:v20250902
WORKDIR /usr/src/app
COPY bundle/bundle.js ./