@masterteam/flowplus-workflow 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/flowplus-workflow.css +1 -1
- package/assets/i18n/ar.json +8 -1
- package/assets/i18n/en.json +8 -1
- package/fesm2022/masterteam-flowplus-workflow.mjs +1054 -307
- package/fesm2022/masterteam-flowplus-workflow.mjs.map +1 -1
- package/package.json +4 -4
- package/types/masterteam-flowplus-workflow.d.ts +133 -6
|
@@ -27,7 +27,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
|
27
27
|
import { DateField } from '@masterteam/components/date-field';
|
|
28
28
|
import { ToastService } from '@masterteam/components/toast';
|
|
29
29
|
import * as i1$2 from '@foblex/flow';
|
|
30
|
-
import { FExternalItem, FExternalItemPreview, FFlowModule, EFMarkerType, provideFFlow, withReflowOnResize, EFReflowDeltaSource, EFReflowCollision } from '@foblex/flow';
|
|
30
|
+
import { FExternalItem, FExternalItemPreview, EFResizeHandleType, FFlowModule, EFMarkerType, EFCanvasLayer, provideFFlow, withReflowOnResize, EFReflowDeltaSource, EFReflowCollision } from '@foblex/flow';
|
|
31
31
|
import { Avatar } from '@masterteam/components/avatar';
|
|
32
32
|
import { RadioCardsField } from '@masterteam/components/radio-cards-field';
|
|
33
33
|
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
@@ -1244,16 +1244,16 @@ function defaultApprovalDecisionValues(routeOutputKeys) {
|
|
|
1244
1244
|
function dynamicRouteOutputKeysForConfig$2(nodeType, config) {
|
|
1245
1245
|
if (nodeType === 'ParallelStart') {
|
|
1246
1246
|
return uniqueStrings$2(readArrayRecords$3(config['branches'])
|
|
1247
|
-
.map((branch) => readString$
|
|
1247
|
+
.map((branch) => readString$e(branch, 'key'))
|
|
1248
1248
|
.filter((key) => !!key?.trim()));
|
|
1249
1249
|
}
|
|
1250
1250
|
if (nodeType === 'Switch') {
|
|
1251
1251
|
const caseKeys = readArrayRecords$3(config['cases'])
|
|
1252
|
-
.map((item) => readString$
|
|
1252
|
+
.map((item) => readString$e(item, 'key'))
|
|
1253
1253
|
.filter((key) => !!key?.trim())
|
|
1254
1254
|
.map((key) => switchCaseRouteKey$3(key));
|
|
1255
|
-
const defaultKey = readString$
|
|
1256
|
-
readString$
|
|
1255
|
+
const defaultKey = readString$e(config, 'defaultOutputKey') ??
|
|
1256
|
+
readString$e(config, 'defaultCaseKey') ??
|
|
1257
1257
|
'default';
|
|
1258
1258
|
return uniqueStrings$2([
|
|
1259
1259
|
...caseKeys,
|
|
@@ -1397,7 +1397,7 @@ function readRecord$3(value) {
|
|
|
1397
1397
|
? value
|
|
1398
1398
|
: null;
|
|
1399
1399
|
}
|
|
1400
|
-
function readString$
|
|
1400
|
+
function readString$e(record, key) {
|
|
1401
1401
|
const value = record?.[key];
|
|
1402
1402
|
return typeof value === 'string' ? value : undefined;
|
|
1403
1403
|
}
|
|
@@ -1593,19 +1593,19 @@ function automationBuilderCatalogToWorkflowCatalog(catalog) {
|
|
|
1593
1593
|
const triggerTypes = (catalog.triggerTypes ?? []).map((item) => {
|
|
1594
1594
|
const raw = asRecord$7(item);
|
|
1595
1595
|
const type = catalogTriggerType$2(item);
|
|
1596
|
-
const key = readString$
|
|
1596
|
+
const key = readString$d(raw, 'key') ?? type;
|
|
1597
1597
|
return {
|
|
1598
1598
|
key,
|
|
1599
1599
|
value: type,
|
|
1600
1600
|
label: primaryText(item.displayName) ?? type,
|
|
1601
1601
|
displayName: item.displayName ?? type,
|
|
1602
1602
|
description: item.description ?? null,
|
|
1603
|
-
icon: readString$
|
|
1603
|
+
icon: readString$d(raw, 'icon') ?? readString$d(raw, 'iconKey') ?? null,
|
|
1604
1604
|
metadata: {
|
|
1605
1605
|
automationTriggerType: true,
|
|
1606
1606
|
type,
|
|
1607
1607
|
triggerType: type,
|
|
1608
|
-
category: readString$
|
|
1608
|
+
category: readString$d(raw, 'category') ?? null,
|
|
1609
1609
|
configSchema: item.configSchema ?? null,
|
|
1610
1610
|
authPolicySchema: item.authPolicySchema ?? null,
|
|
1611
1611
|
payloadSchema: item.payloadSchema ?? null,
|
|
@@ -1776,8 +1776,8 @@ function workflowMetadataRequestToAutomationMetadata(request) {
|
|
|
1776
1776
|
name: primaryText(request.name) ?? 'Untitled automation',
|
|
1777
1777
|
};
|
|
1778
1778
|
const description = primaryText(request.description);
|
|
1779
|
-
const ownerId = readString$
|
|
1780
|
-
const projectId = readString$
|
|
1779
|
+
const ownerId = readString$d(metadata, 'ownerId');
|
|
1780
|
+
const projectId = readString$d(metadata, 'projectId');
|
|
1781
1781
|
if (description)
|
|
1782
1782
|
payload.description = description;
|
|
1783
1783
|
if (ownerId)
|
|
@@ -1793,17 +1793,17 @@ function workflowStepToAutomationNodeRequest(step, existing) {
|
|
|
1793
1793
|
};
|
|
1794
1794
|
const key = step.key ??
|
|
1795
1795
|
existing?.key ??
|
|
1796
|
-
readString$
|
|
1796
|
+
readString$d(metadata, 'nodeKey') ??
|
|
1797
1797
|
keyFromText(step.name ?? existing?.name ?? 'node');
|
|
1798
1798
|
const type = String(step.type ?? existing?.type ?? 'SetFields');
|
|
1799
1799
|
const mergedConfig = {
|
|
1800
1800
|
...readConfigFromStep(existing),
|
|
1801
1801
|
...readConfigFromStep(step),
|
|
1802
1802
|
};
|
|
1803
|
-
const configJson = readString$
|
|
1803
|
+
const configJson = readString$d(metadata, 'configJson') ?? stringifyJson$1(mergedConfig) ?? '{}';
|
|
1804
1804
|
const positionJson = layoutToJson(step.layout) ??
|
|
1805
1805
|
layoutToJson(existing?.layout) ??
|
|
1806
|
-
readString$
|
|
1806
|
+
readString$d(metadata, 'positionJson') ??
|
|
1807
1807
|
stringifyJson$1(readRecord$2(metadata, 'position')) ??
|
|
1808
1808
|
'{}';
|
|
1809
1809
|
const nodeType = String(step.type ?? existing?.type ?? 'SetFields');
|
|
@@ -1817,7 +1817,7 @@ function workflowStepToAutomationNodeRequest(step, existing) {
|
|
|
1817
1817
|
timeoutPolicyJson: jsonField(metadata, 'timeoutPolicyJson', '{}'),
|
|
1818
1818
|
retryPolicyJson: jsonField(metadata, 'retryPolicyJson', '{}'),
|
|
1819
1819
|
errorPolicyJson: jsonField(metadata, 'errorPolicyJson', '{}'),
|
|
1820
|
-
sideEffectPolicy: readString$
|
|
1820
|
+
sideEffectPolicy: readString$d(metadata, 'sideEffectPolicy') ??
|
|
1821
1821
|
defaultSideEffectPolicyForNodeType(nodeType),
|
|
1822
1822
|
};
|
|
1823
1823
|
}
|
|
@@ -1850,7 +1850,7 @@ function workflowTriggerToAutomationTriggerRequest(trigger, existing) {
|
|
|
1850
1850
|
...(asRecord$7(trigger.metadata) ?? {}),
|
|
1851
1851
|
};
|
|
1852
1852
|
const type = String(trigger.type ?? existing?.type ?? 'ManualTrigger');
|
|
1853
|
-
const key = readString$
|
|
1853
|
+
const key = readString$d(metadata, 'triggerKey') ??
|
|
1854
1854
|
trigger.webhookKey ??
|
|
1855
1855
|
existing?.webhookKey ??
|
|
1856
1856
|
keyFromText(`${type}_trigger`);
|
|
@@ -1860,7 +1860,7 @@ function workflowTriggerToAutomationTriggerRequest(trigger, existing) {
|
|
|
1860
1860
|
...parseJsonObject$4(trigger.configJson),
|
|
1861
1861
|
...readRecord$2(metadata, 'config'),
|
|
1862
1862
|
};
|
|
1863
|
-
const startNodeKey = readString$
|
|
1863
|
+
const startNodeKey = readString$d(metadata, 'startNodeKey') ?? readString$d(config, 'startNodeKey');
|
|
1864
1864
|
if (startNodeKey)
|
|
1865
1865
|
config['startNodeKey'] = startNodeKey;
|
|
1866
1866
|
return {
|
|
@@ -1897,37 +1897,37 @@ function workflowConnectionToAutomationRouteRequest(connection, index, existing)
|
|
|
1897
1897
|
const targetStepId = readNumber$5(connectionRecord, 'targetStepId') ??
|
|
1898
1898
|
existing?.targetStepId ??
|
|
1899
1899
|
0;
|
|
1900
|
-
const sourceNodeKey = readString$
|
|
1900
|
+
const sourceNodeKey = readString$d(metadata, 'sourceNodeKey') ??
|
|
1901
1901
|
index.nodeKeyByStepId.get(sourceStepId) ??
|
|
1902
1902
|
existing?.sourceStepKey ??
|
|
1903
1903
|
'';
|
|
1904
|
-
const targetNodeKey = readString$
|
|
1904
|
+
const targetNodeKey = readString$d(metadata, 'targetNodeKey') ??
|
|
1905
1905
|
index.nodeKeyByStepId.get(targetStepId) ??
|
|
1906
1906
|
existing?.targetStepKey ??
|
|
1907
1907
|
'';
|
|
1908
|
-
const sourcePortKey = readString$
|
|
1908
|
+
const sourcePortKey = readString$d(connectionRecord, 'sourcePortKey');
|
|
1909
1909
|
const sourceOutputChanged = sourcePortKey != null &&
|
|
1910
1910
|
existing?.sourcePortKey != null &&
|
|
1911
1911
|
normalizeRouteKey(sourcePortKey) !== normalizeRouteKey(existing.sourcePortKey);
|
|
1912
|
-
const sourceOutputKey = readString$
|
|
1912
|
+
const sourceOutputKey = readString$d(connectionMetadata, 'sourceOutputKey') ??
|
|
1913
1913
|
sourcePortKey ??
|
|
1914
1914
|
existing?.sourcePortKey ??
|
|
1915
1915
|
readSelectedActionKey(connection) ??
|
|
1916
1916
|
'';
|
|
1917
|
-
const explicitConditionJson = readString$
|
|
1917
|
+
const explicitConditionJson = readString$d(connectionMetadata, 'conditionJson') ??
|
|
1918
1918
|
readExpressionText(connection);
|
|
1919
1919
|
const preservedConditionJson = sourceOutputChanged
|
|
1920
1920
|
? null
|
|
1921
|
-
: (readString$
|
|
1921
|
+
: (readString$d(existingMetadata, 'conditionJson') ??
|
|
1922
1922
|
existing?.expressionText ??
|
|
1923
1923
|
null);
|
|
1924
1924
|
const conditionJson = explicitConditionJson ??
|
|
1925
1925
|
preservedConditionJson ??
|
|
1926
1926
|
defaultConditionJsonForRoute(sourceOutputKey);
|
|
1927
|
-
const routeType = normalizeAutomationRouteType(readString$
|
|
1928
|
-
(sourceOutputChanged ? null : readString$
|
|
1927
|
+
const routeType = normalizeAutomationRouteType(readString$d(connectionMetadata, 'routeType') ??
|
|
1928
|
+
(sourceOutputChanged ? null : readString$d(existingMetadata, 'routeType')), sourceOutputKey, conditionJson);
|
|
1929
1929
|
return {
|
|
1930
|
-
routeId: readString$
|
|
1930
|
+
routeId: readString$d(metadata, 'routeId') ??
|
|
1931
1931
|
index.routeIdByConnectionId.get(readNumber$5(connectionRecord, 'id') ?? 0) ??
|
|
1932
1932
|
null,
|
|
1933
1933
|
sourceNodeKey,
|
|
@@ -1942,11 +1942,11 @@ function findWorkflowStepByNodeKey(builder, nodeKey) {
|
|
|
1942
1942
|
return builder.steps.find((step) => step.key === nodeKey) ?? null;
|
|
1943
1943
|
}
|
|
1944
1944
|
function findWorkflowTriggerByKey(builder, triggerKey) {
|
|
1945
|
-
return (builder.triggers.find((trigger) => readString$
|
|
1945
|
+
return (builder.triggers.find((trigger) => readString$d(asRecord$7(trigger.metadata), 'triggerKey') === triggerKey) ?? null);
|
|
1946
1946
|
}
|
|
1947
1947
|
function findWorkflowConnectionForRoute(builder, route, routeId) {
|
|
1948
1948
|
if (routeId != null) {
|
|
1949
|
-
const exact = builder.connections.find((connection) => readString$
|
|
1949
|
+
const exact = builder.connections.find((connection) => readString$d(asRecord$7(connection.metadata), 'routeId') ===
|
|
1950
1950
|
String(routeId));
|
|
1951
1951
|
if (exact)
|
|
1952
1952
|
return exact;
|
|
@@ -1958,7 +1958,7 @@ function findWorkflowConnectionForRoute(builder, route, routeId) {
|
|
|
1958
1958
|
function automationNodeToWorkflowStep(node, workflowId, index, triggerStartKeys, routeOutputsByType) {
|
|
1959
1959
|
const raw = asRecord$7(node);
|
|
1960
1960
|
const nodeKey = node.key || keyFromText(node.name ?? `node_${index}`);
|
|
1961
|
-
const nodeType = readString$
|
|
1961
|
+
const nodeType = readString$d(raw, 'type') ?? readString$d(raw, 'nodeType') ?? 'SetFields';
|
|
1962
1962
|
const id = readNumber$5(raw, 'nodeId') ??
|
|
1963
1963
|
readNumber$5(raw, 'id') ??
|
|
1964
1964
|
toWorkflowEntityId(nodeKey, `node:${workflowId}`);
|
|
@@ -2013,11 +2013,11 @@ function automationNodeToWorkflowStep(node, workflowId, index, triggerStartKeys,
|
|
|
2013
2013
|
}
|
|
2014
2014
|
function automationTriggerToWorkflowTrigger(trigger, workflowId, index) {
|
|
2015
2015
|
const raw = asRecord$7(trigger);
|
|
2016
|
-
const triggerType = readString$
|
|
2017
|
-
readString$
|
|
2016
|
+
const triggerType = readString$d(raw, 'type') ??
|
|
2017
|
+
readString$d(raw, 'triggerType') ??
|
|
2018
2018
|
'ManualTrigger';
|
|
2019
2019
|
const triggerKey = trigger.key ||
|
|
2020
|
-
readString$
|
|
2020
|
+
readString$d(raw, 'key') ||
|
|
2021
2021
|
keyFromText(`${triggerType}_trigger`);
|
|
2022
2022
|
const id = readNumber$5(raw, 'triggerId') ??
|
|
2023
2023
|
readNumber$5(raw, 'id') ??
|
|
@@ -2040,7 +2040,7 @@ function automationTriggerToWorkflowTrigger(trigger, workflowId, index) {
|
|
|
2040
2040
|
name: toTranslatableText$1(trigger.name || triggerKey),
|
|
2041
2041
|
enabled,
|
|
2042
2042
|
isEnabled: enabled,
|
|
2043
|
-
webhookKey: readString$
|
|
2043
|
+
webhookKey: readString$d(config, 'webhookKey') ?? triggerKey,
|
|
2044
2044
|
workflowKey: triggerKey,
|
|
2045
2045
|
triggerId: id,
|
|
2046
2046
|
payloadSchema: parseJsonValue$2(trigger.schemaJson ?? null),
|
|
@@ -2058,7 +2058,7 @@ function automationTriggerToWorkflowTrigger(trigger, workflowId, index) {
|
|
|
2058
2058
|
layout,
|
|
2059
2059
|
schemaJson: trigger.schemaJson ?? null,
|
|
2060
2060
|
authenticationPolicyJson: trigger.authenticationPolicyJson ?? null,
|
|
2061
|
-
startNodeKey: readString$
|
|
2061
|
+
startNodeKey: readString$d(config, 'startNodeKey') ?? null,
|
|
2062
2062
|
},
|
|
2063
2063
|
};
|
|
2064
2064
|
}
|
|
@@ -2218,7 +2218,7 @@ function automationDetailToWorkflowLayout(workflowId, steps, connections, trigge
|
|
|
2218
2218
|
function automationNodeTypeToWorkflowStepType(item) {
|
|
2219
2219
|
const raw = asRecord$7(item);
|
|
2220
2220
|
const type = catalogNodeType$1(item);
|
|
2221
|
-
const key = readString$
|
|
2221
|
+
const key = readString$d(raw, 'key') ?? type;
|
|
2222
2222
|
const routeOutputKeys = readStringArray$7(raw, 'routeOutputKeys');
|
|
2223
2223
|
const supportsRetry = ['HTTP', 'FlowPlusCommit', 'CallAutomation'].includes(type) ||
|
|
2224
2224
|
!!item.defaultRetryPolicy;
|
|
@@ -2244,9 +2244,9 @@ function automationNodeTypeToWorkflowStepType(item) {
|
|
|
2244
2244
|
typeKey: type,
|
|
2245
2245
|
displayName: item.displayName ?? type,
|
|
2246
2246
|
description: item.description ?? null,
|
|
2247
|
-
category: readString$
|
|
2248
|
-
icon: readString$
|
|
2249
|
-
readString$
|
|
2247
|
+
category: readString$d(raw, 'category') ?? categoryForNodeType(type),
|
|
2248
|
+
icon: readString$d(raw, 'icon') ??
|
|
2249
|
+
readString$d(raw, 'iconKey') ??
|
|
2250
2250
|
iconForNodeType(type),
|
|
2251
2251
|
colorToken: item.colorToken ?? type,
|
|
2252
2252
|
tags: [type],
|
|
@@ -2322,7 +2322,7 @@ function routeOutputKeysByNodeType(catalog) {
|
|
|
2322
2322
|
for (const item of catalog?.nodeTypes ?? []) {
|
|
2323
2323
|
const raw = asRecord$7(item);
|
|
2324
2324
|
const type = catalogNodeType$1(item);
|
|
2325
|
-
const key = readString$
|
|
2325
|
+
const key = readString$d(raw, 'key') ?? type;
|
|
2326
2326
|
const keys = readStringArray$7(raw, 'routeOutputKeys');
|
|
2327
2327
|
out.set(type, keys);
|
|
2328
2328
|
out.set(key, keys);
|
|
@@ -2349,17 +2349,17 @@ function dynamicRouteOutputKeysForConfig$1(nodeType, config) {
|
|
|
2349
2349
|
if (nodeType === 'ParallelStart') {
|
|
2350
2350
|
const branches = arrayRecords(config['branches']);
|
|
2351
2351
|
return uniqueStrings$1(branches
|
|
2352
|
-
.map((branch) => readString$
|
|
2352
|
+
.map((branch) => readString$d(branch, 'key'))
|
|
2353
2353
|
.filter((key) => !!key?.trim()));
|
|
2354
2354
|
}
|
|
2355
2355
|
if (nodeType === 'Switch') {
|
|
2356
2356
|
const cases = arrayRecords(config['cases']);
|
|
2357
2357
|
const caseKeys = cases
|
|
2358
|
-
.map((item) => readString$
|
|
2358
|
+
.map((item) => readString$d(item, 'key'))
|
|
2359
2359
|
.filter((key) => !!key?.trim())
|
|
2360
2360
|
.map((key) => switchCaseRouteKey$2(key));
|
|
2361
|
-
const defaultKey = readString$
|
|
2362
|
-
readString$
|
|
2361
|
+
const defaultKey = readString$d(config, 'defaultOutputKey') ??
|
|
2362
|
+
readString$d(config, 'defaultCaseKey') ??
|
|
2363
2363
|
'default';
|
|
2364
2364
|
return uniqueStrings$1([
|
|
2365
2365
|
...caseKeys,
|
|
@@ -2400,7 +2400,7 @@ function readConfigFromStep(step) {
|
|
|
2400
2400
|
return {};
|
|
2401
2401
|
const metadata = asRecord$7(step.metadata);
|
|
2402
2402
|
return stripUndefined({
|
|
2403
|
-
...parseJsonObject$4(readString$
|
|
2403
|
+
...parseJsonObject$4(readString$d(metadata, 'configJson')),
|
|
2404
2404
|
...readRecord$2(metadata, 'config'),
|
|
2405
2405
|
automated: step.automated ?? undefined,
|
|
2406
2406
|
plugin: step.plugin ?? undefined,
|
|
@@ -2465,7 +2465,7 @@ function readTriggerStartNodeKey(trigger) {
|
|
|
2465
2465
|
...parseJsonObject$4(trigger.configJson),
|
|
2466
2466
|
...readRecord$2(asRecord$7(trigger), 'config'),
|
|
2467
2467
|
};
|
|
2468
|
-
return readString$
|
|
2468
|
+
return readString$d(config, 'startNodeKey') ?? null;
|
|
2469
2469
|
}
|
|
2470
2470
|
function positionToLayout(workflowId, stepId, stepKey, position, index) {
|
|
2471
2471
|
return {
|
|
@@ -2520,7 +2520,7 @@ function isWorkflowNodeLayout(layout) {
|
|
|
2520
2520
|
return !!layout;
|
|
2521
2521
|
}
|
|
2522
2522
|
function jsonField(record, jsonKey, fallback) {
|
|
2523
|
-
const existing = readString$
|
|
2523
|
+
const existing = readString$d(record, jsonKey);
|
|
2524
2524
|
if (existing != null)
|
|
2525
2525
|
return existing;
|
|
2526
2526
|
const valueKey = jsonKey.replace(/Json$/, '');
|
|
@@ -2531,14 +2531,14 @@ function readSelectedActionKey(value) {
|
|
|
2531
2531
|
const selected = raw['selectedActions'];
|
|
2532
2532
|
if (!Array.isArray(selected) || selected.length === 0)
|
|
2533
2533
|
return null;
|
|
2534
|
-
return readString$
|
|
2534
|
+
return readString$d(asRecord$7(selected[0]), 'actionKey') ?? null;
|
|
2535
2535
|
}
|
|
2536
2536
|
function readExpressionText(value) {
|
|
2537
2537
|
const raw = asRecord$7(value);
|
|
2538
|
-
return (readString$
|
|
2539
|
-
readString$
|
|
2540
|
-
readString$
|
|
2541
|
-
readString$
|
|
2538
|
+
return (readString$d(raw, 'expressionText') ??
|
|
2539
|
+
readString$d(raw, 'expression') ??
|
|
2540
|
+
readString$d(raw, 'formulaRaw') ??
|
|
2541
|
+
readString$d(asRecord$7(raw['formula']), 'expression') ??
|
|
2542
2542
|
null);
|
|
2543
2543
|
}
|
|
2544
2544
|
function categoryForNodeType(type) {
|
|
@@ -2599,23 +2599,23 @@ function defaultSideEffectPolicyForNodeType(type) {
|
|
|
2599
2599
|
}
|
|
2600
2600
|
function catalogNodeType$1(item) {
|
|
2601
2601
|
const raw = asRecord$7(item);
|
|
2602
|
-
return (readString$
|
|
2603
|
-
readString$
|
|
2604
|
-
readString$
|
|
2602
|
+
return (readString$d(raw, 'type') ??
|
|
2603
|
+
readString$d(raw, 'nodeType') ??
|
|
2604
|
+
readString$d(raw, 'key') ??
|
|
2605
2605
|
'SetFields');
|
|
2606
2606
|
}
|
|
2607
2607
|
function catalogTriggerType$2(item) {
|
|
2608
2608
|
const raw = asRecord$7(item);
|
|
2609
|
-
return (readString$
|
|
2610
|
-
readString$
|
|
2611
|
-
readString$
|
|
2609
|
+
return (readString$d(raw, 'type') ??
|
|
2610
|
+
readString$d(raw, 'triggerType') ??
|
|
2611
|
+
readString$d(raw, 'key') ??
|
|
2612
2612
|
'ManualTrigger');
|
|
2613
2613
|
}
|
|
2614
2614
|
function namespaceKey(namespace) {
|
|
2615
2615
|
const raw = asRecord$7(namespace);
|
|
2616
|
-
return (readString$
|
|
2617
|
-
readString$
|
|
2618
|
-
readString$
|
|
2616
|
+
return (readString$d(raw, 'key') ??
|
|
2617
|
+
readString$d(raw, 'name') ??
|
|
2618
|
+
readString$d(raw, 'label') ??
|
|
2619
2619
|
'$json');
|
|
2620
2620
|
}
|
|
2621
2621
|
function namespacePaths(namespace) {
|
|
@@ -2647,9 +2647,9 @@ function primaryText(value) {
|
|
|
2647
2647
|
return value || null;
|
|
2648
2648
|
if (value && typeof value === 'object') {
|
|
2649
2649
|
const raw = value;
|
|
2650
|
-
return (readString$
|
|
2651
|
-
readString$
|
|
2652
|
-
readString$
|
|
2650
|
+
return (readString$d(raw, 'en') ??
|
|
2651
|
+
readString$d(raw, 'display') ??
|
|
2652
|
+
readString$d(raw, 'ar') ??
|
|
2653
2653
|
null);
|
|
2654
2654
|
}
|
|
2655
2655
|
return null;
|
|
@@ -2657,9 +2657,9 @@ function primaryText(value) {
|
|
|
2657
2657
|
function toTranslatableText$1(value) {
|
|
2658
2658
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
2659
2659
|
const raw = value;
|
|
2660
|
-
const en = readString$
|
|
2661
|
-
const ar = readString$
|
|
2662
|
-
const display = readString$
|
|
2660
|
+
const en = readString$d(raw, 'en');
|
|
2661
|
+
const ar = readString$d(raw, 'ar');
|
|
2662
|
+
const display = readString$d(raw, 'display');
|
|
2663
2663
|
return {
|
|
2664
2664
|
...raw,
|
|
2665
2665
|
en: en ?? ar ?? display ?? '',
|
|
@@ -2738,7 +2738,7 @@ function asRecord$7(value) {
|
|
|
2738
2738
|
return {};
|
|
2739
2739
|
return value;
|
|
2740
2740
|
}
|
|
2741
|
-
function readString$
|
|
2741
|
+
function readString$d(record, key) {
|
|
2742
2742
|
const value = record?.[key];
|
|
2743
2743
|
return typeof value === 'string' ? value : undefined;
|
|
2744
2744
|
}
|
|
@@ -2752,31 +2752,31 @@ function readBoolean$6(record, key) {
|
|
|
2752
2752
|
|
|
2753
2753
|
function normalizeWorkflowDefinitionSummaryDto(value) {
|
|
2754
2754
|
const raw = asRecord$6(value);
|
|
2755
|
-
const moduleType = readString$
|
|
2756
|
-
const primaryModuleKey = readString$
|
|
2755
|
+
const moduleType = readString$c(raw, 'moduleType');
|
|
2756
|
+
const primaryModuleKey = readString$c(raw, 'primaryModuleKey');
|
|
2757
2757
|
const isPublished = readBoolean$5(raw, 'isPublished');
|
|
2758
2758
|
const isValid = readBoolean$5(raw, 'isValid');
|
|
2759
2759
|
return {
|
|
2760
2760
|
...spreadAs(raw),
|
|
2761
2761
|
id: readNumber$4(raw, 'id'),
|
|
2762
|
-
key: readString$
|
|
2762
|
+
key: readString$c(raw, 'key'),
|
|
2763
2763
|
name: toTranslatableText(raw['name']),
|
|
2764
2764
|
description: toTranslatableText(raw['description']),
|
|
2765
|
-
status: readString$
|
|
2765
|
+
status: readString$c(raw, 'status') ?? (isPublished ? 'Published' : 'Draft'),
|
|
2766
2766
|
isPublished,
|
|
2767
2767
|
isValid,
|
|
2768
2768
|
primaryModuleId: readNullableNumber(raw, 'primaryModuleId'),
|
|
2769
2769
|
primaryModuleKey,
|
|
2770
2770
|
moduleType,
|
|
2771
|
-
primaryModuleType: readString$
|
|
2772
|
-
operationType: readString$
|
|
2773
|
-
commandName: readString$
|
|
2771
|
+
primaryModuleType: readString$c(raw, 'primaryModuleType') ?? moduleType ?? primaryModuleKey,
|
|
2772
|
+
operationType: readString$c(raw, 'operationType'),
|
|
2773
|
+
commandName: readString$c(raw, 'commandName'),
|
|
2774
2774
|
hasUnpublishedChanges: readNullableBoolean(raw, 'hasUnpublishedChanges'),
|
|
2775
2775
|
version: readNullableNumber(raw, 'version'),
|
|
2776
2776
|
draftVersion: readNullableNumber(raw, 'draftVersion'),
|
|
2777
2777
|
publishedVersion: readNullableNumber(raw, 'publishedVersion'),
|
|
2778
|
-
rowVersion: readString$
|
|
2779
|
-
triggerType: readString$
|
|
2778
|
+
rowVersion: readString$c(raw, 'rowVersion'),
|
|
2779
|
+
triggerType: readString$c(raw, 'triggerType'),
|
|
2780
2780
|
};
|
|
2781
2781
|
}
|
|
2782
2782
|
function normalizeWorkflowDefinitionDto(value) {
|
|
@@ -2784,9 +2784,9 @@ function normalizeWorkflowDefinitionDto(value) {
|
|
|
2784
2784
|
}
|
|
2785
2785
|
function normalizeWorkflowTriggerDto(value) {
|
|
2786
2786
|
const raw = asRecord$6(value);
|
|
2787
|
-
const payloadSchemaJson = readString$
|
|
2787
|
+
const payloadSchemaJson = readString$c(raw, 'payloadSchemaJson') ?? readString$c(raw, 'payloadSchema');
|
|
2788
2788
|
const metadata = readObject$3(raw, 'metadata') ?? {};
|
|
2789
|
-
const parsedConfig = parseJsonObject$3(readString$
|
|
2789
|
+
const parsedConfig = parseJsonObject$3(readString$c(raw, 'configJson'));
|
|
2790
2790
|
if (parsedConfig && !metadata['config'])
|
|
2791
2791
|
metadata['config'] = parsedConfig;
|
|
2792
2792
|
return {
|
|
@@ -2794,8 +2794,8 @@ function normalizeWorkflowTriggerDto(value) {
|
|
|
2794
2794
|
id: readNumber$4(raw, 'id'),
|
|
2795
2795
|
workflowId: readNumber$4(raw, 'workflowId', null) ?? readNumber$4(raw, 'requestSchemaId'),
|
|
2796
2796
|
requestSchemaId: readNullableNumber(raw, 'requestSchemaId'),
|
|
2797
|
-
type: (readString$
|
|
2798
|
-
typeKey: readString$
|
|
2797
|
+
type: (readString$c(raw, 'type') ?? 'Manual'),
|
|
2798
|
+
typeKey: readString$c(raw, 'typeKey'),
|
|
2799
2799
|
name: toTranslatableText(raw['name']),
|
|
2800
2800
|
enabled: readNullableBoolean(raw, 'enabled') ??
|
|
2801
2801
|
readNullableBoolean(raw, 'isEnabled') ??
|
|
@@ -2806,24 +2806,24 @@ function normalizeWorkflowTriggerDto(value) {
|
|
|
2806
2806
|
payloadSchema: parseJsonSchema(payloadSchemaJson) ??
|
|
2807
2807
|
payloadSchemaJson,
|
|
2808
2808
|
payloadSchemaJson,
|
|
2809
|
-
initiationPropertyMappings: readString$
|
|
2809
|
+
initiationPropertyMappings: readString$c(raw, 'initiationPropertyMappings'),
|
|
2810
2810
|
targetProcessSchemaId: readNullableNumber(raw, 'targetProcessSchemaId'),
|
|
2811
2811
|
targetProcessSchemaName: toTranslatableText(raw['targetProcessSchemaName']),
|
|
2812
|
-
expectedHttpMethod: readString$
|
|
2813
|
-
workflowKey: readString$
|
|
2812
|
+
expectedHttpMethod: readString$c(raw, 'expectedHttpMethod'),
|
|
2813
|
+
workflowKey: readString$c(raw, 'workflowKey'),
|
|
2814
2814
|
triggerId: readNullableNumber(raw, 'triggerId') ?? readNullableNumber(raw, 'id'),
|
|
2815
2815
|
allowedContentTypes: readStringArray$6(raw, 'allowedContentTypes'),
|
|
2816
2816
|
examplePayload: raw['examplePayload'],
|
|
2817
|
-
exampleCurl: readString$
|
|
2817
|
+
exampleCurl: readString$c(raw, 'exampleCurl'),
|
|
2818
2818
|
secretConfigured: readNullableBoolean(raw, 'secretConfigured') ??
|
|
2819
2819
|
readNullableBoolean(raw, 'hasSecret') ??
|
|
2820
2820
|
false,
|
|
2821
2821
|
hasSecret: readNullableBoolean(raw, 'hasSecret') ??
|
|
2822
2822
|
readNullableBoolean(raw, 'secretConfigured') ??
|
|
2823
2823
|
false,
|
|
2824
|
-
configJson: readString$
|
|
2825
|
-
schemaJson: readString$
|
|
2826
|
-
authenticationPolicyJson: readString$
|
|
2824
|
+
configJson: readString$c(raw, 'configJson'),
|
|
2825
|
+
schemaJson: readString$c(raw, 'schemaJson'),
|
|
2826
|
+
authenticationPolicyJson: readString$c(raw, 'authenticationPolicyJson'),
|
|
2827
2827
|
metadata,
|
|
2828
2828
|
};
|
|
2829
2829
|
}
|
|
@@ -2836,18 +2836,18 @@ function normalizeWorkflowStepDto(value) {
|
|
|
2836
2836
|
id: readNumber$4(raw, 'id'),
|
|
2837
2837
|
requestSchemaId: readNumber$4(raw, 'requestSchemaId', null) ??
|
|
2838
2838
|
readNumber$4(raw, 'requestSchemaId'),
|
|
2839
|
-
key: readString$
|
|
2839
|
+
key: readString$c(raw, 'key') ?? `step_${readNumber$4(raw, 'id')}`,
|
|
2840
2840
|
name: toTranslatableText(raw['name']),
|
|
2841
2841
|
description: toTranslatableText(raw['description']),
|
|
2842
|
-
type: (readString$
|
|
2843
|
-
typeKey: readString$
|
|
2842
|
+
type: (readString$c(raw, 'type') ?? 'UserInput'),
|
|
2843
|
+
typeKey: readString$c(raw, 'typeKey'),
|
|
2844
2844
|
isInitial: readBoolean$5(raw, 'isInitial'),
|
|
2845
2845
|
isSystem: readBoolean$5(raw, 'isSystem'),
|
|
2846
2846
|
isLocked: readBoolean$5(raw, 'isLocked'),
|
|
2847
|
-
systemKind: readString$
|
|
2848
|
-
targetType: readString$
|
|
2849
|
-
targetValue: readString$
|
|
2850
|
-
groupSelection: readString$
|
|
2847
|
+
systemKind: readString$c(raw, 'systemKind'),
|
|
2848
|
+
targetType: readString$c(raw, 'targetType'),
|
|
2849
|
+
targetValue: readString$c(raw, 'targetValue'),
|
|
2850
|
+
groupSelection: readString$c(raw, 'groupSelection'),
|
|
2851
2851
|
sla: readNullableNumber(raw, 'sla') ?? 0,
|
|
2852
2852
|
slaHours: readNullableNumber(raw, 'slaHours'),
|
|
2853
2853
|
metadata: readObject$3(raw, 'metadata'),
|
|
@@ -2862,7 +2862,7 @@ function normalizeWorkflowStepDto(value) {
|
|
|
2862
2862
|
joinParallel: normalizeJoinParallelConfig(raw['joinParallel']),
|
|
2863
2863
|
layout: normalizeStepLayout(raw['layout']),
|
|
2864
2864
|
validationState: raw['validationState'] ?? null,
|
|
2865
|
-
formBindingMode: readString$
|
|
2865
|
+
formBindingMode: readString$c(raw, 'formBindingMode'),
|
|
2866
2866
|
formId: readNullableNumber(raw, 'formId'),
|
|
2867
2867
|
tags: Array.isArray(raw['tags']) ? raw['tags'] : undefined,
|
|
2868
2868
|
};
|
|
@@ -2873,9 +2873,9 @@ function normalizeWorkflowConnectionDto(value, steps = [], fallbackSelectedActio
|
|
|
2873
2873
|
const targetStepId = readNumber$4(raw, 'targetStepId', null) ?? readNumber$4(raw, 'target');
|
|
2874
2874
|
const sourceStep = steps.find((step) => step.id === sourceStepId);
|
|
2875
2875
|
const selectedActions = normalizeSelectedActions(raw['selectedActions'], sourceStep, fallbackSelectedActions);
|
|
2876
|
-
const expressionText = readString$
|
|
2877
|
-
readString$
|
|
2878
|
-
readString$
|
|
2876
|
+
const expressionText = readString$c(raw, 'expressionText') ??
|
|
2877
|
+
readString$c(raw, 'expression') ??
|
|
2878
|
+
readString$c(raw, 'formulaRaw');
|
|
2879
2879
|
return {
|
|
2880
2880
|
...spreadAs(raw),
|
|
2881
2881
|
id: readNumber$4(raw, 'id'),
|
|
@@ -2885,19 +2885,19 @@ function normalizeWorkflowConnectionDto(value, steps = [], fallbackSelectedActio
|
|
|
2885
2885
|
targetStepId,
|
|
2886
2886
|
source: readNullableNumber(raw, 'source'),
|
|
2887
2887
|
target: readNullableNumber(raw, 'target'),
|
|
2888
|
-
sourceStepKey: readString$
|
|
2889
|
-
targetStepKey: readString$
|
|
2890
|
-
sourcePortKey: readString$
|
|
2888
|
+
sourceStepKey: readString$c(raw, 'sourceStepKey'),
|
|
2889
|
+
targetStepKey: readString$c(raw, 'targetStepKey'),
|
|
2890
|
+
sourcePortKey: readString$c(raw, 'sourcePortKey') ??
|
|
2891
2891
|
selectedActions[0]?.actionKey ??
|
|
2892
2892
|
undefined,
|
|
2893
|
-
targetPortKey: readString$
|
|
2893
|
+
targetPortKey: readString$c(raw, 'targetPortKey') ?? 'in',
|
|
2894
2894
|
priority: readNullableNumber(raw, 'priority') ?? 0,
|
|
2895
2895
|
label: toTranslatableText(raw['label']),
|
|
2896
2896
|
formula: expressionText
|
|
2897
2897
|
? { expression: expressionText }
|
|
2898
2898
|
: null,
|
|
2899
|
-
formulaRaw: readString$
|
|
2900
|
-
expression: readString$
|
|
2899
|
+
formulaRaw: readString$c(raw, 'formulaRaw'),
|
|
2900
|
+
expression: readString$c(raw, 'expression'),
|
|
2901
2901
|
expressionText,
|
|
2902
2902
|
selectedActions,
|
|
2903
2903
|
metadata: readObject$3(raw, 'metadata'),
|
|
@@ -2939,24 +2939,24 @@ function normalizeWorkflowBuilderDto(value) {
|
|
|
2939
2939
|
supports: Array.isArray(raw['supports'])
|
|
2940
2940
|
? raw['supports']
|
|
2941
2941
|
: undefined,
|
|
2942
|
-
rowVersion: readString$
|
|
2942
|
+
rowVersion: readString$c(raw, 'rowVersion') ?? definition.rowVersion ?? null,
|
|
2943
2943
|
};
|
|
2944
2944
|
}
|
|
2945
2945
|
function normalizeWorkflowPluginDescriptorDto(value) {
|
|
2946
2946
|
const raw = asRecord$6(value);
|
|
2947
|
-
const inputSchema = parseJsonSchema(readString$
|
|
2947
|
+
const inputSchema = parseJsonSchema(readString$c(raw, 'inputSchemaJson')) ??
|
|
2948
2948
|
schemaFromPluginFields(raw['inputFields']);
|
|
2949
|
-
const outputSchema = parseJsonSchema(readString$
|
|
2949
|
+
const outputSchema = parseJsonSchema(readString$c(raw, 'outputSchemaJson')) ??
|
|
2950
2950
|
schemaFromPluginFields(raw['outputFields']);
|
|
2951
2951
|
return {
|
|
2952
2952
|
...spreadAs(raw),
|
|
2953
|
-
pluginId: readString$
|
|
2953
|
+
pluginId: readString$c(raw, 'pluginId') ?? '',
|
|
2954
2954
|
displayName: toTranslatableText(raw['displayName']),
|
|
2955
2955
|
description: toTranslatableText(raw['description']),
|
|
2956
2956
|
inputSchema,
|
|
2957
2957
|
outputSchema,
|
|
2958
|
-
inputSchemaJson: readString$
|
|
2959
|
-
outputSchemaJson: readString$
|
|
2958
|
+
inputSchemaJson: readString$c(raw, 'inputSchemaJson'),
|
|
2959
|
+
outputSchemaJson: readString$c(raw, 'outputSchemaJson'),
|
|
2960
2960
|
inputFields: Array.isArray(raw['inputFields'])
|
|
2961
2961
|
? raw['inputFields']
|
|
2962
2962
|
: [],
|
|
@@ -2964,14 +2964,14 @@ function normalizeWorkflowPluginDescriptorDto(value) {
|
|
|
2964
2964
|
? raw['outputFields']
|
|
2965
2965
|
: [],
|
|
2966
2966
|
isAvailable: readNullableBoolean(raw, 'isAvailable'),
|
|
2967
|
-
errorMessage: readString$
|
|
2967
|
+
errorMessage: readString$c(raw, 'errorMessage'),
|
|
2968
2968
|
};
|
|
2969
2969
|
}
|
|
2970
2970
|
function normalizeWorkflowAppDescriptorDto(value) {
|
|
2971
2971
|
const raw = asRecord$6(value);
|
|
2972
2972
|
return {
|
|
2973
2973
|
...spreadAs(raw),
|
|
2974
|
-
appCode: readString$
|
|
2974
|
+
appCode: readString$c(raw, 'appCode') ?? '',
|
|
2975
2975
|
displayName: toTranslatableText(raw['displayName']),
|
|
2976
2976
|
description: toTranslatableText(raw['description']),
|
|
2977
2977
|
actionCount: readNullableNumber(raw, 'actionCount'),
|
|
@@ -2982,16 +2982,16 @@ function normalizeWorkflowAppActionDescriptorDto(value) {
|
|
|
2982
2982
|
const inputSchema = schemaFromAppInputSchema(raw['inputSchema']);
|
|
2983
2983
|
const outputSchema = schemaFromAppOutputSchema(raw['outputSchema']);
|
|
2984
2984
|
const configSchema = readObject$3(raw, 'configSchema')?.['schema'] ??
|
|
2985
|
-
parseJsonSchema(readString$
|
|
2985
|
+
parseJsonSchema(readString$c(raw, 'configSchemaJson'));
|
|
2986
2986
|
return {
|
|
2987
2987
|
...spreadAs(raw),
|
|
2988
|
-
appCode: readString$
|
|
2989
|
-
actionKey: readString$
|
|
2988
|
+
appCode: readString$c(raw, 'appCode'),
|
|
2989
|
+
actionKey: readString$c(raw, 'actionKey') ?? '',
|
|
2990
2990
|
displayName: toTranslatableText(raw['displayName']),
|
|
2991
2991
|
description: toTranslatableText(raw['description']),
|
|
2992
|
-
category: readString$
|
|
2992
|
+
category: readString$c(raw, 'category'),
|
|
2993
2993
|
configSchema: configSchema ?? null,
|
|
2994
|
-
configSchemaJson: readString$
|
|
2994
|
+
configSchemaJson: readString$c(raw, 'configSchemaJson'),
|
|
2995
2995
|
runtimeInputsSchema: inputSchema,
|
|
2996
2996
|
outputsSchema: outputSchema,
|
|
2997
2997
|
inputSchema: Array.isArray(raw['inputSchema'])
|
|
@@ -3028,9 +3028,9 @@ function normalizeWorkflowTestRunResultDto(value) {
|
|
|
3028
3028
|
return {
|
|
3029
3029
|
...spreadAs(raw),
|
|
3030
3030
|
workflowId: readNullableNumber(raw, 'workflowId'),
|
|
3031
|
-
testRunId: readString$
|
|
3031
|
+
testRunId: readString$c(raw, 'testRunId') ??
|
|
3032
3032
|
`workflow_${readNullableNumber(raw, 'workflowId') ?? 'test'}`,
|
|
3033
|
-
status: readString$
|
|
3033
|
+
status: readString$c(raw, 'status') ??
|
|
3034
3034
|
(readNullableBoolean(raw, 'success') === false ? 'Failed' : 'Succeeded'),
|
|
3035
3035
|
success: readNullableBoolean(raw, 'success'),
|
|
3036
3036
|
canStart: readNullableBoolean(raw, 'canStart'),
|
|
@@ -3248,10 +3248,10 @@ function normalizeWorkflowStepActions(value) {
|
|
|
3248
3248
|
return [];
|
|
3249
3249
|
return value.map((item) => {
|
|
3250
3250
|
const raw = asRecord$6(item);
|
|
3251
|
-
const key = readString$
|
|
3252
|
-
readString$
|
|
3253
|
-
readString$
|
|
3254
|
-
readString$
|
|
3251
|
+
const key = readString$c(raw, 'key') ??
|
|
3252
|
+
readString$c(raw, 'typeKey') ??
|
|
3253
|
+
readString$c(raw, 'type') ??
|
|
3254
|
+
readString$c(raw, 'statusKey') ??
|
|
3255
3255
|
'';
|
|
3256
3256
|
return {
|
|
3257
3257
|
...spreadAs(raw),
|
|
@@ -3262,25 +3262,25 @@ function normalizeWorkflowStepActions(value) {
|
|
|
3262
3262
|
stepSchemaId: readNullableNumber(raw, 'stepSchemaId') ?? undefined,
|
|
3263
3263
|
order: readNullableNumber(raw, 'order') ?? undefined,
|
|
3264
3264
|
key,
|
|
3265
|
-
type: readString$
|
|
3266
|
-
typeKey: readString$
|
|
3265
|
+
type: readString$c(raw, 'type'),
|
|
3266
|
+
typeKey: readString$c(raw, 'typeKey'),
|
|
3267
3267
|
label: toTranslatableText(raw['label'] ?? raw['name'] ?? key),
|
|
3268
3268
|
name: toTranslatableText(raw['name'] ?? raw['label'] ?? key),
|
|
3269
|
-
statusKey: readString$
|
|
3270
|
-
color: readString$
|
|
3271
|
-
icon: readString$
|
|
3269
|
+
statusKey: readString$c(raw, 'statusKey'),
|
|
3270
|
+
color: readString$c(raw, 'color'),
|
|
3271
|
+
icon: readString$c(raw, 'icon'),
|
|
3272
3272
|
requireConfirmation: readNullableBoolean(raw, 'requireConfirmation') ?? undefined,
|
|
3273
3273
|
confirmationMessage: toTranslatableText(raw['confirmationMessage']),
|
|
3274
3274
|
requireSignature: readNullableBoolean(raw, 'requireSignature') ?? undefined,
|
|
3275
|
-
routingBehavior: readString$
|
|
3275
|
+
routingBehavior: readString$c(raw, 'routingBehavior'),
|
|
3276
3276
|
routesThroughSelectedActionConnection: readNullableBoolean(raw, 'routesThroughSelectedActionConnection') ??
|
|
3277
3277
|
undefined,
|
|
3278
3278
|
isTerminal: readNullableBoolean(raw, 'isTerminal') ??
|
|
3279
|
-
readString$
|
|
3279
|
+
readString$c(raw, 'routingBehavior') === 'Terminal',
|
|
3280
3280
|
isRouteable: readNullableBoolean(raw, 'isRouteable') ??
|
|
3281
3281
|
readNullableBoolean(raw, 'canRoute') ??
|
|
3282
3282
|
readNullableBoolean(raw, 'routesThroughSelectedActionConnection') ??
|
|
3283
|
-
readString$
|
|
3283
|
+
readString$c(raw, 'routingBehavior') === 'SelectedActionConnection',
|
|
3284
3284
|
canRoute: readNullableBoolean(raw, 'canRoute') ??
|
|
3285
3285
|
readNullableBoolean(raw, 'isRouteable') ??
|
|
3286
3286
|
undefined,
|
|
@@ -3300,9 +3300,9 @@ function normalizeWorkflowStepProperties(value) {
|
|
|
3300
3300
|
readNullableNumber(property, 'id') ??
|
|
3301
3301
|
0,
|
|
3302
3302
|
refId: readNullableNumber(raw, 'refId') ?? undefined,
|
|
3303
|
-
refType: readString$
|
|
3304
|
-
type: readString$
|
|
3305
|
-
propertyKey: readString$
|
|
3303
|
+
refType: readString$c(raw, 'refType'),
|
|
3304
|
+
type: readString$c(raw, 'type'),
|
|
3305
|
+
propertyKey: readString$c(raw, 'propertyKey') ?? readString$c(property, 'key'),
|
|
3306
3306
|
read: readNullableBoolean(raw, 'read') ??
|
|
3307
3307
|
readNullableBoolean(raw, 'isRead') ??
|
|
3308
3308
|
false,
|
|
@@ -3314,9 +3314,9 @@ function normalizeWorkflowStepProperties(value) {
|
|
|
3314
3314
|
property: property
|
|
3315
3315
|
? {
|
|
3316
3316
|
id: readNullableNumber(property, 'id'),
|
|
3317
|
-
key: readString$
|
|
3317
|
+
key: readString$c(property, 'key'),
|
|
3318
3318
|
name: toTranslatableText(property['name']),
|
|
3319
|
-
viewType: readString$
|
|
3319
|
+
viewType: readString$c(property, 'viewType'),
|
|
3320
3320
|
isRequired: readNullableBoolean(property, 'isRequired') ?? undefined,
|
|
3321
3321
|
isTranslatable: readNullableBoolean(property, 'isTranslatable') ?? undefined,
|
|
3322
3322
|
}
|
|
@@ -3330,25 +3330,25 @@ function normalizeAutomatedConfig(value) {
|
|
|
3330
3330
|
const raw = asRecord$6(value);
|
|
3331
3331
|
return {
|
|
3332
3332
|
...spreadAs(raw),
|
|
3333
|
-
method: readString$
|
|
3334
|
-
serviceUrl: readString$
|
|
3335
|
-
url: readString$
|
|
3333
|
+
method: readString$c(raw, 'method') ?? 'POST',
|
|
3334
|
+
serviceUrl: readString$c(raw, 'serviceUrl') ?? readString$c(raw, 'url'),
|
|
3335
|
+
url: readString$c(raw, 'url') ?? readString$c(raw, 'serviceUrl'),
|
|
3336
3336
|
timeoutSeconds: readNullableNumber(raw, 'timeoutSeconds'),
|
|
3337
3337
|
retryCount: readNullableNumber(raw, 'retryCount'),
|
|
3338
3338
|
retryDelaySeconds: readNullableNumber(raw, 'retryDelaySeconds'),
|
|
3339
|
-
onFailureBehavior: readString$
|
|
3340
|
-
readString$
|
|
3341
|
-
failureBehavior: readString$
|
|
3342
|
-
readString$
|
|
3339
|
+
onFailureBehavior: readString$c(raw, 'onFailureBehavior') ??
|
|
3340
|
+
readString$c(raw, 'failureBehavior'),
|
|
3341
|
+
failureBehavior: readString$c(raw, 'failureBehavior') ??
|
|
3342
|
+
readString$c(raw, 'onFailureBehavior'),
|
|
3343
3343
|
headers: pairsFromUnknown(raw['headers']),
|
|
3344
3344
|
headersMap: readStringRecord(raw['headers']),
|
|
3345
3345
|
query: pairsFromUnknown(raw['query'] ?? raw['queryParameters'] ?? raw['queryParams']),
|
|
3346
3346
|
queryParameters: readStringRecord(raw['queryParameters'] ?? raw['queryParams']),
|
|
3347
3347
|
queryParams: readStringRecord(raw['queryParams'] ?? raw['queryParameters']),
|
|
3348
|
-
jsonBody: readString$
|
|
3349
|
-
body: readString$
|
|
3350
|
-
bodyType: readString$
|
|
3351
|
-
bodyKind: readString$
|
|
3348
|
+
jsonBody: readString$c(raw, 'jsonBody') ?? readString$c(raw, 'body'),
|
|
3349
|
+
body: readString$c(raw, 'body') ?? readString$c(raw, 'jsonBody'),
|
|
3350
|
+
bodyType: readString$c(raw, 'bodyType'),
|
|
3351
|
+
bodyKind: readString$c(raw, 'bodyKind'),
|
|
3352
3352
|
outputs: normalizeAutomatedOutputMappings(raw['outputs'] ?? raw['outputMappings']),
|
|
3353
3353
|
outputMappings: normalizeAutomatedOutputMappings(raw['outputMappings'] ?? raw['outputs']),
|
|
3354
3354
|
placeholders: readStringRecord(raw['placeholders']),
|
|
@@ -3367,17 +3367,17 @@ function normalizePluginConfig(value) {
|
|
|
3367
3367
|
: [];
|
|
3368
3368
|
return {
|
|
3369
3369
|
...spreadAs(raw),
|
|
3370
|
-
pluginId: readString$
|
|
3371
|
-
inputSchemaJson: readString$
|
|
3372
|
-
outputSchemaJson: readString$
|
|
3370
|
+
pluginId: readString$c(raw, 'pluginId'),
|
|
3371
|
+
inputSchemaJson: readString$c(raw, 'inputSchemaJson'),
|
|
3372
|
+
outputSchemaJson: readString$c(raw, 'outputSchemaJson'),
|
|
3373
3373
|
waitForCompletion: readNullableBoolean(raw, 'waitForCompletion') ?? true,
|
|
3374
3374
|
timeoutSeconds: readNullableNumber(raw, 'timeoutSeconds'),
|
|
3375
3375
|
retryCount: readNullableNumber(raw, 'retryCount'),
|
|
3376
3376
|
retryDelaySeconds: readNullableNumber(raw, 'retryDelaySeconds'),
|
|
3377
|
-
onFailureBehavior: readString$
|
|
3378
|
-
readString$
|
|
3379
|
-
failureBehavior: readString$
|
|
3380
|
-
readString$
|
|
3377
|
+
onFailureBehavior: readString$c(raw, 'onFailureBehavior') ??
|
|
3378
|
+
readString$c(raw, 'failureBehavior'),
|
|
3379
|
+
failureBehavior: readString$c(raw, 'failureBehavior') ??
|
|
3380
|
+
readString$c(raw, 'onFailureBehavior'),
|
|
3381
3381
|
skipInputValidation: readNullableBoolean(raw, 'skipInputValidation') ?? undefined,
|
|
3382
3382
|
inputs: Array.isArray(raw['inputs']) && raw['inputs'].length > 0
|
|
3383
3383
|
? raw['inputs']
|
|
@@ -3404,10 +3404,10 @@ function normalizeAppActionConfig(value) {
|
|
|
3404
3404
|
: [];
|
|
3405
3405
|
return {
|
|
3406
3406
|
...spreadAs(raw),
|
|
3407
|
-
appCode: readString$
|
|
3408
|
-
actionKey: readString$
|
|
3409
|
-
configJson: readString$
|
|
3410
|
-
config: parseJsonObject$3(readString$
|
|
3407
|
+
appCode: readString$c(raw, 'appCode'),
|
|
3408
|
+
actionKey: readString$c(raw, 'actionKey') ?? '',
|
|
3409
|
+
configJson: readString$c(raw, 'configJson'),
|
|
3410
|
+
config: parseJsonObject$3(readString$c(raw, 'configJson')) ??
|
|
3411
3411
|
readObject$3(raw, 'config') ??
|
|
3412
3412
|
{},
|
|
3413
3413
|
configMappings,
|
|
@@ -3419,7 +3419,7 @@ function normalizeAppActionConfig(value) {
|
|
|
3419
3419
|
? raw['outputs']
|
|
3420
3420
|
: outputMappings.map((mapping) => normalizeAppOutput(mapping)),
|
|
3421
3421
|
outputMappings,
|
|
3422
|
-
failureBehavior: readString$
|
|
3422
|
+
failureBehavior: readString$c(raw, 'failureBehavior'),
|
|
3423
3423
|
timeoutSeconds: readNullableNumber(raw, 'timeoutSeconds'),
|
|
3424
3424
|
};
|
|
3425
3425
|
}
|
|
@@ -3470,7 +3470,7 @@ function normalizeJoinParallelConfig(value) {
|
|
|
3470
3470
|
const anyBranchApprove = readNullableBoolean(raw, 'anyBranchApprove') ?? false;
|
|
3471
3471
|
return {
|
|
3472
3472
|
...spreadAs(raw),
|
|
3473
|
-
policy: readString$
|
|
3473
|
+
policy: readString$c(raw, 'policy') ?? (anyBranchApprove ? 'Any' : 'All'),
|
|
3474
3474
|
anyBranchApprove,
|
|
3475
3475
|
threshold: readNullableNumber(raw, 'threshold'),
|
|
3476
3476
|
customCondition: raw['customCondition'] ??
|
|
@@ -3501,12 +3501,12 @@ function normalizeSelectedActions(value, sourceStep, fallbackSelectedActions = [
|
|
|
3501
3501
|
return {
|
|
3502
3502
|
stepActionId: stepActionId ?? undefined,
|
|
3503
3503
|
actionId: stepActionId ?? undefined,
|
|
3504
|
-
actionKey: readString$
|
|
3505
|
-
readString$
|
|
3506
|
-
readString$
|
|
3507
|
-
readString$
|
|
3504
|
+
actionKey: readString$c(raw, 'actionKey') ??
|
|
3505
|
+
readString$c(raw, 'key') ??
|
|
3506
|
+
readString$c(raw, 'typeKey') ??
|
|
3507
|
+
readString$c(raw, 'statusKey') ??
|
|
3508
3508
|
'',
|
|
3509
|
-
key: readString$
|
|
3509
|
+
key: readString$c(raw, 'key'),
|
|
3510
3510
|
};
|
|
3511
3511
|
})
|
|
3512
3512
|
.filter((item) => item.actionKey);
|
|
@@ -3564,12 +3564,12 @@ function normalizeAutomatedOutputMappings(value) {
|
|
|
3564
3564
|
return value.map((item) => {
|
|
3565
3565
|
const raw = asRecord$6(item);
|
|
3566
3566
|
return {
|
|
3567
|
-
source: readString$
|
|
3568
|
-
targetPath: readString$
|
|
3569
|
-
jsonPath: readString$
|
|
3570
|
-
contextPath: readString$
|
|
3571
|
-
writePolicy: readString$
|
|
3572
|
-
valueType: readString$
|
|
3567
|
+
source: readString$c(raw, 'source') ?? readString$c(raw, 'jsonPath') ?? 'response',
|
|
3568
|
+
targetPath: readString$c(raw, 'targetPath') ?? readString$c(raw, 'contextPath') ?? '',
|
|
3569
|
+
jsonPath: readString$c(raw, 'jsonPath'),
|
|
3570
|
+
contextPath: readString$c(raw, 'contextPath'),
|
|
3571
|
+
writePolicy: readString$c(raw, 'writePolicy'),
|
|
3572
|
+
valueType: readString$c(raw, 'valueType'),
|
|
3573
3573
|
isSecret: readNullableBoolean(raw, 'isSecret') ?? undefined,
|
|
3574
3574
|
};
|
|
3575
3575
|
});
|
|
@@ -3578,27 +3578,27 @@ function normalizePluginInput(value) {
|
|
|
3578
3578
|
const raw = asRecord$6(value);
|
|
3579
3579
|
if (readNullableNumber(raw, 'requestPropertyId') != null) {
|
|
3580
3580
|
return {
|
|
3581
|
-
field: readString$
|
|
3581
|
+
field: readString$c(raw, 'pluginInputFieldName') ?? '',
|
|
3582
3582
|
source: 'Property',
|
|
3583
3583
|
value: readNullableNumber(raw, 'requestPropertyId'),
|
|
3584
3584
|
};
|
|
3585
3585
|
}
|
|
3586
|
-
if (readString$
|
|
3586
|
+
if (readString$c(raw, 'contextPath')) {
|
|
3587
3587
|
return {
|
|
3588
|
-
field: readString$
|
|
3588
|
+
field: readString$c(raw, 'pluginInputFieldName') ?? '',
|
|
3589
3589
|
source: 'Context',
|
|
3590
|
-
value: readString$
|
|
3590
|
+
value: readString$c(raw, 'contextPath') ?? '',
|
|
3591
3591
|
};
|
|
3592
3592
|
}
|
|
3593
|
-
if (readString$
|
|
3593
|
+
if (readString$c(raw, 'transformExpression')) {
|
|
3594
3594
|
return {
|
|
3595
|
-
field: readString$
|
|
3595
|
+
field: readString$c(raw, 'pluginInputFieldName') ?? '',
|
|
3596
3596
|
source: 'Expression',
|
|
3597
|
-
value: readString$
|
|
3597
|
+
value: readString$c(raw, 'transformExpression') ?? '',
|
|
3598
3598
|
};
|
|
3599
3599
|
}
|
|
3600
3600
|
return {
|
|
3601
|
-
field: readString$
|
|
3601
|
+
field: readString$c(raw, 'pluginInputFieldName') ?? '',
|
|
3602
3602
|
source: 'Static',
|
|
3603
3603
|
value: raw['staticValue'],
|
|
3604
3604
|
};
|
|
@@ -3606,35 +3606,35 @@ function normalizePluginInput(value) {
|
|
|
3606
3606
|
function normalizePluginOutput(value) {
|
|
3607
3607
|
const raw = asRecord$6(value);
|
|
3608
3608
|
return {
|
|
3609
|
-
field: readString$
|
|
3610
|
-
targetPath: readString$
|
|
3609
|
+
field: readString$c(raw, 'pluginOutputFieldName') ?? '',
|
|
3610
|
+
targetPath: readString$c(raw, 'contextPath') ?? readString$c(raw, 'targetPath') ?? '',
|
|
3611
3611
|
};
|
|
3612
3612
|
}
|
|
3613
3613
|
function normalizeAppRuntimeInput(value) {
|
|
3614
3614
|
const raw = asRecord$6(value);
|
|
3615
3615
|
if (readNullableNumber(raw, 'requestPropertyId') != null) {
|
|
3616
3616
|
return {
|
|
3617
|
-
field: readString$
|
|
3617
|
+
field: readString$c(raw, 'fieldKey') ?? '',
|
|
3618
3618
|
source: 'Property',
|
|
3619
3619
|
value: readNullableNumber(raw, 'requestPropertyId'),
|
|
3620
3620
|
};
|
|
3621
3621
|
}
|
|
3622
|
-
if (readString$
|
|
3622
|
+
if (readString$c(raw, 'contextPath')) {
|
|
3623
3623
|
return {
|
|
3624
|
-
field: readString$
|
|
3624
|
+
field: readString$c(raw, 'fieldKey') ?? '',
|
|
3625
3625
|
source: 'Context',
|
|
3626
|
-
value: readString$
|
|
3626
|
+
value: readString$c(raw, 'contextPath') ?? '',
|
|
3627
3627
|
};
|
|
3628
3628
|
}
|
|
3629
|
-
if (readString$
|
|
3629
|
+
if (readString$c(raw, 'transformExpression')) {
|
|
3630
3630
|
return {
|
|
3631
|
-
field: readString$
|
|
3631
|
+
field: readString$c(raw, 'fieldKey') ?? '',
|
|
3632
3632
|
source: 'Expression',
|
|
3633
|
-
value: readString$
|
|
3633
|
+
value: readString$c(raw, 'transformExpression') ?? '',
|
|
3634
3634
|
};
|
|
3635
3635
|
}
|
|
3636
3636
|
return {
|
|
3637
|
-
field: readString$
|
|
3637
|
+
field: readString$c(raw, 'fieldKey') ?? '',
|
|
3638
3638
|
source: 'Static',
|
|
3639
3639
|
value: raw['staticValue'],
|
|
3640
3640
|
};
|
|
@@ -3642,8 +3642,8 @@ function normalizeAppRuntimeInput(value) {
|
|
|
3642
3642
|
function normalizeAppOutput(value) {
|
|
3643
3643
|
const raw = asRecord$6(value);
|
|
3644
3644
|
return {
|
|
3645
|
-
field: readString$
|
|
3646
|
-
targetPath: readString$
|
|
3645
|
+
field: readString$c(raw, 'fieldKey') ?? '',
|
|
3646
|
+
targetPath: readString$c(raw, 'contextPath') ?? readString$c(raw, 'targetPath') ?? '',
|
|
3647
3647
|
};
|
|
3648
3648
|
}
|
|
3649
3649
|
function normalizeSubprocessPropertyMapping(value) {
|
|
@@ -3654,23 +3654,23 @@ function normalizeSubprocessPropertyMapping(value) {
|
|
|
3654
3654
|
parentRequestPropertyId: readNullableNumber(raw, 'parentRequestPropertyId') ?? undefined,
|
|
3655
3655
|
subRequestPropertyId: readNullableNumber(raw, 'subRequestPropertyId') ?? undefined,
|
|
3656
3656
|
reverseMapping: readNullableBoolean(raw, 'reverseMapping') ?? undefined,
|
|
3657
|
-
parentPath: readString$
|
|
3657
|
+
parentPath: readString$c(raw, 'parentPath') ??
|
|
3658
3658
|
String(readNullableNumber(raw, 'parentRequestPropertyId') ?? ''),
|
|
3659
|
-
childPath: readString$
|
|
3659
|
+
childPath: readString$c(raw, 'childPath') ??
|
|
3660
3660
|
String(readNullableNumber(raw, 'subRequestPropertyId') ?? ''),
|
|
3661
|
-
direction: readString$
|
|
3661
|
+
direction: readString$c(raw, 'direction') ??
|
|
3662
3662
|
(readNullableBoolean(raw, 'reverseMapping') ? 'Both' : 'In'),
|
|
3663
3663
|
required: readNullableBoolean(raw, 'required') ?? undefined,
|
|
3664
|
-
transform: readString$
|
|
3664
|
+
transform: readString$c(raw, 'transform'),
|
|
3665
3665
|
};
|
|
3666
3666
|
}
|
|
3667
3667
|
function normalizeSubprocessContextMapping(value) {
|
|
3668
3668
|
const raw = asRecord$6(value);
|
|
3669
3669
|
return {
|
|
3670
|
-
parentPath: readString$
|
|
3671
|
-
childPath: readString$
|
|
3672
|
-
direction: readString$
|
|
3673
|
-
transform: readString$
|
|
3670
|
+
parentPath: readString$c(raw, 'parentPath') ?? '',
|
|
3671
|
+
childPath: readString$c(raw, 'childPath') ?? '',
|
|
3672
|
+
direction: readString$c(raw, 'direction') ?? 'In',
|
|
3673
|
+
transform: readString$c(raw, 'transform'),
|
|
3674
3674
|
};
|
|
3675
3675
|
}
|
|
3676
3676
|
function normalizeActionsForPayload(actions) {
|
|
@@ -3721,14 +3721,14 @@ function normalizePluginInputsForPayload(mappings) {
|
|
|
3721
3721
|
if ('pluginInputFieldName' in raw || 'contextPath' in raw) {
|
|
3722
3722
|
return { ...raw };
|
|
3723
3723
|
}
|
|
3724
|
-
const source = readString$
|
|
3724
|
+
const source = readString$c(raw, 'source') ?? 'Context';
|
|
3725
3725
|
return {
|
|
3726
3726
|
id: 0,
|
|
3727
|
-
pluginInputFieldName: readString$
|
|
3727
|
+
pluginInputFieldName: readString$c(raw, 'field') ?? '',
|
|
3728
3728
|
requestPropertyId: source === 'Property' ? readNullableNumber(raw, 'value') : undefined,
|
|
3729
|
-
contextPath: source === 'Context' ? (readString$
|
|
3729
|
+
contextPath: source === 'Context' ? (readString$c(raw, 'value') ?? '') : undefined,
|
|
3730
3730
|
staticValue: source === 'Static' ? raw['value'] : undefined,
|
|
3731
|
-
transformExpression: source === 'Expression' ? (readString$
|
|
3731
|
+
transformExpression: source === 'Expression' ? (readString$c(raw, 'value') ?? '') : undefined,
|
|
3732
3732
|
};
|
|
3733
3733
|
});
|
|
3734
3734
|
}
|
|
@@ -3742,9 +3742,9 @@ function normalizePluginOutputsForPayload(mappings) {
|
|
|
3742
3742
|
}
|
|
3743
3743
|
return {
|
|
3744
3744
|
id: 0,
|
|
3745
|
-
pluginOutputFieldName: readString$
|
|
3746
|
-
contextPath: readString$
|
|
3747
|
-
transformExpression: readString$
|
|
3745
|
+
pluginOutputFieldName: readString$c(raw, 'field') ?? '',
|
|
3746
|
+
contextPath: readString$c(raw, 'targetPath') ?? readString$c(raw, 'contextPath') ?? '',
|
|
3747
|
+
transformExpression: readString$c(raw, 'transformExpression') ?? undefined,
|
|
3748
3748
|
};
|
|
3749
3749
|
});
|
|
3750
3750
|
}
|
|
@@ -3760,17 +3760,17 @@ function normalizeAppActionMappingsForPayload(mappings, kind) {
|
|
|
3760
3760
|
}
|
|
3761
3761
|
if (kind === 'output') {
|
|
3762
3762
|
return {
|
|
3763
|
-
fieldKey: readString$
|
|
3764
|
-
contextPath: readString$
|
|
3763
|
+
fieldKey: readString$c(raw, 'field') ?? '',
|
|
3764
|
+
contextPath: readString$c(raw, 'targetPath') ?? readString$c(raw, 'contextPath') ?? '',
|
|
3765
3765
|
};
|
|
3766
3766
|
}
|
|
3767
|
-
const source = readString$
|
|
3767
|
+
const source = readString$c(raw, 'source') ?? 'Context';
|
|
3768
3768
|
return {
|
|
3769
|
-
fieldKey: readString$
|
|
3769
|
+
fieldKey: readString$c(raw, 'field') ?? '',
|
|
3770
3770
|
requestPropertyId: source === 'Property' ? readNullableNumber(raw, 'value') : undefined,
|
|
3771
|
-
contextPath: source === 'Context' ? (readString$
|
|
3771
|
+
contextPath: source === 'Context' ? (readString$c(raw, 'value') ?? '') : undefined,
|
|
3772
3772
|
staticValue: source === 'Static' ? raw['value'] : undefined,
|
|
3773
|
-
transformExpression: source === 'Expression' ? (readString$
|
|
3773
|
+
transformExpression: source === 'Expression' ? (readString$c(raw, 'value') ?? '') : undefined,
|
|
3774
3774
|
};
|
|
3775
3775
|
});
|
|
3776
3776
|
}
|
|
@@ -3808,7 +3808,7 @@ function normalizeContextSnapshot(value) {
|
|
|
3808
3808
|
const snapshot = {};
|
|
3809
3809
|
for (const item of value) {
|
|
3810
3810
|
const raw = asRecord$6(item);
|
|
3811
|
-
const path = readString$
|
|
3811
|
+
const path = readString$c(raw, 'path');
|
|
3812
3812
|
if (!path)
|
|
3813
3813
|
continue;
|
|
3814
3814
|
snapshot[path] = raw['value'];
|
|
@@ -3822,12 +3822,12 @@ function schemaFromPluginFields(value) {
|
|
|
3822
3822
|
const required = [];
|
|
3823
3823
|
for (const item of value) {
|
|
3824
3824
|
const raw = asRecord$6(item);
|
|
3825
|
-
const key = readString$
|
|
3825
|
+
const key = readString$c(raw, 'name');
|
|
3826
3826
|
if (!key)
|
|
3827
3827
|
continue;
|
|
3828
3828
|
properties[key] = {
|
|
3829
|
-
type: readString$
|
|
3830
|
-
description: readString$
|
|
3829
|
+
type: readString$c(raw, 'type') ?? 'string',
|
|
3830
|
+
description: readString$c(raw, 'description') ?? '',
|
|
3831
3831
|
};
|
|
3832
3832
|
if (readNullableBoolean(raw, 'required'))
|
|
3833
3833
|
required.push(key);
|
|
@@ -3841,12 +3841,12 @@ function schemaFromAppInputSchema(value) {
|
|
|
3841
3841
|
const required = [];
|
|
3842
3842
|
for (const item of value) {
|
|
3843
3843
|
const raw = asRecord$6(item);
|
|
3844
|
-
const key = readString$
|
|
3844
|
+
const key = readString$c(raw, 'key');
|
|
3845
3845
|
if (!key)
|
|
3846
3846
|
continue;
|
|
3847
3847
|
properties[key] = {
|
|
3848
3848
|
type: 'string',
|
|
3849
|
-
description: readString$
|
|
3849
|
+
description: readString$c(raw, 'source') ?? '',
|
|
3850
3850
|
};
|
|
3851
3851
|
if (readNullableBoolean(raw, 'required'))
|
|
3852
3852
|
required.push(key);
|
|
@@ -3859,12 +3859,12 @@ function schemaFromAppOutputSchema(value) {
|
|
|
3859
3859
|
const properties = {};
|
|
3860
3860
|
for (const item of value) {
|
|
3861
3861
|
const raw = asRecord$6(item);
|
|
3862
|
-
const key = readString$
|
|
3862
|
+
const key = readString$c(raw, 'key');
|
|
3863
3863
|
if (!key)
|
|
3864
3864
|
continue;
|
|
3865
3865
|
properties[key] = {
|
|
3866
|
-
type: readString$
|
|
3867
|
-
description: readString$
|
|
3866
|
+
type: readString$c(raw, 'type') ?? 'object',
|
|
3867
|
+
description: readString$c(raw, 'description') ?? '',
|
|
3868
3868
|
};
|
|
3869
3869
|
}
|
|
3870
3870
|
return { type: 'object', properties };
|
|
@@ -3872,9 +3872,9 @@ function schemaFromAppOutputSchema(value) {
|
|
|
3872
3872
|
function toTranslatableText(value) {
|
|
3873
3873
|
if (value && typeof value === 'object') {
|
|
3874
3874
|
const raw = value;
|
|
3875
|
-
const en = readString$
|
|
3876
|
-
const ar = readString$
|
|
3877
|
-
const display = readString$
|
|
3875
|
+
const en = readString$c(raw, 'en');
|
|
3876
|
+
const ar = readString$c(raw, 'ar');
|
|
3877
|
+
const display = readString$c(raw, 'display');
|
|
3878
3878
|
return {
|
|
3879
3879
|
en: en ?? ar ?? display ?? '',
|
|
3880
3880
|
ar: ar ?? en ?? display ?? '',
|
|
@@ -3889,9 +3889,9 @@ function toPrimaryText(value) {
|
|
|
3889
3889
|
return value || undefined;
|
|
3890
3890
|
if (value && typeof value === 'object') {
|
|
3891
3891
|
const raw = value;
|
|
3892
|
-
return (readString$
|
|
3893
|
-
readString$
|
|
3894
|
-
readString$
|
|
3892
|
+
return (readString$c(raw, 'en') ??
|
|
3893
|
+
readString$c(raw, 'display') ??
|
|
3894
|
+
readString$c(raw, 'ar') ??
|
|
3895
3895
|
undefined);
|
|
3896
3896
|
}
|
|
3897
3897
|
return undefined;
|
|
@@ -3913,8 +3913,8 @@ function pairsFromUnknown(value) {
|
|
|
3913
3913
|
return value
|
|
3914
3914
|
.map((item) => asRecord$6(item))
|
|
3915
3915
|
.map((item) => ({
|
|
3916
|
-
key: readString$
|
|
3917
|
-
value: readString$
|
|
3916
|
+
key: readString$c(item, 'key') ?? '',
|
|
3917
|
+
value: readString$c(item, 'value') ?? '',
|
|
3918
3918
|
}));
|
|
3919
3919
|
}
|
|
3920
3920
|
return Object.entries(readStringRecord(value) ?? {}).map(([key, recordValue]) => ({
|
|
@@ -3981,7 +3981,7 @@ function readObject$3(record, key) {
|
|
|
3981
3981
|
return null;
|
|
3982
3982
|
return value;
|
|
3983
3983
|
}
|
|
3984
|
-
function readString$
|
|
3984
|
+
function readString$c(record, key) {
|
|
3985
3985
|
const value = record[key];
|
|
3986
3986
|
return typeof value === 'string' ? value : undefined;
|
|
3987
3987
|
}
|
|
@@ -4918,7 +4918,7 @@ function normalizePathValidation(paths, response) {
|
|
|
4918
4918
|
}
|
|
4919
4919
|
return {
|
|
4920
4920
|
results: raw.map((item, index) => {
|
|
4921
|
-
const path = readString$
|
|
4921
|
+
const path = readString$b(item, 'path') ?? readString$b(item, 'expression');
|
|
4922
4922
|
const valid = readBoolean$4(item, 'isValid') ??
|
|
4923
4923
|
readBoolean$4(item, 'valid') ??
|
|
4924
4924
|
readBoolean$4(item, 'success') ??
|
|
@@ -4930,8 +4930,8 @@ function normalizePathValidation(paths, response) {
|
|
|
4930
4930
|
path: path ?? paths[index] ?? '',
|
|
4931
4931
|
isValid: valid,
|
|
4932
4932
|
isAvailable: available,
|
|
4933
|
-
type: readString$
|
|
4934
|
-
message: readString$
|
|
4933
|
+
type: readString$b(item, 'type'),
|
|
4934
|
+
message: readString$b(item, 'message') ?? readString$b(item, 'error'),
|
|
4935
4935
|
};
|
|
4936
4936
|
}),
|
|
4937
4937
|
};
|
|
@@ -4950,7 +4950,7 @@ function asRecordArray(value) {
|
|
|
4950
4950
|
return null;
|
|
4951
4951
|
return value.filter((item) => !!item && typeof item === 'object' && !Array.isArray(item));
|
|
4952
4952
|
}
|
|
4953
|
-
function readString$
|
|
4953
|
+
function readString$b(source, key) {
|
|
4954
4954
|
const value = source[key];
|
|
4955
4955
|
return typeof value === 'string' ? value : null;
|
|
4956
4956
|
}
|
|
@@ -5101,8 +5101,8 @@ function normalizeExecutionListResult(result) {
|
|
|
5101
5101
|
...result,
|
|
5102
5102
|
items,
|
|
5103
5103
|
hasMore: readBoolean$3(raw, 'hasMore') ?? result.hasMore,
|
|
5104
|
-
nextCursor: readString$
|
|
5105
|
-
buildCursor(readString$
|
|
5104
|
+
nextCursor: readString$a(raw, 'nextCursor') ??
|
|
5105
|
+
buildCursor(readString$a(raw, 'nextCursorStartedAtUtc'), readId$3(raw, 'nextCursorExecutionId')),
|
|
5106
5106
|
};
|
|
5107
5107
|
}
|
|
5108
5108
|
function normalizeExecutionDetail(detail) {
|
|
@@ -5116,11 +5116,11 @@ function normalizeExecutionDetail(detail) {
|
|
|
5116
5116
|
? readArray$1(raw, 'events')
|
|
5117
5117
|
: readArray$1(raw, 'timeline')).map(normalizeExecutionEvent);
|
|
5118
5118
|
const triggerSummary = raw['triggerSummary'] ??
|
|
5119
|
-
parseJsonValue$1(readString$
|
|
5119
|
+
parseJsonValue$1(readString$a(raw, 'triggerSummaryJson'));
|
|
5120
5120
|
return {
|
|
5121
5121
|
...detail,
|
|
5122
5122
|
...summary,
|
|
5123
|
-
triggerSummaryJson: readString$
|
|
5123
|
+
triggerSummaryJson: readString$a(raw, 'triggerSummaryJson') ?? null,
|
|
5124
5124
|
triggerSummary,
|
|
5125
5125
|
nodeRuns,
|
|
5126
5126
|
waits,
|
|
@@ -5131,7 +5131,7 @@ function normalizeExecutionDetail(detail) {
|
|
|
5131
5131
|
flowPlusCommitAudits: readArray$1(raw, 'flowPlusCommitAudits'),
|
|
5132
5132
|
approvalDecisions: readArray$1(raw, 'approvalDecisions'),
|
|
5133
5133
|
timelineHasMore: readBoolean$3(raw, 'timelineHasMore') ?? false,
|
|
5134
|
-
timelineNextAfterUtc: readString$
|
|
5134
|
+
timelineNextAfterUtc: readString$a(raw, 'timelineNextAfterUtc') ?? null,
|
|
5135
5135
|
};
|
|
5136
5136
|
}
|
|
5137
5137
|
function normalizeExecutionSummary(value) {
|
|
@@ -5143,18 +5143,18 @@ function normalizeExecutionSummary(value) {
|
|
|
5143
5143
|
automationId: readId$3(raw, 'automationId') ?? '',
|
|
5144
5144
|
revisionId,
|
|
5145
5145
|
automationRevisionId: readId$3(raw, 'automationRevisionId') ?? revisionId,
|
|
5146
|
-
automationName: readString$
|
|
5146
|
+
automationName: readString$a(raw, 'automationName') ?? null,
|
|
5147
5147
|
revisionNumber: readNumber$2(raw, 'revisionNumber') ?? null,
|
|
5148
|
-
status: String(readString$
|
|
5149
|
-
triggerType: readString$
|
|
5150
|
-
triggerKey: readString$
|
|
5151
|
-
createdAtUtc: readString$
|
|
5152
|
-
startedAtUtc: readString$
|
|
5153
|
-
readString$
|
|
5148
|
+
status: String(readString$a(raw, 'status') ?? ''),
|
|
5149
|
+
triggerType: readString$a(raw, 'triggerType') ?? null,
|
|
5150
|
+
triggerKey: readString$a(raw, 'triggerKey') ?? null,
|
|
5151
|
+
createdAtUtc: readString$a(raw, 'createdAtUtc') ?? null,
|
|
5152
|
+
startedAtUtc: readString$a(raw, 'startedAtUtc') ??
|
|
5153
|
+
readString$a(raw, 'createdAtUtc') ??
|
|
5154
5154
|
null,
|
|
5155
|
-
completedAtUtc: readString$
|
|
5155
|
+
completedAtUtc: readString$a(raw, 'completedAtUtc') ?? null,
|
|
5156
5156
|
durationMs: readNumber$2(raw, 'durationMs') ?? null,
|
|
5157
|
-
correlationId: readString$
|
|
5157
|
+
correlationId: readString$a(raw, 'correlationId') ?? null,
|
|
5158
5158
|
};
|
|
5159
5159
|
}
|
|
5160
5160
|
function normalizeNodeRun(value) {
|
|
@@ -5162,9 +5162,9 @@ function normalizeNodeRun(value) {
|
|
|
5162
5162
|
return {
|
|
5163
5163
|
...raw,
|
|
5164
5164
|
nodeRunId: readId$3(raw, 'nodeRunId') ?? '',
|
|
5165
|
-
nodeKey: readString$
|
|
5166
|
-
nodeType: String(readString$
|
|
5167
|
-
status: String(readString$
|
|
5165
|
+
nodeKey: readString$a(raw, 'nodeKey') ?? '',
|
|
5166
|
+
nodeType: String(readString$a(raw, 'nodeType') ?? ''),
|
|
5167
|
+
status: String(readString$a(raw, 'status') ?? ''),
|
|
5168
5168
|
attempts: readArray$1(raw, 'attempts').map((attempt) => {
|
|
5169
5169
|
const attemptRaw = asRecord$5(attempt);
|
|
5170
5170
|
return {
|
|
@@ -5173,9 +5173,9 @@ function normalizeNodeRun(value) {
|
|
|
5173
5173
|
readId$3(attemptRaw, 'nodeAttemptId') ??
|
|
5174
5174
|
'',
|
|
5175
5175
|
nodeAttemptId: readId$3(attemptRaw, 'nodeAttemptId'),
|
|
5176
|
-
status: String(readString$
|
|
5177
|
-
errorMessage: readString$
|
|
5178
|
-
readString$
|
|
5176
|
+
status: String(readString$a(attemptRaw, 'status') ?? ''),
|
|
5177
|
+
errorMessage: readString$a(attemptRaw, 'errorMessage') ??
|
|
5178
|
+
readString$a(attemptRaw, 'errorJson') ??
|
|
5179
5179
|
null,
|
|
5180
5180
|
};
|
|
5181
5181
|
}),
|
|
@@ -5187,9 +5187,9 @@ function normalizeRuntimeWait(value) {
|
|
|
5187
5187
|
...raw,
|
|
5188
5188
|
runtimeWaitId: readId$3(raw, 'runtimeWaitId') ?? '',
|
|
5189
5189
|
nodeRunId: readId$3(raw, 'nodeRunId') ?? null,
|
|
5190
|
-
nodeKey: readString$
|
|
5191
|
-
waitType: readString$
|
|
5192
|
-
status: readString$
|
|
5190
|
+
nodeKey: readString$a(raw, 'nodeKey') ?? null,
|
|
5191
|
+
waitType: readString$a(raw, 'waitType') ?? '',
|
|
5192
|
+
status: readString$a(raw, 'status') ?? '',
|
|
5193
5193
|
};
|
|
5194
5194
|
}
|
|
5195
5195
|
function normalizeExecutionEvent(value) {
|
|
@@ -5197,27 +5197,27 @@ function normalizeExecutionEvent(value) {
|
|
|
5197
5197
|
return {
|
|
5198
5198
|
...raw,
|
|
5199
5199
|
eventId: readId$3(raw, 'eventId') ?? '',
|
|
5200
|
-
eventType: readString$
|
|
5201
|
-
severity: readString$
|
|
5202
|
-
occurredAtUtc: readString$
|
|
5200
|
+
eventType: readString$a(raw, 'eventType') ?? '',
|
|
5201
|
+
severity: readString$a(raw, 'severity') ?? 'Info',
|
|
5202
|
+
occurredAtUtc: readString$a(raw, 'occurredAtUtc') ?? '',
|
|
5203
5203
|
nodeRunId: readId$3(raw, 'nodeRunId') ?? null,
|
|
5204
5204
|
nodeAttemptId: readId$3(raw, 'nodeAttemptId') ?? null,
|
|
5205
|
-
correlationId: readString$
|
|
5206
|
-
data: raw['data'] ?? parseJsonValue$1(readString$
|
|
5207
|
-
dataJson: readString$
|
|
5205
|
+
correlationId: readString$a(raw, 'correlationId') ?? null,
|
|
5206
|
+
data: raw['data'] ?? parseJsonValue$1(readString$a(raw, 'dataJson')),
|
|
5207
|
+
dataJson: readString$a(raw, 'dataJson') ?? null,
|
|
5208
5208
|
};
|
|
5209
5209
|
}
|
|
5210
5210
|
function normalizeNodeDataDetail(detail) {
|
|
5211
5211
|
const raw = asRecord$5(detail);
|
|
5212
5212
|
const input = normalizeDataBlob(raw['input']);
|
|
5213
5213
|
const output = normalizeDataBlob(raw['output']);
|
|
5214
|
-
const error = parseJsonValue$1(readString$
|
|
5214
|
+
const error = parseJsonValue$1(readString$a(raw, 'errorJson'));
|
|
5215
5215
|
const summary = raw['summary'] ?? {
|
|
5216
5216
|
input,
|
|
5217
5217
|
output,
|
|
5218
5218
|
error,
|
|
5219
5219
|
replayAvailable: readBoolean$3(raw, 'replayAvailable') ?? false,
|
|
5220
|
-
replayAvailabilityReason: readString$
|
|
5220
|
+
replayAvailabilityReason: readString$a(raw, 'replayAvailabilityReason') ?? null,
|
|
5221
5221
|
};
|
|
5222
5222
|
return {
|
|
5223
5223
|
...detail,
|
|
@@ -5225,7 +5225,7 @@ function normalizeNodeDataDetail(detail) {
|
|
|
5225
5225
|
summary,
|
|
5226
5226
|
input: raw['input'],
|
|
5227
5227
|
output: raw['output'],
|
|
5228
|
-
errorJson: readString$
|
|
5228
|
+
errorJson: readString$a(raw, 'errorJson') ?? null,
|
|
5229
5229
|
attempts: readArray$1(raw, 'attempts').map((attempt) => {
|
|
5230
5230
|
const attemptRaw = asRecord$5(attempt);
|
|
5231
5231
|
return {
|
|
@@ -5233,7 +5233,7 @@ function normalizeNodeDataDetail(detail) {
|
|
|
5233
5233
|
attemptId: readId$3(attemptRaw, 'attemptId') ??
|
|
5234
5234
|
readId$3(attemptRaw, 'nodeAttemptId') ??
|
|
5235
5235
|
'',
|
|
5236
|
-
status: String(readString$
|
|
5236
|
+
status: String(readString$a(attemptRaw, 'status') ?? ''),
|
|
5237
5237
|
};
|
|
5238
5238
|
}),
|
|
5239
5239
|
logs: readArray$1(raw, 'logs').map(normalizeExecutionEvent),
|
|
@@ -5252,8 +5252,8 @@ function normalizeDataBlob(value) {
|
|
|
5252
5252
|
return {
|
|
5253
5253
|
...raw,
|
|
5254
5254
|
content: raw['content'] ??
|
|
5255
|
-
parseJsonValue$1(readString$
|
|
5256
|
-
readString$
|
|
5255
|
+
parseJsonValue$1(readString$a(raw, 'contentJson')) ??
|
|
5256
|
+
readString$a(raw, 'contentJson') ??
|
|
5257
5257
|
null,
|
|
5258
5258
|
};
|
|
5259
5259
|
}
|
|
@@ -5281,7 +5281,7 @@ function readArray$1(record, key) {
|
|
|
5281
5281
|
const value = record[key];
|
|
5282
5282
|
return Array.isArray(value) ? value : [];
|
|
5283
5283
|
}
|
|
5284
|
-
function readString$
|
|
5284
|
+
function readString$a(record, key) {
|
|
5285
5285
|
const value = record[key];
|
|
5286
5286
|
return typeof value === 'string' ? value : undefined;
|
|
5287
5287
|
}
|
|
@@ -6720,6 +6720,43 @@ class SetLayoutAutosavePaused {
|
|
|
6720
6720
|
this.paused = paused;
|
|
6721
6721
|
}
|
|
6722
6722
|
}
|
|
6723
|
+
class AddCanvasNote {
|
|
6724
|
+
note;
|
|
6725
|
+
static type = '[FlowplusWorkflow] Add Canvas Note';
|
|
6726
|
+
constructor(note) {
|
|
6727
|
+
this.note = note;
|
|
6728
|
+
}
|
|
6729
|
+
}
|
|
6730
|
+
class UpdateCanvasNote {
|
|
6731
|
+
noteId;
|
|
6732
|
+
patch;
|
|
6733
|
+
static type = '[FlowplusWorkflow] Update Canvas Note';
|
|
6734
|
+
constructor(noteId, patch) {
|
|
6735
|
+
this.noteId = noteId;
|
|
6736
|
+
this.patch = patch;
|
|
6737
|
+
}
|
|
6738
|
+
}
|
|
6739
|
+
class DeleteCanvasNote {
|
|
6740
|
+
noteId;
|
|
6741
|
+
static type = '[FlowplusWorkflow] Delete Canvas Note';
|
|
6742
|
+
constructor(noteId) {
|
|
6743
|
+
this.noteId = noteId;
|
|
6744
|
+
}
|
|
6745
|
+
}
|
|
6746
|
+
class DuplicateCanvasNote {
|
|
6747
|
+
noteId;
|
|
6748
|
+
static type = '[FlowplusWorkflow] Duplicate Canvas Note';
|
|
6749
|
+
constructor(noteId) {
|
|
6750
|
+
this.noteId = noteId;
|
|
6751
|
+
}
|
|
6752
|
+
}
|
|
6753
|
+
class SelectCanvasNote {
|
|
6754
|
+
noteId;
|
|
6755
|
+
static type = '[FlowplusWorkflow] Select Canvas Note';
|
|
6756
|
+
constructor(noteId) {
|
|
6757
|
+
this.noteId = noteId;
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6723
6760
|
/* ============================================================
|
|
6724
6761
|
* Validation / publish
|
|
6725
6762
|
* ============================================================ */
|
|
@@ -6762,10 +6799,12 @@ class ClearSelection {
|
|
|
6762
6799
|
class SetSelectionFromCanvas {
|
|
6763
6800
|
stepIds;
|
|
6764
6801
|
connectionIds;
|
|
6802
|
+
canvasNoteIds;
|
|
6765
6803
|
static type = '[FlowplusWorkflow] Set Selection From Canvas';
|
|
6766
|
-
constructor(stepIds, connectionIds) {
|
|
6804
|
+
constructor(stepIds, connectionIds, canvasNoteIds = []) {
|
|
6767
6805
|
this.stepIds = stepIds;
|
|
6768
6806
|
this.connectionIds = connectionIds;
|
|
6807
|
+
this.canvasNoteIds = canvasNoteIds;
|
|
6769
6808
|
}
|
|
6770
6809
|
}
|
|
6771
6810
|
class SetActiveInspectorTab {
|
|
@@ -6950,6 +6989,188 @@ class RunWorkflowTest {
|
|
|
6950
6989
|
}
|
|
6951
6990
|
}
|
|
6952
6991
|
|
|
6992
|
+
const CANVAS_NOTE_METADATA_KEY = 'canvasNotes';
|
|
6993
|
+
const CANVAS_NOTE_GROUP_PREFIX = 'note:';
|
|
6994
|
+
const CANVAS_NOTE_DEFAULT_WIDTH = 360;
|
|
6995
|
+
const CANVAS_NOTE_DEFAULT_HEIGHT = 220;
|
|
6996
|
+
const CANVAS_NOTE_MIN_WIDTH = 220;
|
|
6997
|
+
const CANVAS_NOTE_MIN_HEIGHT = 140;
|
|
6998
|
+
const CANVAS_NOTE_DEFAULT_TEXT = "## I'm a note\nDouble click to edit. **Guide**";
|
|
6999
|
+
const CANVAS_NOTE_COLORS = [
|
|
7000
|
+
{
|
|
7001
|
+
key: 'amber',
|
|
7002
|
+
label: 'Amber',
|
|
7003
|
+
background: '#733e0a',
|
|
7004
|
+
border: '#a16207',
|
|
7005
|
+
text: '#fff7ed',
|
|
7006
|
+
},
|
|
7007
|
+
{
|
|
7008
|
+
key: 'slate',
|
|
7009
|
+
label: 'Slate',
|
|
7010
|
+
background: '#1f2937',
|
|
7011
|
+
border: '#475569',
|
|
7012
|
+
text: '#f8fafc',
|
|
7013
|
+
},
|
|
7014
|
+
{
|
|
7015
|
+
key: 'rose',
|
|
7016
|
+
label: 'Rose',
|
|
7017
|
+
background: '#881337',
|
|
7018
|
+
border: '#be123c',
|
|
7019
|
+
text: '#fff1f2',
|
|
7020
|
+
},
|
|
7021
|
+
{
|
|
7022
|
+
key: 'emerald',
|
|
7023
|
+
label: 'Emerald',
|
|
7024
|
+
background: '#064e3b',
|
|
7025
|
+
border: '#059669',
|
|
7026
|
+
text: '#ecfdf5',
|
|
7027
|
+
},
|
|
7028
|
+
{
|
|
7029
|
+
key: 'blue',
|
|
7030
|
+
label: 'Blue',
|
|
7031
|
+
background: '#1e3a8a',
|
|
7032
|
+
border: '#2563eb',
|
|
7033
|
+
text: '#eff6ff',
|
|
7034
|
+
},
|
|
7035
|
+
{
|
|
7036
|
+
key: 'violet',
|
|
7037
|
+
label: 'Violet',
|
|
7038
|
+
background: '#4c1d95',
|
|
7039
|
+
border: '#7c3aed',
|
|
7040
|
+
text: '#f5f3ff',
|
|
7041
|
+
},
|
|
7042
|
+
{
|
|
7043
|
+
key: 'neutral',
|
|
7044
|
+
label: 'Neutral',
|
|
7045
|
+
background: '#262626',
|
|
7046
|
+
border: '#737373',
|
|
7047
|
+
text: '#fafafa',
|
|
7048
|
+
},
|
|
7049
|
+
];
|
|
7050
|
+
const DEFAULT_COLOR = CANVAS_NOTE_COLORS[0];
|
|
7051
|
+
function canvasNoteGroupId(noteId) {
|
|
7052
|
+
return `${CANVAS_NOTE_GROUP_PREFIX}${noteId}`;
|
|
7053
|
+
}
|
|
7054
|
+
function parseCanvasNoteGroupId(value) {
|
|
7055
|
+
if (!value?.startsWith(CANVAS_NOTE_GROUP_PREFIX))
|
|
7056
|
+
return null;
|
|
7057
|
+
const id = value.slice(CANVAS_NOTE_GROUP_PREFIX.length).trim();
|
|
7058
|
+
return id || null;
|
|
7059
|
+
}
|
|
7060
|
+
function resolveCanvasNoteColor(color) {
|
|
7061
|
+
return (CANVAS_NOTE_COLORS.find((item) => item.key === color) ?? DEFAULT_COLOR);
|
|
7062
|
+
}
|
|
7063
|
+
function createCanvasNote(position, now = new Date().toISOString()) {
|
|
7064
|
+
return {
|
|
7065
|
+
id: createCanvasNoteId(),
|
|
7066
|
+
text: CANVAS_NOTE_DEFAULT_TEXT,
|
|
7067
|
+
color: DEFAULT_COLOR.key,
|
|
7068
|
+
x: Math.round(position.x),
|
|
7069
|
+
y: Math.round(position.y),
|
|
7070
|
+
width: CANVAS_NOTE_DEFAULT_WIDTH,
|
|
7071
|
+
height: CANVAS_NOTE_DEFAULT_HEIGHT,
|
|
7072
|
+
createdAt: now,
|
|
7073
|
+
updatedAt: now,
|
|
7074
|
+
};
|
|
7075
|
+
}
|
|
7076
|
+
function readCanvasNotesFromLayout(layout) {
|
|
7077
|
+
return normalizeCanvasNotes(layout?.metadata?.[CANVAS_NOTE_METADATA_KEY]);
|
|
7078
|
+
}
|
|
7079
|
+
function writeCanvasNotesToLayout(layout, workflowId, notes) {
|
|
7080
|
+
const metadata = { ...(layout?.metadata ?? {}) };
|
|
7081
|
+
metadata[CANVAS_NOTE_METADATA_KEY] = notes.map((note) => ({ ...note }));
|
|
7082
|
+
return {
|
|
7083
|
+
workflowId,
|
|
7084
|
+
version: layout?.version ?? null,
|
|
7085
|
+
nodes: layout?.nodes ?? [],
|
|
7086
|
+
connections: layout?.connections ?? [],
|
|
7087
|
+
viewport: layout?.viewport ?? null,
|
|
7088
|
+
metadata,
|
|
7089
|
+
};
|
|
7090
|
+
}
|
|
7091
|
+
function upsertCanvasNote(notes, note) {
|
|
7092
|
+
const index = notes.findIndex((item) => item.id === note.id);
|
|
7093
|
+
if (index < 0)
|
|
7094
|
+
return [...notes, note];
|
|
7095
|
+
const next = notes.slice();
|
|
7096
|
+
next[index] = note;
|
|
7097
|
+
return next;
|
|
7098
|
+
}
|
|
7099
|
+
function patchCanvasNote(note, patch, now = new Date().toISOString()) {
|
|
7100
|
+
return {
|
|
7101
|
+
...note,
|
|
7102
|
+
text: patch.text ?? note.text,
|
|
7103
|
+
color: resolveCanvasNoteColor(patch.color ?? note.color).key,
|
|
7104
|
+
x: normalizeNumber(patch.x, note.x),
|
|
7105
|
+
y: normalizeNumber(patch.y, note.y),
|
|
7106
|
+
width: Math.max(CANVAS_NOTE_MIN_WIDTH, normalizeNumber(patch.width, note.width)),
|
|
7107
|
+
height: Math.max(CANVAS_NOTE_MIN_HEIGHT, normalizeNumber(patch.height, note.height)),
|
|
7108
|
+
updatedAt: now,
|
|
7109
|
+
};
|
|
7110
|
+
}
|
|
7111
|
+
function duplicateCanvasNote(note, now = new Date().toISOString()) {
|
|
7112
|
+
return {
|
|
7113
|
+
...note,
|
|
7114
|
+
id: createCanvasNoteId(),
|
|
7115
|
+
x: note.x + 32,
|
|
7116
|
+
y: note.y + 32,
|
|
7117
|
+
createdAt: now,
|
|
7118
|
+
updatedAt: now,
|
|
7119
|
+
};
|
|
7120
|
+
}
|
|
7121
|
+
function normalizeCanvasNotes(value) {
|
|
7122
|
+
if (!Array.isArray(value))
|
|
7123
|
+
return [];
|
|
7124
|
+
return value
|
|
7125
|
+
.map((item) => normalizeCanvasNote(item))
|
|
7126
|
+
.filter((item) => item != null);
|
|
7127
|
+
}
|
|
7128
|
+
function normalizeCanvasNote(value) {
|
|
7129
|
+
if (!isRecord(value))
|
|
7130
|
+
return null;
|
|
7131
|
+
const id = readString$9(value, 'id');
|
|
7132
|
+
if (!id)
|
|
7133
|
+
return null;
|
|
7134
|
+
return {
|
|
7135
|
+
id,
|
|
7136
|
+
text: readString$9(value, 'text') ?? CANVAS_NOTE_DEFAULT_TEXT,
|
|
7137
|
+
color: resolveCanvasNoteColor(readString$9(value, 'color')).key,
|
|
7138
|
+
x: normalizeNumber(value['x'], 120),
|
|
7139
|
+
y: normalizeNumber(value['y'], 120),
|
|
7140
|
+
width: Math.max(CANVAS_NOTE_MIN_WIDTH, normalizeNumber(value['width'], CANVAS_NOTE_DEFAULT_WIDTH)),
|
|
7141
|
+
height: Math.max(CANVAS_NOTE_MIN_HEIGHT, normalizeNumber(value['height'], CANVAS_NOTE_DEFAULT_HEIGHT)),
|
|
7142
|
+
createdAt: readString$9(value, 'createdAt'),
|
|
7143
|
+
updatedAt: readString$9(value, 'updatedAt'),
|
|
7144
|
+
};
|
|
7145
|
+
}
|
|
7146
|
+
function createCanvasNoteId() {
|
|
7147
|
+
const cryptoApi = globalThis.crypto;
|
|
7148
|
+
if (cryptoApi && typeof cryptoApi.randomUUID === 'function') {
|
|
7149
|
+
return cryptoApi.randomUUID();
|
|
7150
|
+
}
|
|
7151
|
+
return `note_${Date.now().toString(36)}_${Math.random()
|
|
7152
|
+
.toString(36)
|
|
7153
|
+
.slice(2, 8)}`;
|
|
7154
|
+
}
|
|
7155
|
+
function normalizeNumber(value, fallback) {
|
|
7156
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
7157
|
+
return Math.round(value);
|
|
7158
|
+
}
|
|
7159
|
+
if (typeof value === 'string' && value.trim()) {
|
|
7160
|
+
const parsed = Number(value);
|
|
7161
|
+
if (Number.isFinite(parsed))
|
|
7162
|
+
return Math.round(parsed);
|
|
7163
|
+
}
|
|
7164
|
+
return fallback;
|
|
7165
|
+
}
|
|
7166
|
+
function readString$9(record, key) {
|
|
7167
|
+
const value = record[key];
|
|
7168
|
+
return typeof value === 'string' && value.trim() ? value : null;
|
|
7169
|
+
}
|
|
7170
|
+
function isRecord(value) {
|
|
7171
|
+
return value != null && typeof value === 'object' && !Array.isArray(value);
|
|
7172
|
+
}
|
|
7173
|
+
|
|
6953
7174
|
/**
|
|
6954
7175
|
* NGXS state model for the FlowPlus design-time workflow builder.
|
|
6955
7176
|
*
|
|
@@ -7031,6 +7252,7 @@ const FLOWPLUS_WORKFLOW_DEFAULT_STATE = {
|
|
|
7031
7252
|
selection: {
|
|
7032
7253
|
stepIds: [],
|
|
7033
7254
|
connectionIds: [],
|
|
7255
|
+
canvasNoteIds: [],
|
|
7034
7256
|
triggerId: null,
|
|
7035
7257
|
isWorkflowSelected: true,
|
|
7036
7258
|
activeTab: 'overview',
|
|
@@ -7841,6 +8063,7 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
7841
8063
|
? Array.from(new Set([...cur.stepIds, action.stepId]))
|
|
7842
8064
|
: [action.stepId],
|
|
7843
8065
|
connectionIds: action.append ? cur.connectionIds : [],
|
|
8066
|
+
canvasNoteIds: [],
|
|
7844
8067
|
triggerId: null,
|
|
7845
8068
|
isWorkflowSelected: false,
|
|
7846
8069
|
activeTab: cur.activeTab || 'overview',
|
|
@@ -8044,6 +8267,7 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8044
8267
|
selection: {
|
|
8045
8268
|
stepIds: [],
|
|
8046
8269
|
connectionIds: [action.connectionId],
|
|
8270
|
+
canvasNoteIds: [],
|
|
8047
8271
|
triggerId: null,
|
|
8048
8272
|
isWorkflowSelected: false,
|
|
8049
8273
|
activeTab: 'configure',
|
|
@@ -8059,6 +8283,7 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8059
8283
|
selection: {
|
|
8060
8284
|
stepIds: [],
|
|
8061
8285
|
connectionIds: [],
|
|
8286
|
+
canvasNoteIds: [],
|
|
8062
8287
|
triggerId: action.triggerId,
|
|
8063
8288
|
isWorkflowSelected: false,
|
|
8064
8289
|
activeTab: 'configure',
|
|
@@ -8370,6 +8595,95 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8370
8595
|
}
|
|
8371
8596
|
return undefined;
|
|
8372
8597
|
}
|
|
8598
|
+
addCanvasNote(ctx, action) {
|
|
8599
|
+
const state = ctx.getState();
|
|
8600
|
+
const workflowId = state.builder.workflowId;
|
|
8601
|
+
if (!workflowId)
|
|
8602
|
+
return;
|
|
8603
|
+
const notes = upsertCanvasNote(readCanvasNotesFromLayout(state.builder.layout), action.note);
|
|
8604
|
+
this.patchCanvasNotes(ctx, workflowId, notes, [action.note.id]);
|
|
8605
|
+
return ctx.dispatch(new MarkLayoutDirty());
|
|
8606
|
+
}
|
|
8607
|
+
updateCanvasNote(ctx, action) {
|
|
8608
|
+
const state = ctx.getState();
|
|
8609
|
+
const workflowId = state.builder.workflowId;
|
|
8610
|
+
if (!workflowId)
|
|
8611
|
+
return;
|
|
8612
|
+
const notes = readCanvasNotesFromLayout(state.builder.layout);
|
|
8613
|
+
const next = notes.map((note) => note.id === action.noteId ? patchCanvasNote(note, action.patch) : note);
|
|
8614
|
+
if (!next.some((note) => note.id === action.noteId))
|
|
8615
|
+
return;
|
|
8616
|
+
this.patchCanvasNotes(ctx, workflowId, next);
|
|
8617
|
+
return ctx.dispatch(new MarkLayoutDirty());
|
|
8618
|
+
}
|
|
8619
|
+
deleteCanvasNote(ctx, action) {
|
|
8620
|
+
const state = ctx.getState();
|
|
8621
|
+
const workflowId = state.builder.workflowId;
|
|
8622
|
+
if (!workflowId)
|
|
8623
|
+
return;
|
|
8624
|
+
const notes = readCanvasNotesFromLayout(state.builder.layout);
|
|
8625
|
+
const next = notes.filter((note) => note.id !== action.noteId);
|
|
8626
|
+
if (next.length === notes.length)
|
|
8627
|
+
return;
|
|
8628
|
+
const selected = state.builder.selection.canvasNoteIds.includes(action.noteId)
|
|
8629
|
+
? []
|
|
8630
|
+
: state.builder.selection.canvasNoteIds;
|
|
8631
|
+
this.patchCanvasNotes(ctx, workflowId, next, selected);
|
|
8632
|
+
return ctx.dispatch(new MarkLayoutDirty());
|
|
8633
|
+
}
|
|
8634
|
+
duplicateCanvasNote(ctx, action) {
|
|
8635
|
+
const state = ctx.getState();
|
|
8636
|
+
const workflowId = state.builder.workflowId;
|
|
8637
|
+
if (!workflowId)
|
|
8638
|
+
return;
|
|
8639
|
+
const notes = readCanvasNotesFromLayout(state.builder.layout);
|
|
8640
|
+
const note = notes.find((item) => item.id === action.noteId);
|
|
8641
|
+
if (!note)
|
|
8642
|
+
return;
|
|
8643
|
+
const copy = duplicateCanvasNote(note);
|
|
8644
|
+
this.patchCanvasNotes(ctx, workflowId, [...notes, copy], [copy.id]);
|
|
8645
|
+
return ctx.dispatch(new MarkLayoutDirty());
|
|
8646
|
+
}
|
|
8647
|
+
selectCanvasNote(ctx, action) {
|
|
8648
|
+
const state = ctx.getState();
|
|
8649
|
+
ctx.patchState({
|
|
8650
|
+
builder: {
|
|
8651
|
+
...state.builder,
|
|
8652
|
+
selection: {
|
|
8653
|
+
stepIds: [],
|
|
8654
|
+
connectionIds: [],
|
|
8655
|
+
canvasNoteIds: action.noteId ? [action.noteId] : [],
|
|
8656
|
+
triggerId: null,
|
|
8657
|
+
isWorkflowSelected: false,
|
|
8658
|
+
activeTab: 'overview',
|
|
8659
|
+
},
|
|
8660
|
+
},
|
|
8661
|
+
ui: { ...state.ui, isInspectorOpen: false },
|
|
8662
|
+
});
|
|
8663
|
+
}
|
|
8664
|
+
patchCanvasNotes(ctx, workflowId, notes, selectedNoteIds) {
|
|
8665
|
+
const state = ctx.getState();
|
|
8666
|
+
const selection = selectedNoteIds === undefined
|
|
8667
|
+
? state.builder.selection
|
|
8668
|
+
: {
|
|
8669
|
+
stepIds: [],
|
|
8670
|
+
connectionIds: [],
|
|
8671
|
+
canvasNoteIds: selectedNoteIds,
|
|
8672
|
+
triggerId: null,
|
|
8673
|
+
isWorkflowSelected: false,
|
|
8674
|
+
activeTab: selectedNoteIds.length > 1 ? 'multi' : 'overview',
|
|
8675
|
+
};
|
|
8676
|
+
ctx.patchState({
|
|
8677
|
+
builder: {
|
|
8678
|
+
...state.builder,
|
|
8679
|
+
layout: writeCanvasNotesToLayout(state.builder.layout, workflowId, notes),
|
|
8680
|
+
selection,
|
|
8681
|
+
layoutSaveStatus: 'dirty',
|
|
8682
|
+
dirty: { ...state.builder.dirty, layout: true },
|
|
8683
|
+
},
|
|
8684
|
+
ui: { ...state.ui, isInspectorOpen: false },
|
|
8685
|
+
});
|
|
8686
|
+
}
|
|
8373
8687
|
saveLayout(ctx) {
|
|
8374
8688
|
if (this.layoutTimer) {
|
|
8375
8689
|
clearTimeout(this.layoutTimer);
|
|
@@ -8483,8 +8797,13 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8483
8797
|
setSelectionFromCanvas(ctx, action) {
|
|
8484
8798
|
const state = ctx.getState();
|
|
8485
8799
|
const cur = state.builder.selection;
|
|
8486
|
-
const nothing = action.stepIds.length === 0 &&
|
|
8487
|
-
|
|
8800
|
+
const nothing = action.stepIds.length === 0 &&
|
|
8801
|
+
action.connectionIds.length === 0 &&
|
|
8802
|
+
action.canvasNoteIds.length === 0;
|
|
8803
|
+
const single = action.stepIds.length +
|
|
8804
|
+
action.connectionIds.length +
|
|
8805
|
+
action.canvasNoteIds.length ===
|
|
8806
|
+
1;
|
|
8488
8807
|
let activeTab = cur.activeTab;
|
|
8489
8808
|
if (nothing)
|
|
8490
8809
|
activeTab = 'overview';
|
|
@@ -8497,12 +8816,16 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8497
8816
|
else if (action.connectionIds.length === 1) {
|
|
8498
8817
|
activeTab = 'configure';
|
|
8499
8818
|
}
|
|
8819
|
+
else if (action.canvasNoteIds.length === 1) {
|
|
8820
|
+
activeTab = 'overview';
|
|
8821
|
+
}
|
|
8500
8822
|
ctx.patchState({
|
|
8501
8823
|
builder: {
|
|
8502
8824
|
...state.builder,
|
|
8503
8825
|
selection: {
|
|
8504
8826
|
stepIds: action.stepIds,
|
|
8505
8827
|
connectionIds: action.connectionIds,
|
|
8828
|
+
canvasNoteIds: action.canvasNoteIds,
|
|
8506
8829
|
triggerId: null,
|
|
8507
8830
|
// Clicking empty canvas no longer auto-selects the workflow root —
|
|
8508
8831
|
// the canvas-first shell expects the inspector to close on empty
|
|
@@ -8519,7 +8842,9 @@ let FlowplusWorkflowState = class FlowplusWorkflowState {
|
|
|
8519
8842
|
// empty canvas still closes whatever was open.
|
|
8520
8843
|
ui: {
|
|
8521
8844
|
...state.ui,
|
|
8522
|
-
isInspectorOpen: nothing
|
|
8845
|
+
isInspectorOpen: nothing || action.canvasNoteIds.length > 0
|
|
8846
|
+
? false
|
|
8847
|
+
: state.ui.isInspectorOpen,
|
|
8523
8848
|
},
|
|
8524
8849
|
});
|
|
8525
8850
|
}
|
|
@@ -9226,6 +9551,21 @@ __decorate([
|
|
|
9226
9551
|
__decorate([
|
|
9227
9552
|
Action(SetLayoutAutosavePaused)
|
|
9228
9553
|
], FlowplusWorkflowState.prototype, "setLayoutAutosavePaused", null);
|
|
9554
|
+
__decorate([
|
|
9555
|
+
Action(AddCanvasNote)
|
|
9556
|
+
], FlowplusWorkflowState.prototype, "addCanvasNote", null);
|
|
9557
|
+
__decorate([
|
|
9558
|
+
Action(UpdateCanvasNote)
|
|
9559
|
+
], FlowplusWorkflowState.prototype, "updateCanvasNote", null);
|
|
9560
|
+
__decorate([
|
|
9561
|
+
Action(DeleteCanvasNote)
|
|
9562
|
+
], FlowplusWorkflowState.prototype, "deleteCanvasNote", null);
|
|
9563
|
+
__decorate([
|
|
9564
|
+
Action(DuplicateCanvasNote)
|
|
9565
|
+
], FlowplusWorkflowState.prototype, "duplicateCanvasNote", null);
|
|
9566
|
+
__decorate([
|
|
9567
|
+
Action(SelectCanvasNote)
|
|
9568
|
+
], FlowplusWorkflowState.prototype, "selectCanvasNote", null);
|
|
9229
9569
|
__decorate([
|
|
9230
9570
|
Action(SaveLayout)
|
|
9231
9571
|
], FlowplusWorkflowState.prototype, "saveLayout", null);
|
|
@@ -9438,7 +9778,7 @@ FlowplusWorkflowState = FlowplusWorkflowState_1 = __decorate([
|
|
|
9438
9778
|
], FlowplusWorkflowState);
|
|
9439
9779
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FlowplusWorkflowState, decorators: [{
|
|
9440
9780
|
type: Injectable
|
|
9441
|
-
}], propDecorators: { loadWorkflowList: [], setStudioFilter: [], createWorkflow: [], duplicateWorkflow: [], deleteWorkflow: [], loadWorkflowBuilder: [], applyBuilderSnapshot: [], reloadWorkflowBuilder: [], clearWorkflowBuilder: [], loadWorkflowCatalog: [], setWorkflowCatalog: [], loadContextCatalog: [], loadContextCatalogForStep: [], setContextCatalog: [], updateWorkflowMetadata: [], commitWorkflowMetadata: [], setWorkflowDefinition: [], updateWorkflowResources: [], updateWorkflowVariables: [], selectStep: [], createStep: [], updateStep: [], deleteStep: [], moveStep: [], selectConnection: [], selectTrigger: [], createConnection: [], updateConnection: [], deleteConnection: [], loadTriggers: [], createTrigger: [], updateTrigger: [], deleteTrigger: [], loadLayout: [], markLayoutDirty: [], setLayoutAutosavePaused: [], saveLayout: [], validateWorkflow: [], setValidation: [], setLayout: [], publishWorkflow: [], unpublishWorkflow: [], setSelection: [], setSelectionFromCanvas: [], setActiveInspectorTab: [], setBottomPanelTab: [], setBottomPanelOpen: [], setMinimap: [], setPaletteOpen: [], setInspectorOpen: [], setCreateDialogOpen: [], setPaletteSearch: [], setCanvasViewport: [], setReadonly: [], setPendingOperation: [], clearPendingOperation: [], clearConflict: [], undoBuilderCommand: [], redoBuilderCommand: [], clearCommandHistory: [], setSelectedRuntimeTrigger: [], runAutomationTrigger: [], pollAutomationExecution: [], loadLatestAutomationExecution: [], loadAutomationExecution: [], applyAutomationExecutionDetail: [], clearAutomationRuntimeState: [], selectRuntimeNodeRun: [], runWorkflowTest: [] } });
|
|
9781
|
+
}], propDecorators: { loadWorkflowList: [], setStudioFilter: [], createWorkflow: [], duplicateWorkflow: [], deleteWorkflow: [], loadWorkflowBuilder: [], applyBuilderSnapshot: [], reloadWorkflowBuilder: [], clearWorkflowBuilder: [], loadWorkflowCatalog: [], setWorkflowCatalog: [], loadContextCatalog: [], loadContextCatalogForStep: [], setContextCatalog: [], updateWorkflowMetadata: [], commitWorkflowMetadata: [], setWorkflowDefinition: [], updateWorkflowResources: [], updateWorkflowVariables: [], selectStep: [], createStep: [], updateStep: [], deleteStep: [], moveStep: [], selectConnection: [], selectTrigger: [], createConnection: [], updateConnection: [], deleteConnection: [], loadTriggers: [], createTrigger: [], updateTrigger: [], deleteTrigger: [], loadLayout: [], markLayoutDirty: [], setLayoutAutosavePaused: [], addCanvasNote: [], updateCanvasNote: [], deleteCanvasNote: [], duplicateCanvasNote: [], selectCanvasNote: [], saveLayout: [], validateWorkflow: [], setValidation: [], setLayout: [], publishWorkflow: [], unpublishWorkflow: [], setSelection: [], setSelectionFromCanvas: [], setActiveInspectorTab: [], setBottomPanelTab: [], setBottomPanelOpen: [], setMinimap: [], setPaletteOpen: [], setInspectorOpen: [], setCreateDialogOpen: [], setPaletteSearch: [], setCanvasViewport: [], setReadonly: [], setPendingOperation: [], clearPendingOperation: [], clearConflict: [], undoBuilderCommand: [], redoBuilderCommand: [], clearCommandHistory: [], setSelectedRuntimeTrigger: [], runAutomationTrigger: [], pollAutomationExecution: [], loadLatestAutomationExecution: [], loadAutomationExecution: [], applyAutomationExecutionDetail: [], clearAutomationRuntimeState: [], selectRuntimeNodeRun: [], runWorkflowTest: [] } });
|
|
9442
9782
|
function collectRuntimeFacts(detail) {
|
|
9443
9783
|
const nodeKeyByRunId = new Map((detail.nodeRuns ?? []).map((nodeRun) => [
|
|
9444
9784
|
String(nodeRun.nodeRunId),
|
|
@@ -9831,6 +10171,8 @@ class FlowplusWorkflowFacade {
|
|
|
9831
10171
|
selection = select(FlowplusWorkflowState.selection);
|
|
9832
10172
|
viewport = select(FlowplusWorkflowState.viewport);
|
|
9833
10173
|
layout = select(FlowplusWorkflowState.layout);
|
|
10174
|
+
canvasNotes = computed(() => readCanvasNotesFromLayout(this.layout()), ...(ngDevMode ? [{ debugName: "canvasNotes" }] : /* istanbul ignore next */ []));
|
|
10175
|
+
selectedCanvasNoteIds = computed(() => this.selection().canvasNoteIds, ...(ngDevMode ? [{ debugName: "selectedCanvasNoteIds" }] : /* istanbul ignore next */ []));
|
|
9834
10176
|
saveStatus = select(FlowplusWorkflowState.saveStatus);
|
|
9835
10177
|
layoutSaveStatus = select(FlowplusWorkflowState.layoutSaveStatus);
|
|
9836
10178
|
dirtyFlags = select(FlowplusWorkflowState.dirtyFlags);
|
|
@@ -10244,20 +10586,24 @@ class FlowplusWorkflowFacade {
|
|
|
10244
10586
|
return this.store.dispatch(new SetSelection({
|
|
10245
10587
|
stepIds: [],
|
|
10246
10588
|
connectionIds: [],
|
|
10589
|
+
canvasNoteIds: [],
|
|
10247
10590
|
triggerId: null,
|
|
10248
10591
|
isWorkflowSelected: true,
|
|
10249
10592
|
activeTab: 'overview',
|
|
10250
10593
|
}));
|
|
10251
10594
|
}
|
|
10252
10595
|
/** Set selection from a Foblex `fSelectionChange` payload. */
|
|
10253
|
-
setSelectionFromCanvas(stepIds, connectionIds) {
|
|
10254
|
-
return this.store.dispatch(new SetSelectionFromCanvas(stepIds, connectionIds));
|
|
10596
|
+
setSelectionFromCanvas(stepIds, connectionIds, canvasNoteIds = []) {
|
|
10597
|
+
return this.store.dispatch(new SetSelectionFromCanvas(stepIds, connectionIds, canvasNoteIds));
|
|
10255
10598
|
}
|
|
10256
10599
|
/** Select every step (Ctrl/Cmd+A). */
|
|
10257
10600
|
selectAll() {
|
|
10258
10601
|
const ids = this.steps().map((s) => s.id);
|
|
10259
10602
|
return this.store.dispatch(new SetSelectionFromCanvas(ids, []));
|
|
10260
10603
|
}
|
|
10604
|
+
selectCanvasNote(noteId) {
|
|
10605
|
+
return this.store.dispatch(new SelectCanvasNote(noteId));
|
|
10606
|
+
}
|
|
10261
10607
|
setInspectorTab(tab) {
|
|
10262
10608
|
return this.store.dispatch(new SetActiveInspectorTab(tab));
|
|
10263
10609
|
}
|
|
@@ -10301,6 +10647,21 @@ class FlowplusWorkflowFacade {
|
|
|
10301
10647
|
deleteTrigger(triggerId) {
|
|
10302
10648
|
return this.store.dispatch(new DeleteTrigger(triggerId));
|
|
10303
10649
|
}
|
|
10650
|
+
/* -------- canvas notes -------- */
|
|
10651
|
+
addCanvasNote(position) {
|
|
10652
|
+
const note = createCanvasNote(position);
|
|
10653
|
+
this.store.dispatch(new AddCanvasNote(note));
|
|
10654
|
+
return note;
|
|
10655
|
+
}
|
|
10656
|
+
updateCanvasNote(noteId, patch) {
|
|
10657
|
+
return this.store.dispatch(new UpdateCanvasNote(noteId, patch));
|
|
10658
|
+
}
|
|
10659
|
+
deleteCanvasNote(noteId) {
|
|
10660
|
+
return this.store.dispatch(new DeleteCanvasNote(noteId));
|
|
10661
|
+
}
|
|
10662
|
+
duplicateCanvasNote(noteId) {
|
|
10663
|
+
return this.store.dispatch(new DuplicateCanvasNote(noteId));
|
|
10664
|
+
}
|
|
10304
10665
|
/* -------- layout -------- */
|
|
10305
10666
|
loadLayout() {
|
|
10306
10667
|
return this.store.dispatch(new LoadLayout());
|
|
@@ -10346,6 +10707,28 @@ class FlowplusWorkflowFacade {
|
|
|
10346
10707
|
y: trigger.y,
|
|
10347
10708
|
};
|
|
10348
10709
|
}
|
|
10710
|
+
let layoutForNotes = state.layout;
|
|
10711
|
+
if ((args.notes?.length ?? 0) > 0) {
|
|
10712
|
+
const notes = readCanvasNotesFromLayout(state.layout);
|
|
10713
|
+
let notesChanged = false;
|
|
10714
|
+
const nextNotes = notes.map((note) => {
|
|
10715
|
+
const update = args.notes?.find((item) => item.noteId === note.id);
|
|
10716
|
+
if (!update)
|
|
10717
|
+
return note;
|
|
10718
|
+
const next = patchCanvasNote(note, update);
|
|
10719
|
+
if (next.x !== note.x ||
|
|
10720
|
+
next.y !== note.y ||
|
|
10721
|
+
next.width !== note.width ||
|
|
10722
|
+
next.height !== note.height) {
|
|
10723
|
+
notesChanged = true;
|
|
10724
|
+
}
|
|
10725
|
+
return next;
|
|
10726
|
+
});
|
|
10727
|
+
if (notesChanged) {
|
|
10728
|
+
changed = true;
|
|
10729
|
+
layoutForNotes = writeCanvasNotesToLayout(state.layout, state.workflowId, nextNotes);
|
|
10730
|
+
}
|
|
10731
|
+
}
|
|
10349
10732
|
if (!changed)
|
|
10350
10733
|
return false;
|
|
10351
10734
|
if ((args.triggers?.length ?? 0) > 0) {
|
|
@@ -10353,11 +10736,17 @@ class FlowplusWorkflowFacade {
|
|
|
10353
10736
|
}
|
|
10354
10737
|
this.store.dispatch(new SetLayout({
|
|
10355
10738
|
workflowId: state.workflowId,
|
|
10356
|
-
version:
|
|
10739
|
+
version: layoutForNotes?.version ?? null,
|
|
10357
10740
|
nodes: Array.from(nodesByStepId.values()),
|
|
10358
|
-
connections:
|
|
10359
|
-
viewport:
|
|
10360
|
-
metadata
|
|
10741
|
+
connections: layoutForNotes?.connections ?? [],
|
|
10742
|
+
viewport: layoutForNotes?.viewport ?? null,
|
|
10743
|
+
metadata: {
|
|
10744
|
+
...metadata,
|
|
10745
|
+
...(layoutForNotes?.metadata ?? {}),
|
|
10746
|
+
...((args.triggers?.length ?? 0) > 0
|
|
10747
|
+
? { triggerPositions }
|
|
10748
|
+
: {}),
|
|
10749
|
+
},
|
|
10361
10750
|
}));
|
|
10362
10751
|
if (options.scheduleSave !== false) {
|
|
10363
10752
|
this.store.dispatch(new MarkLayoutDirty());
|
|
@@ -18290,6 +18679,135 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
18290
18679
|
type: Output
|
|
18291
18680
|
}] } });
|
|
18292
18681
|
|
|
18682
|
+
class CanvasNoteComponent {
|
|
18683
|
+
host = inject((ElementRef));
|
|
18684
|
+
note = input.required(...(ngDevMode ? [{ debugName: "note" }] : /* istanbul ignore next */ []));
|
|
18685
|
+
selected = input(false, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
18686
|
+
editing = input(false, ...(ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []));
|
|
18687
|
+
colors = input(CANVAS_NOTE_COLORS, ...(ngDevMode ? [{ debugName: "colors" }] : /* istanbul ignore next */ []));
|
|
18688
|
+
contentChange = output();
|
|
18689
|
+
colorChange = output();
|
|
18690
|
+
duplicate = output();
|
|
18691
|
+
remove = output();
|
|
18692
|
+
editStart = output();
|
|
18693
|
+
editEnd = output();
|
|
18694
|
+
resizeHandle = EFResizeHandleType;
|
|
18695
|
+
draft = signal('', ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
18696
|
+
textareaInputs = {
|
|
18697
|
+
spellcheck: true,
|
|
18698
|
+
};
|
|
18699
|
+
color = computed(() => resolveCanvasNoteColor(this.note().color), ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
18700
|
+
noteLabel = computed(() => `Canvas note ${this.note().text.split(/\r?\n/)[0] ?? ''}`.trim(), ...(ngDevMode ? [{ debugName: "noteLabel" }] : /* istanbul ignore next */ []));
|
|
18701
|
+
markdownLines = computed(() => parseMarkdown(this.note().text), ...(ngDevMode ? [{ debugName: "markdownLines" }] : /* istanbul ignore next */ []));
|
|
18702
|
+
constructor() {
|
|
18703
|
+
effect(() => {
|
|
18704
|
+
if (this.editing())
|
|
18705
|
+
return;
|
|
18706
|
+
this.draft.set(this.note().text);
|
|
18707
|
+
});
|
|
18708
|
+
effect(() => {
|
|
18709
|
+
if (!this.editing())
|
|
18710
|
+
return;
|
|
18711
|
+
requestAnimationFrame(() => {
|
|
18712
|
+
this.host.nativeElement.querySelector('textarea')?.focus();
|
|
18713
|
+
});
|
|
18714
|
+
});
|
|
18715
|
+
}
|
|
18716
|
+
startEdit(event) {
|
|
18717
|
+
event?.stopPropagation();
|
|
18718
|
+
this.draft.set(this.note().text);
|
|
18719
|
+
this.editStart.emit({ noteId: this.note().id });
|
|
18720
|
+
}
|
|
18721
|
+
updateDraft(value) {
|
|
18722
|
+
this.draft.set(value ?? '');
|
|
18723
|
+
}
|
|
18724
|
+
finishEdit(event) {
|
|
18725
|
+
event?.stopPropagation();
|
|
18726
|
+
const text = this.draft().trimEnd();
|
|
18727
|
+
if (text !== this.note().text) {
|
|
18728
|
+
this.contentChange.emit({ noteId: this.note().id, text });
|
|
18729
|
+
}
|
|
18730
|
+
this.editEnd.emit({ noteId: this.note().id });
|
|
18731
|
+
}
|
|
18732
|
+
finishEditFromKeyboard(event) {
|
|
18733
|
+
event.preventDefault();
|
|
18734
|
+
this.finishEdit(event);
|
|
18735
|
+
}
|
|
18736
|
+
iconForColor(color) {
|
|
18737
|
+
return color.key === this.note().color ? 'general.check' : undefined;
|
|
18738
|
+
}
|
|
18739
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: CanvasNoteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18740
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: CanvasNoteComponent, isStandalone: true, selector: "fp-canvas-note", inputs: { note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: true, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", colorChange: "colorChange", duplicate: "duplicate", remove: "remove", editStart: "editStart", editEnd: "editEnd" }, host: { attributes: { "tabindex": "0" }, properties: { "class.is-selected": "selected()", "style.width.px": "note().width", "style.height.px": "note().height", "style.--fp-note-bg": "color().background", "style.--fp-note-border": "color().border", "style.--fp-note-text": "color().text", "attr.aria-label": "noteLabel()" }, classAttribute: "fp-canvas-note-host group/note block touch-none select-none outline-none" }, ngImport: i0, template: "@if (selected()) {\n <div\n class=\"absolute -top-10 start-2 z-10 flex items-center gap-1.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background)/95 px-1.5 py-1 shadow-lg backdrop-blur\"\n role=\"toolbar\"\n [attr.aria-label]=\"'flowplus.canvas.noteActions' | transloco\"\n fDragBlocker\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.editNote' | transloco\"\n (onClick)=\"startEdit($event)\"\n />\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.copy-05\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.duplicateNote' | transloco\"\n (onClick)=\"duplicate.emit({ noteId: note().id })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.deleteNote' | transloco\"\n (onClick)=\"remove.emit({ noteId: note().id })\"\n />\n <span class=\"mx-1 h-4 w-px bg-(--p-content-border-color)\"></span>\n @for (option of colors(); track option.key) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"iconForColor(option)\"\n styleClass=\"fp-note-swatch\"\n [style.--fp-note-swatch]=\"option.background\"\n [attr.aria-label]=\"option.label\"\n [tooltip]=\"option.label\"\n (onClick)=\"colorChange.emit({ noteId: note().id, color: option.key })\"\n />\n }\n </div>\n}\n\n<article\n class=\"fp-canvas-note-card relative flex h-full w-full overflow-hidden rounded-[9px] border-2 backdrop-blur-[1px] transition-[border-color,box-shadow,transform] duration-150\"\n (dblclick)=\"startEdit($event)\"\n>\n @if (editing()) {\n <div\n class=\"flex h-full w-full flex-col p-3\"\n fDragBlocker\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (focusout)=\"finishEdit($event)\"\n >\n <mt-textarea-field\n class=\"fp-note-editor min-h-0 flex-1\"\n [field]=\"false\"\n [rows]=\"'8'\"\n [maxLength]=\"5000\"\n [pInputs]=\"textareaInputs\"\n [placeholder]=\"'flowplus.canvas.notePlaceholder' | transloco\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"updateDraft($event)\"\n (keydown.control.enter)=\"finishEditFromKeyboard($event)\"\n (keydown.meta.enter)=\"finishEditFromKeyboard($event)\"\n />\n </div>\n } @else {\n <div class=\"fp-scroll min-h-0 flex-1 overflow-auto px-5 py-4\">\n @for (line of markdownLines(); track $index) {\n @if (line.kind === \"empty\") {\n <div class=\"h-3\"></div>\n } @else {\n <p\n class=\"m-0 max-w-full break-words\"\n [class.text-[28px]]=\"line.kind === 'h1'\"\n [class.text-[24px]]=\"line.kind === 'h2'\"\n [class.text-[15px]]=\"line.kind === 'body'\"\n [class.font-bold]=\"line.kind !== 'body'\"\n [class.leading-tight]=\"line.kind !== 'body'\"\n [class.leading-6]=\"line.kind === 'body'\"\n [class.mb-2]=\"line.kind !== 'body'\"\n [class.mb-1]=\"line.kind === 'body'\"\n >\n @for (segment of line.segments; track $index) {\n <span [class.font-bold]=\"segment.bold\">{{ segment.text }}</span>\n }\n </p>\n }\n }\n </div>\n }\n\n <span\n fResizeHandle\n [fResizeHandleType]=\"resizeHandle.RIGHT_BOTTOM\"\n class=\"fp-note-resize-handle absolute end-1.5 bottom-1.5 h-4 w-4 cursor-nwse-resize rounded-sm border-e-2 border-b-2 opacity-0 transition-opacity\"\n [attr.aria-label]=\"'flowplus.canvas.resizeNote' | transloco\"\n ></span>\n</article>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FFlowModule }, { kind: "directive", type: i1$2.FResizeHandleDirective, selector: "[fResizeHandle]", inputs: ["fResizeHandleType"] }, { kind: "directive", type: i1$2.FDragBlockerDirective, selector: "[fDragBlocker]" }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
18741
|
+
}
|
|
18742
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: CanvasNoteComponent, decorators: [{
|
|
18743
|
+
type: Component,
|
|
18744
|
+
args: [{ selector: 'fp-canvas-note', standalone: true, imports: [
|
|
18745
|
+
CommonModule,
|
|
18746
|
+
FormsModule,
|
|
18747
|
+
FFlowModule,
|
|
18748
|
+
TranslocoModule,
|
|
18749
|
+
Button,
|
|
18750
|
+
TextareaField,
|
|
18751
|
+
Tooltip,
|
|
18752
|
+
Icon,
|
|
18753
|
+
], host: {
|
|
18754
|
+
class: 'fp-canvas-note-host group/note block touch-none select-none outline-none',
|
|
18755
|
+
'[class.is-selected]': 'selected()',
|
|
18756
|
+
'[style.width.px]': 'note().width',
|
|
18757
|
+
'[style.height.px]': 'note().height',
|
|
18758
|
+
'[style.--fp-note-bg]': 'color().background',
|
|
18759
|
+
'[style.--fp-note-border]': 'color().border',
|
|
18760
|
+
'[style.--fp-note-text]': 'color().text',
|
|
18761
|
+
'[attr.aria-label]': 'noteLabel()',
|
|
18762
|
+
tabindex: '0',
|
|
18763
|
+
}, template: "@if (selected()) {\n <div\n class=\"absolute -top-10 start-2 z-10 flex items-center gap-1.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background)/95 px-1.5 py-1 shadow-lg backdrop-blur\"\n role=\"toolbar\"\n [attr.aria-label]=\"'flowplus.canvas.noteActions' | transloco\"\n fDragBlocker\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.editNote' | transloco\"\n (onClick)=\"startEdit($event)\"\n />\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.copy-05\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.duplicateNote' | transloco\"\n (onClick)=\"duplicate.emit({ noteId: note().id })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n styleClass=\"fp-note-tool-button\"\n [tooltip]=\"'flowplus.canvas.deleteNote' | transloco\"\n (onClick)=\"remove.emit({ noteId: note().id })\"\n />\n <span class=\"mx-1 h-4 w-px bg-(--p-content-border-color)\"></span>\n @for (option of colors(); track option.key) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"iconForColor(option)\"\n styleClass=\"fp-note-swatch\"\n [style.--fp-note-swatch]=\"option.background\"\n [attr.aria-label]=\"option.label\"\n [tooltip]=\"option.label\"\n (onClick)=\"colorChange.emit({ noteId: note().id, color: option.key })\"\n />\n }\n </div>\n}\n\n<article\n class=\"fp-canvas-note-card relative flex h-full w-full overflow-hidden rounded-[9px] border-2 backdrop-blur-[1px] transition-[border-color,box-shadow,transform] duration-150\"\n (dblclick)=\"startEdit($event)\"\n>\n @if (editing()) {\n <div\n class=\"flex h-full w-full flex-col p-3\"\n fDragBlocker\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (focusout)=\"finishEdit($event)\"\n >\n <mt-textarea-field\n class=\"fp-note-editor min-h-0 flex-1\"\n [field]=\"false\"\n [rows]=\"'8'\"\n [maxLength]=\"5000\"\n [pInputs]=\"textareaInputs\"\n [placeholder]=\"'flowplus.canvas.notePlaceholder' | transloco\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"updateDraft($event)\"\n (keydown.control.enter)=\"finishEditFromKeyboard($event)\"\n (keydown.meta.enter)=\"finishEditFromKeyboard($event)\"\n />\n </div>\n } @else {\n <div class=\"fp-scroll min-h-0 flex-1 overflow-auto px-5 py-4\">\n @for (line of markdownLines(); track $index) {\n @if (line.kind === \"empty\") {\n <div class=\"h-3\"></div>\n } @else {\n <p\n class=\"m-0 max-w-full break-words\"\n [class.text-[28px]]=\"line.kind === 'h1'\"\n [class.text-[24px]]=\"line.kind === 'h2'\"\n [class.text-[15px]]=\"line.kind === 'body'\"\n [class.font-bold]=\"line.kind !== 'body'\"\n [class.leading-tight]=\"line.kind !== 'body'\"\n [class.leading-6]=\"line.kind === 'body'\"\n [class.mb-2]=\"line.kind !== 'body'\"\n [class.mb-1]=\"line.kind === 'body'\"\n >\n @for (segment of line.segments; track $index) {\n <span [class.font-bold]=\"segment.bold\">{{ segment.text }}</span>\n }\n </p>\n }\n }\n </div>\n }\n\n <span\n fResizeHandle\n [fResizeHandleType]=\"resizeHandle.RIGHT_BOTTOM\"\n class=\"fp-note-resize-handle absolute end-1.5 bottom-1.5 h-4 w-4 cursor-nwse-resize rounded-sm border-e-2 border-b-2 opacity-0 transition-opacity\"\n [attr.aria-label]=\"'flowplus.canvas.resizeNote' | transloco\"\n ></span>\n</article>\n" }]
|
|
18764
|
+
}], ctorParameters: () => [], propDecorators: { note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], contentChange: [{ type: i0.Output, args: ["contentChange"] }], colorChange: [{ type: i0.Output, args: ["colorChange"] }], duplicate: [{ type: i0.Output, args: ["duplicate"] }], remove: [{ type: i0.Output, args: ["remove"] }], editStart: [{ type: i0.Output, args: ["editStart"] }], editEnd: [{ type: i0.Output, args: ["editEnd"] }] } });
|
|
18765
|
+
function parseMarkdown(text) {
|
|
18766
|
+
const rawLines = text.split(/\r?\n/);
|
|
18767
|
+
const lines = rawLines.length ? rawLines : [''];
|
|
18768
|
+
return lines.map((line) => {
|
|
18769
|
+
const trimmed = line.trim();
|
|
18770
|
+
if (!trimmed)
|
|
18771
|
+
return { kind: 'empty', segments: [] };
|
|
18772
|
+
if (trimmed.startsWith('## ')) {
|
|
18773
|
+
return {
|
|
18774
|
+
kind: 'h2',
|
|
18775
|
+
segments: parseInline(trimmed.slice(3).trim()),
|
|
18776
|
+
};
|
|
18777
|
+
}
|
|
18778
|
+
if (trimmed.startsWith('# ')) {
|
|
18779
|
+
return {
|
|
18780
|
+
kind: 'h1',
|
|
18781
|
+
segments: parseInline(trimmed.slice(2).trim()),
|
|
18782
|
+
};
|
|
18783
|
+
}
|
|
18784
|
+
return { kind: 'body', segments: parseInline(line) };
|
|
18785
|
+
});
|
|
18786
|
+
}
|
|
18787
|
+
function parseInline(text) {
|
|
18788
|
+
const parts = [];
|
|
18789
|
+
let rest = text;
|
|
18790
|
+
while (rest.length) {
|
|
18791
|
+
const start = rest.indexOf('**');
|
|
18792
|
+
if (start < 0) {
|
|
18793
|
+
parts.push({ text: rest, bold: false });
|
|
18794
|
+
break;
|
|
18795
|
+
}
|
|
18796
|
+
if (start > 0) {
|
|
18797
|
+
parts.push({ text: rest.slice(0, start), bold: false });
|
|
18798
|
+
}
|
|
18799
|
+
const afterStart = rest.slice(start + 2);
|
|
18800
|
+
const end = afterStart.indexOf('**');
|
|
18801
|
+
if (end < 0) {
|
|
18802
|
+
parts.push({ text: rest.slice(start), bold: false });
|
|
18803
|
+
break;
|
|
18804
|
+
}
|
|
18805
|
+
parts.push({ text: afterStart.slice(0, end), bold: true });
|
|
18806
|
+
rest = afterStart.slice(end + 2);
|
|
18807
|
+
}
|
|
18808
|
+
return parts;
|
|
18809
|
+
}
|
|
18810
|
+
|
|
18293
18811
|
function canvasIssueSeverity(issues) {
|
|
18294
18812
|
const list = issues ?? [];
|
|
18295
18813
|
if (list.some((issue) => issue.severity === 'Error'))
|
|
@@ -19240,12 +19758,23 @@ class FlowCanvasComponent {
|
|
|
19240
19758
|
canvasBackgroundClick = new EventEmitter();
|
|
19241
19759
|
/** Add affordance → page opens the left palette (no floating popover). */
|
|
19242
19760
|
requestAddStep = new EventEmitter();
|
|
19761
|
+
noteUpdate = new EventEmitter();
|
|
19762
|
+
noteDuplicate = new EventEmitter();
|
|
19763
|
+
noteDelete = new EventEmitter();
|
|
19243
19764
|
/* -------- VM signals -------- */
|
|
19765
|
+
canvasLayers = [
|
|
19766
|
+
EFCanvasLayer.GROUPS,
|
|
19767
|
+
EFCanvasLayer.CONNECTIONS,
|
|
19768
|
+
EFCanvasLayer.NODES,
|
|
19769
|
+
];
|
|
19244
19770
|
nodes = computed(() => this.store.nodeVms(), ...(ngDevMode ? [{ debugName: "nodes" }] : /* istanbul ignore next */ []));
|
|
19771
|
+
canvasNotes = computed(() => this.store.canvasNotes(), ...(ngDevMode ? [{ debugName: "canvasNotes" }] : /* istanbul ignore next */ []));
|
|
19245
19772
|
edges = computed(() => this.store.edgeVms(), ...(ngDevMode ? [{ debugName: "edges" }] : /* istanbul ignore next */ []));
|
|
19246
19773
|
triggerNodes = computed(() => this.store.triggerNodeVms(), ...(ngDevMode ? [{ debugName: "triggerNodes" }] : /* istanbul ignore next */ []));
|
|
19247
19774
|
branchLanes = computed(() => this.store.branchLaneVms(), ...(ngDevMode ? [{ debugName: "branchLanes" }] : /* istanbul ignore next */ []));
|
|
19248
19775
|
viewport = computed(() => this.store.viewport(), ...(ngDevMode ? [{ debugName: "viewport" }] : /* istanbul ignore next */ []));
|
|
19776
|
+
selectedCanvasNoteIds = computed(() => this.store.selectedCanvasNoteIds(), ...(ngDevMode ? [{ debugName: "selectedCanvasNoteIds" }] : /* istanbul ignore next */ []));
|
|
19777
|
+
editingNoteId = signal(null, ...(ngDevMode ? [{ debugName: "editingNoteId" }] : /* istanbul ignore next */ []));
|
|
19249
19778
|
/**
|
|
19250
19779
|
* Minimum world size the minimap renders. A very small value (Foblex's
|
|
19251
19780
|
* default-ish 80) makes one or two nodes fill the whole minimap, which
|
|
@@ -19410,7 +19939,7 @@ class FlowCanvasComponent {
|
|
|
19410
19939
|
}
|
|
19411
19940
|
/** Real Foblex nodes on the canvas: steps + virtual trigger nodes. */
|
|
19412
19941
|
totalNodeCount() {
|
|
19413
|
-
return this.nodes().length + this.triggerNodes().length;
|
|
19942
|
+
return (this.nodes().length + this.triggerNodes().length + this.canvasNotes().length);
|
|
19414
19943
|
}
|
|
19415
19944
|
/**
|
|
19416
19945
|
* Keep the toolbar zoom label and the persisted viewport in sync with
|
|
@@ -19452,6 +19981,11 @@ class FlowCanvasComponent {
|
|
|
19452
19981
|
focusTrigger(triggerId) {
|
|
19453
19982
|
this.requestFocus(`trigger:${triggerId}`, false);
|
|
19454
19983
|
}
|
|
19984
|
+
/** Public: center + select a sticky canvas note. */
|
|
19985
|
+
focusNote(noteId) {
|
|
19986
|
+
this.requestFocus(canvasNoteGroupId(noteId), false);
|
|
19987
|
+
this.store.selectCanvasNote(noteId);
|
|
19988
|
+
}
|
|
19455
19989
|
/**
|
|
19456
19990
|
* Public: center + select a connection. Foblex centers nodes/groups, not
|
|
19457
19991
|
* edges, so we center on the connection's source node and highlight the
|
|
@@ -19492,6 +20026,10 @@ class FlowCanvasComponent {
|
|
|
19492
20026
|
});
|
|
19493
20027
|
}
|
|
19494
20028
|
canvasNodeExists(canvasNodeId) {
|
|
20029
|
+
const noteId = parseCanvasNoteGroupId(canvasNodeId);
|
|
20030
|
+
if (noteId) {
|
|
20031
|
+
return this.canvasNotes().some((note) => note.id === noteId);
|
|
20032
|
+
}
|
|
19495
20033
|
if (canvasNodeId.startsWith('trigger:')) {
|
|
19496
20034
|
const tid = Number(canvasNodeId.slice('trigger:'.length));
|
|
19497
20035
|
return this.triggerNodes().some((t) => t.triggerId === tid);
|
|
@@ -19935,7 +20473,17 @@ class FlowCanvasComponent {
|
|
|
19935
20473
|
onMoveNodes(event) {
|
|
19936
20474
|
const nodePositions = [];
|
|
19937
20475
|
const triggerPositions = [];
|
|
20476
|
+
const notePositions = [];
|
|
19938
20477
|
for (const move of event.nodes) {
|
|
20478
|
+
const noteId = parseCanvasNoteGroupId(move.id);
|
|
20479
|
+
if (noteId) {
|
|
20480
|
+
notePositions.push({
|
|
20481
|
+
noteId,
|
|
20482
|
+
x: move.position.x,
|
|
20483
|
+
y: move.position.y,
|
|
20484
|
+
});
|
|
20485
|
+
continue;
|
|
20486
|
+
}
|
|
19939
20487
|
const parsed = parseNodeId(move.id);
|
|
19940
20488
|
if (parsed.kind === 'step' && parsed.stepId != null) {
|
|
19941
20489
|
nodePositions.push({
|
|
@@ -19952,18 +20500,49 @@ class FlowCanvasComponent {
|
|
|
19952
20500
|
});
|
|
19953
20501
|
}
|
|
19954
20502
|
}
|
|
19955
|
-
this.commitCanvasPositions(nodePositions, triggerPositions);
|
|
20503
|
+
this.commitCanvasPositions(nodePositions, triggerPositions, notePositions);
|
|
19956
20504
|
}
|
|
19957
20505
|
onStepPositionChange(stepId, position) {
|
|
19958
|
-
this.commitCanvasPositions([{ stepId, x: position.x, y: position.y }], []);
|
|
20506
|
+
this.commitCanvasPositions([{ stepId, x: position.x, y: position.y }], [], []);
|
|
19959
20507
|
}
|
|
19960
20508
|
onTriggerPositionChange(triggerId, position) {
|
|
19961
|
-
this.commitCanvasPositions([], [{ triggerId, x: position.x, y: position.y }]);
|
|
20509
|
+
this.commitCanvasPositions([], [{ triggerId, x: position.x, y: position.y }], []);
|
|
20510
|
+
}
|
|
20511
|
+
onNotePositionChange(noteId, position) {
|
|
20512
|
+
this.commitCanvasPositions([], [], [{ noteId, x: position.x, y: position.y }]);
|
|
20513
|
+
}
|
|
20514
|
+
onNoteSizeChange(noteId, size) {
|
|
20515
|
+
this.noteUpdate.emit({
|
|
20516
|
+
noteId,
|
|
20517
|
+
patch: { width: size.width, height: size.height },
|
|
20518
|
+
});
|
|
20519
|
+
}
|
|
20520
|
+
onNoteContentChange(event) {
|
|
20521
|
+
this.noteUpdate.emit({
|
|
20522
|
+
noteId: event.noteId,
|
|
20523
|
+
patch: { text: event.text },
|
|
20524
|
+
});
|
|
20525
|
+
}
|
|
20526
|
+
onNoteColorChange(event) {
|
|
20527
|
+
this.noteUpdate.emit({
|
|
20528
|
+
noteId: event.noteId,
|
|
20529
|
+
patch: { color: event.color },
|
|
20530
|
+
});
|
|
20531
|
+
}
|
|
20532
|
+
onNoteDuplicate(event) {
|
|
20533
|
+
this.noteDuplicate.emit(event);
|
|
20534
|
+
}
|
|
20535
|
+
onNoteDelete(event) {
|
|
20536
|
+
this.noteDelete.emit(event);
|
|
19962
20537
|
}
|
|
19963
|
-
|
|
19964
|
-
|
|
20538
|
+
onNoteEditStart(noteId) {
|
|
20539
|
+
this.store.selectCanvasNote(noteId);
|
|
20540
|
+
this.editingNoteId.set(noteId);
|
|
20541
|
+
}
|
|
20542
|
+
commitCanvasPositions(nodes, triggers, notes = []) {
|
|
20543
|
+
if (!nodes.length && !triggers.length && !notes.length)
|
|
19965
20544
|
return false;
|
|
19966
|
-
const changed = this.store.setLayoutPositions({ nodes, triggers }, { scheduleSave: !this.positionDragActive });
|
|
20545
|
+
const changed = this.store.setLayoutPositions({ nodes, triggers, notes }, { scheduleSave: !this.positionDragActive });
|
|
19967
20546
|
if (this.positionDragActive && changed) {
|
|
19968
20547
|
this.positionChangedDuringDrag = true;
|
|
19969
20548
|
}
|
|
@@ -19971,7 +20550,7 @@ class FlowCanvasComponent {
|
|
|
19971
20550
|
}
|
|
19972
20551
|
syncCanvasPositionsFromDom() {
|
|
19973
20552
|
const positions = this.readCanvasPositionSnapshot();
|
|
19974
|
-
return this.commitCanvasPositions(positions.nodes, positions.triggers);
|
|
20553
|
+
return this.commitCanvasPositions(positions.nodes, positions.triggers, positions.notes);
|
|
19975
20554
|
}
|
|
19976
20555
|
syncStableCanvasPositions() {
|
|
19977
20556
|
if (this.isPositionSyncSuppressed())
|
|
@@ -19982,7 +20561,7 @@ class FlowCanvasComponent {
|
|
|
19982
20561
|
this.lastObservedPositionSignature = signature;
|
|
19983
20562
|
return;
|
|
19984
20563
|
}
|
|
19985
|
-
const changed = this.commitCanvasPositions(positions.nodes, positions.triggers);
|
|
20564
|
+
const changed = this.commitCanvasPositions(positions.nodes, positions.triggers, positions.notes);
|
|
19986
20565
|
if (this.positionDragActive) {
|
|
19987
20566
|
const shouldSave = changed || this.positionChangedDuringDrag;
|
|
19988
20567
|
this.positionDragActive = false;
|
|
@@ -20015,7 +20594,16 @@ class FlowCanvasComponent {
|
|
|
20015
20594
|
: null;
|
|
20016
20595
|
})
|
|
20017
20596
|
.filter((item) => item != null);
|
|
20018
|
-
|
|
20597
|
+
const notes = Array.from(this.hostEl.querySelectorAll('fp-canvas-note[data-fp-note]'))
|
|
20598
|
+
.map((el) => {
|
|
20599
|
+
const noteId = el.dataset['fpNote'];
|
|
20600
|
+
const position = readTranslatePosition(el);
|
|
20601
|
+
return noteId && position
|
|
20602
|
+
? { noteId, x: position.x, y: position.y }
|
|
20603
|
+
: null;
|
|
20604
|
+
})
|
|
20605
|
+
.filter((item) => item != null);
|
|
20606
|
+
return { nodes, triggers, notes };
|
|
20019
20607
|
}
|
|
20020
20608
|
schedulePointerPositionSync(delayMs) {
|
|
20021
20609
|
if (this.isPositionSyncSuppressed())
|
|
@@ -20135,8 +20723,18 @@ class FlowCanvasComponent {
|
|
|
20135
20723
|
if (c != null)
|
|
20136
20724
|
connectionIds.push(c);
|
|
20137
20725
|
}
|
|
20138
|
-
|
|
20139
|
-
|
|
20726
|
+
const canvasNoteIds = [];
|
|
20727
|
+
for (const id of event.fGroupIds) {
|
|
20728
|
+
const noteId = parseCanvasNoteGroupId(id);
|
|
20729
|
+
if (noteId)
|
|
20730
|
+
canvasNoteIds.push(noteId);
|
|
20731
|
+
}
|
|
20732
|
+
this.store.setSelectionFromCanvas(stepIds, connectionIds, canvasNoteIds);
|
|
20733
|
+
if (!canvasNoteIds.length)
|
|
20734
|
+
this.editingNoteId.set(null);
|
|
20735
|
+
if (stepIds.length === 0 &&
|
|
20736
|
+
connectionIds.length === 0 &&
|
|
20737
|
+
canvasNoteIds.length === 0) {
|
|
20140
20738
|
this.canvasBackgroundClick.emit();
|
|
20141
20739
|
}
|
|
20142
20740
|
}
|
|
@@ -20194,6 +20792,9 @@ class FlowCanvasComponent {
|
|
|
20194
20792
|
isConnectionSelected(connectionId) {
|
|
20195
20793
|
return this.selectionConnectionIds().includes(connectionId);
|
|
20196
20794
|
}
|
|
20795
|
+
canvasNoteGroupId(noteId) {
|
|
20796
|
+
return canvasNoteGroupId(noteId);
|
|
20797
|
+
}
|
|
20197
20798
|
/* -------- node hover-bar forwards -------- */
|
|
20198
20799
|
onNodeQuickAdd(e) {
|
|
20199
20800
|
this.nodeQuickAdd.emit(e);
|
|
@@ -20247,7 +20848,7 @@ class FlowCanvasComponent {
|
|
|
20247
20848
|
this.triggerStartDisconnect.emit(e);
|
|
20248
20849
|
}
|
|
20249
20850
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FlowCanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20250
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FlowCanvasComponent, isStandalone: true, selector: "fp-flow-canvas", outputs: { paletteDrop: "paletteDrop", connectionCreate: "connectionCreate", connectionReassign: "connectionReassign", triggerStartConnect: "triggerStartConnect", triggerStartReassign: "triggerStartReassign", triggerStartDisconnect: "triggerStartDisconnect", connectionQuickAdd: "connectionQuickAdd", quickAddPick: "quickAddPick", autoLayoutRequested: "autoLayoutRequested", loaded: "loaded", nodeQuickAdd: "nodeQuickAdd", nodePortPlusClick: "nodePortPlusClick", nodeDuplicate: "nodeDuplicate", nodeRemove: "nodeRemove", nodeOpenDetails: "nodeOpenDetails", edgeInsertStep: "edgeInsertStep", edgeRemove: "edgeRemove", edgeEditFormula: "edgeEditFormula", edgeOpenDetails: "edgeOpenDetails", assignNodeToConnection: "assignNodeToConnection", openChildWorkflow: "openChildWorkflow", starterAddTrigger: "starterAddTrigger", triggerOpenDetails: "triggerOpenDetails", triggerExecute: "triggerExecute", triggerToggleEnabled: "triggerToggleEnabled", triggerDelete: "triggerDelete", canvasBackgroundClick: "canvasBackgroundClick", requestAddStep: "requestAddStep" }, providers: [
|
|
20851
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FlowCanvasComponent, isStandalone: true, selector: "fp-flow-canvas", outputs: { paletteDrop: "paletteDrop", connectionCreate: "connectionCreate", connectionReassign: "connectionReassign", triggerStartConnect: "triggerStartConnect", triggerStartReassign: "triggerStartReassign", triggerStartDisconnect: "triggerStartDisconnect", connectionQuickAdd: "connectionQuickAdd", quickAddPick: "quickAddPick", autoLayoutRequested: "autoLayoutRequested", loaded: "loaded", nodeQuickAdd: "nodeQuickAdd", nodePortPlusClick: "nodePortPlusClick", nodeDuplicate: "nodeDuplicate", nodeRemove: "nodeRemove", nodeOpenDetails: "nodeOpenDetails", edgeInsertStep: "edgeInsertStep", edgeRemove: "edgeRemove", edgeEditFormula: "edgeEditFormula", edgeOpenDetails: "edgeOpenDetails", assignNodeToConnection: "assignNodeToConnection", openChildWorkflow: "openChildWorkflow", starterAddTrigger: "starterAddTrigger", triggerOpenDetails: "triggerOpenDetails", triggerExecute: "triggerExecute", triggerToggleEnabled: "triggerToggleEnabled", triggerDelete: "triggerDelete", canvasBackgroundClick: "canvasBackgroundClick", requestAddStep: "requestAddStep", noteUpdate: "noteUpdate", noteDuplicate: "noteDuplicate", noteDelete: "noteDelete" }, providers: [
|
|
20251
20852
|
provideFFlow({ id: 'flowplus-builder' }, withReflowOnResize({
|
|
20252
20853
|
collision: EFReflowCollision.STOP,
|
|
20253
20854
|
deltaSource: EFReflowDeltaSource.EDGE_BASED,
|
|
@@ -20255,7 +20856,7 @@ class FlowCanvasComponent {
|
|
|
20255
20856
|
maxCascadeDepth: 8,
|
|
20256
20857
|
maxAbsoluteShiftPerPlan: 10000,
|
|
20257
20858
|
})),
|
|
20258
|
-
], viewQueries: [{ propertyName: "flow", first: true, predicate: ["flow"], descendants: true, isSignal: true }, { propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true, isSignal: true }], ngImport: i0, template: "<f-flow\n #flow\n fDraggable\n [vCellSize]=\"gridCellSize\"\n [hCellSize]=\"gridCellSize\"\n [fCellSizeWhileDragging]=\"false\"\n (fFullRendered)=\"onFullRendered()\"\n (fNodesRendered)=\"onNodesRendered()\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fDragStarted)=\"onDragStarted($event)\"\n (fDragEnded)=\"onDragEnded()\"\n (fMoveNodes)=\"onMoveNodes($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n>\n <!-- Background dot grid \u2014 its spacing is locked to the drag cell size so\n nodes snap exactly onto the visible dots (Foblex grid-system). -->\n <f-background>\n <f-circle-pattern [radius]=\"gridCellSize\" />\n </f-background>\n\n <!-- Alignment guides + marquee selection are `f-flow` children (NOT\n `f-canvas` children \u2014 `f-canvas` only projects connections/nodes/groups,\n so helpers placed inside it are silently dropped). This mirrors the\n Foblex call-center reference layout. -->\n <f-line-alignment [fAlignThreshold]=\"20\" />\n <f-selection-area />\n\n <!-- Auto-pan: when dragging a node / connection near the viewport edge, the\n canvas pans to follow, so you can wire across off-screen nodes without\n letting go. (Foblex `f-auto-pan` plugin.) -->\n <f-auto-pan [fEdgeThreshold]=\"36\" [fSpeed]=\"8\" />\n\n <f-canvas\n #canvas\n fZoom\n [debounceTime]=\"200\"\n (fCanvasChange)=\"onCanvasChange($event)\"\n >\n <!-- Floating behavior anchors the preview at the connector boundary along\n the center\u2192pointer axis, so a connection dragged from the \"+\" outlet\n leaves it cleanly (NOT from its bottom edge \u2014 `fixed` defaults an AUTO\n connectable side to bottom) and snaps to the target's nearest edge. -->\n <f-connection-for-create\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-connection-for-create>\n\n <!-- Auto-snap: while dragging a new/reassigned connection, snap to the\n nearest connector within the threshold (forgiving connect UX). -->\n <f-snap-connection\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fSnapThreshold]=\"40\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-snap-connection>\n\n <!-- ngProjectAs is REQUIRED: `f-canvas` distributes projected content\n into its layer containers via selective `<ng-content select=\"...\">`\n with NO catch-all slot. A wrapper component (`fp-flow-node`, etc.)\n does not match `[fNode]` / `f-connection` on its host, so without\n `ngProjectAs` Foblex silently drops it and the canvas renders empty.\n The actual Foblex directive lives on the wrapper's inner element and\n self-registers via the mediator, so routing the wrapper into the\n right layer is all that's needed. -->\n @for (lane of branchLanes(); track lane.id) {\n <div\n ngProjectAs=\"[fGroup]\"\n class=\"pointer-events-none absolute z-0 rounded-[14px] border border-dashed border-[color-mix(in_srgb,rgb(var(--fp-parallel))_55%,transparent)] bg-[color-mix(in_srgb,rgb(var(--fp-parallel))_8%,transparent)]\"\n [attr.data-color-token]=\"lane.colorToken\"\n [style.left.px]=\"lane.x\"\n [style.top.px]=\"lane.y\"\n [style.width.px]=\"lane.width\"\n [style.height.px]=\"lane.height\"\n >\n <span\n class=\"pointer-events-auto absolute -top-2.5 start-3 rounded-full border border-[color-mix(in_srgb,rgb(var(--fp-parallel))_40%,transparent)] bg-(--p-content-background) px-2 py-px text-[10.5px] font-semibold text-[rgb(var(--fp-parallel))]\"\n >{{ lane.label }}</span\n >\n </div>\n }\n\n <!-- Connections are inlined here (NOT wrapped in a component) so each\n <f-connection> is a DIRECT child of Foblex's connections container.\n A wrapper would make `hostElement.parentElement` the wrapper instead\n of the container, which makes Foblex's select layer-raise throw\n \"Unknown container\" the moment an edge is selected. Same call-center\n pattern used for nodes/triggers. -->\n @for (edge of edges(); track edge.id) {\n <f-connection\n class=\"group\"\n [attr.data-fp-edge]=\"edge.connectionId\"\n [fConnectionId]=\"edge.id\"\n [fOutputId]=\"edge.sourcePortId\"\n [fInputId]=\"edge.targetPortId\"\n [fBehavior]=\"'fixed'\"\n [fType]=\"'adaptive-curve'\"\n [fOffset]=\"32\"\n fInputSide=\"calculate\"\n [fReassignableStart]=\"edge.edgeKind !== 'triggerStart'\"\n [fReassignDisabled]=\"edge.edgeKind === 'triggerStart'\"\n [class.fp-edge]=\"true\"\n [class.is-trigger-start]=\"edge.edgeKind === 'triggerStart'\"\n [class.is-drop-target]=\"isDropTargetEdge(edge.connectionId)\"\n [class.is-selected]=\"isConnectionSelected(edge.connectionId)\"\n [class.is-error]=\"edge.isInvalid\"\n [class.is-formula]=\"edge.isFormula\"\n [class.is-runtime-active]=\"edge.runtimeState === 'active'\"\n [class.is-runtime-completed]=\"edge.runtimeState === 'completed'\"\n [class.is-runtime-failed]=\"edge.runtimeState === 'failed'\"\n [class.is-runtime-waiting]=\"edge.runtimeState === 'waiting'\"\n (dblclick)=\"\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n >\n <!-- Arrow marker at the target \u2014 the connection carries the arrowhead;\n the input lives on the node host (no separate input element). -->\n <f-connection-marker-arrow [type]=\"markerEnd\" />\n\n <!-- Editable waypoints are intentionally NOT rendered: there is no\n backend persistence wired for manual bends, so exposing draggable\n waypoints would silently lose the user's edits on reload. -->\n\n <!-- Label / formula badge \u2014 pinned to the CENTER of the line\n (connection-content position 0.5). Fades out on hover/selected so\n the centered action box can take its place. -->\n @if (edge.label) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-[rgb(var(--fp-connector))] bg-(--p-content-background) py-1 pe-2.5 ps-2 text-[11px] font-semibold text-(--p-text-color) shadow-[0_1px_3px_rgba(15,23,42,0.1)] transition-colors group-[.is-selected]:border-(--p-primary-color) group-[.is-selected]:text-(--p-primary-color)\"\n >\n <span\n class=\"size-1.5 flex-none rounded-full bg-[rgb(var(--fp-connector))] group-[.is-selected]:bg-(--p-primary-color)\"\n ></span>\n {{ edge.label }}\n </span>\n </div>\n } @else if (edge.isFormula) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"grid h-5 w-5 place-items-center rounded-full border border-(--p-content-border-color) bg-(--p-content-background) font-mono text-[12px] italic text-(--p-primary-color) shadow-sm\"\n title=\"Conditional route\"\n >\u0192</span\n >\n </div>\n }\n\n <!-- Centered action box \u2014 edit (opens the connection MODAL) + delete.\n Same content anchor (position 0.5), revealed on hover/selected and\n overlapping the label so the actions stay centered ON the line. -->\n @if (edgeIssueCount(edge) > 0) {\n <div\n fConnectionContent\n [position]=\"0.38\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"fp-node-badge grid h-[18px] w-[18px] cursor-help place-items-center rounded-sm bg-(--p-content-background) shadow-sm outline-none transition-transform focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [style.color]=\"edgeIssueColor(edge)\"\n tabindex=\"0\"\n role=\"img\"\n [attr.aria-label]=\"edgeIssueTooltip(edge)\"\n [mtTooltip]=\"edgeIssueTooltip(edge)\"\n [tooltipStyleClass]=\"edgeIssueTooltipClass(edge)\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"\n $event.stopPropagation();\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M10 3.4 18 16.8 2 16.8 Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"2.6\"\n stroke-linejoin=\"round\"\n />\n <rect x=\"9.05\" y=\"8\" width=\"1.9\" height=\"4.6\" rx=\"0.95\" fill=\"#fff\" />\n <circle cx=\"10\" cy=\"14.6\" r=\"1.05\" fill=\"#fff\" />\n </svg>\n </span>\n </div>\n }\n\n @if (edge.runtimeState && edge.runtimeTooltip) {\n <div\n fConnectionContent\n [position]=\"0.62\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"inline-flex h-[18px] w-[18px] cursor-help items-center justify-center rounded-full border bg-(--p-content-background) shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [class.animate-pulse]=\"edge.runtimeState === 'active'\"\n [style.borderColor]=\"edgeRuntimeColor(edge)\"\n [style.color]=\"edgeRuntimeColor(edge)\"\n tabindex=\"0\"\n role=\"status\"\n [attr.aria-label]=\"edge.runtimeTooltip\"\n [mtTooltip]=\"edge.runtimeTooltip\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <mt-icon [icon]=\"edgeRuntimeIcon(edge)\" class=\"[&_svg]:size-3\" />\n </span>\n </div>\n }\n\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100 group-[.is-selected]:pointer-events-auto group-[.is-selected]:opacity-100\"\n >\n <div\n class=\"flex items-center gap-0.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background) p-1 shadow-md\"\n role=\"toolbar\"\n aria-label=\"Connection actions\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (edge.edgeKind === \"triggerStart\" && edge.triggerId != null) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.settings-01\"\n [tooltip]=\"'flowplus.trigger.node.configure' | transloco\"\n (onClick)=\"onTriggerOpenDetails({ triggerId: edge.triggerId })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.link-broken-01\"\n [tooltip]=\"'flowplus.trigger.node.unlink' | transloco\"\n (onClick)=\"\n onTriggerStartDisconnect({ triggerId: edge.triggerId })\n \"\n />\n } @else {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n [tooltip]=\"'flowplus.inspector.connection.title' | transloco\"\n (onClick)=\"\n onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n [tooltip]=\"'flowplus.edge.delete' | transloco\"\n (onClick)=\"onEdgeRemove({ connectionId: edge.connectionId })\"\n />\n }\n </div>\n </div>\n </f-connection>\n }\n\n <!-- The Foblex `fNode` directive lives on the component element itself\n (not an inner div). This keeps the node element a DIRECT child of\n Foblex's nodes container, so `hostElement.parentElement` IS that\n container \u2014 required by the select/move layer-raise (otherwise it\n throws \"Unknown container\"). This is the Foblex call-center pattern;\n the `fNode` attribute also routes it into the `[fNode]` projection\n slot, so `ngProjectAs` is not needed. -->\n @for (node of nodes(); track node.id) {\n <fp-flow-node\n fNode\n fDragHandle\n fNodeInput\n [attr.data-fp-node]=\"node.stepId\"\n [fInputId]=\"node.inputs[0]?.id\"\n [fInputMultiple]=\"node.inputs[0]?.allowMultiple ?? true\"\n [fInputDisabled]=\"!node.inputs.length\"\n [fNodeId]=\"node.id\"\n [fNodePosition]=\"{ x: node.x, y: node.y }\"\n (fNodePositionChange)=\"onStepPositionChange(node.stepId, $event)\"\n [node]=\"node\"\n [connectedOutputKeys]=\"connectedOutputKeys(node.stepId)\"\n (quickAdd)=\"onNodeQuickAdd($event)\"\n (portPlusClick)=\"onNodePortPlus($event)\"\n (duplicate)=\"onNodeDuplicate($event)\"\n (remove)=\"onNodeRemove($event)\"\n (openDetails)=\"onNodeOpenDetails($event)\"\n (openChild)=\"onOpenChild($event)\"\n />\n }\n\n @for (t of triggerNodes(); track t.triggerId) {\n <fp-trigger-node\n fNode\n fDragHandle\n [attr.data-fp-trigger]=\"t.triggerId\"\n [fNodeId]=\"'trigger:' + t.triggerId\"\n [fNodePosition]=\"{ x: t.x, y: t.y }\"\n (fNodePositionChange)=\"onTriggerPositionChange(t.triggerId, $event)\"\n [trigger]=\"t\"\n [noFirstStep]=\"!t.startStepId\"\n (addFirstStep)=\"onTriggerAddFirstStep($event)\"\n (configure)=\"onTriggerOpenDetails($event)\"\n (execute)=\"onTriggerExecute($event)\"\n (toggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (remove)=\"onTriggerDelete($event)\"\n />\n }\n </f-canvas>\n\n <!-- Minimap \u2014 `f-flow` child (NOT inside `f-canvas`). Toggled from the\n canvas controls; `fMinSize` keeps a couple of nodes zoomed-out enough\n to give real spatial context. -->\n @if (minimapVisible()) {\n <f-minimap [fMinSize]=\"minimapMinSize\" />\n }\n\n @if (showStarter() && !store.loading()) {\n <fp-starter-card\n (addTrigger)=\"onStarterAddTrigger($event)\"\n (directPick)=\"onStarterDirectPick($event)\"\n />\n }\n\n <fp-canvas-controls\n [zoom]=\"zoom()\"\n [minimapVisible]=\"minimapVisible()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (fitView)=\"fitView()\"\n (resetView)=\"resetView()\"\n (toggleMinimap)=\"toggleMinimap()\"\n (autoLayout)=\"autoLayout()\"\n />\n</f-flow>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i1$2.FFlowComponent, selector: "f-flow", inputs: ["fFlowId", "fCache"], outputs: ["fNodesRendered", "fFullRendered", "fLoaded"] }, { kind: "component", type: i1$2.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime", "fLayers"], outputs: ["fCanvasChange"] }, { kind: "component", type: i1$2.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i1$2.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "component", type: i1$2.FAutoPan, selector: "f-auto-pan", inputs: ["fEdgeThreshold", "fSpeed", "fAcceleration"] }, { kind: "directive", type: i1$2.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fZoomDblClickStep"] }, { kind: "component", type: i1$2.FSelectionArea, selector: "f-selection-area", inputs: ["fTrigger"] }, { kind: "directive", type: i1$2.FConnectionContent, selector: "[fConnectionContent]", inputs: ["position", "offset", "align"] }, { kind: "component", type: i1$2.FConnectionMarkerArrow, selector: "f-connection-marker-arrow", inputs: ["type"] }, { kind: "component", type: i1$2.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "component", type: i1$2.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "component", type: i1$2.FSnapConnectionComponent, selector: "f-snap-connection", inputs: ["fSnapThreshold", "fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i1$2.FNodeInputDirective, selector: "[fNodeInput]", inputs: ["fInputId", "fInputCategory", "fInputMultiple", "fInputDisabled", "fInputConnectableSide"], exportAs: ["fNodeInput"] }, { kind: "component", type: i1$2.FLineAlignmentComponent, selector: "f-line-alignment", inputs: ["fAlignThreshold"], exportAs: ["fComponent"] }, { kind: "component", type: i1$2.FMinimapComponent, selector: "f-minimap", inputs: ["fMinSize", "fNodeRenderLimit"], exportAs: ["fComponent"] }, { kind: "directive", type: i1$2.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i1$2.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i1$2.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fConnectionWaypointsTrigger", "fMoveControlPointTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fNodeIntersectedWithConnections", "fNodeConnectionsIntersection", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fConnectionWaypointsChanged", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "component", type: FlowNodeComponent, selector: "fp-flow-node", inputs: ["node", "connectedOutputKeys"], outputs: ["positionChange", "nodeClick", "quickAdd", "portPlusClick", "duplicate", "remove", "testStep", "openChild", "openDetails"] }, { kind: "component", type: CanvasControlsComponent, selector: "fp-canvas-controls", inputs: ["zoom", "minimapVisible"], outputs: ["zoomIn", "zoomOut", "fitView", "resetView", "toggleMinimap", "autoLayout"] }, { kind: "component", type: StarterCardComponent, selector: "fp-starter-card", outputs: ["addTrigger", "directPick"] }, { kind: "component", type: TriggerNodeComponent, selector: "fp-trigger-node", inputs: ["trigger", "noFirstStep"], outputs: ["addFirstStep", "configure", "execute", "toggleEnabled", "remove", "positionChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
20859
|
+
], viewQueries: [{ propertyName: "flow", first: true, predicate: ["flow"], descendants: true, isSignal: true }, { propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true, isSignal: true }], ngImport: i0, template: "<f-flow\n #flow\n fDraggable\n [vCellSize]=\"gridCellSize\"\n [hCellSize]=\"gridCellSize\"\n [fCellSizeWhileDragging]=\"false\"\n (fFullRendered)=\"onFullRendered()\"\n (fNodesRendered)=\"onNodesRendered()\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fDragStarted)=\"onDragStarted($event)\"\n (fDragEnded)=\"onDragEnded()\"\n (fMoveNodes)=\"onMoveNodes($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n>\n <!-- Background dot grid \u2014 its spacing is locked to the drag cell size so\n nodes snap exactly onto the visible dots (Foblex grid-system). -->\n <f-background>\n <f-circle-pattern [radius]=\"gridCellSize\" />\n </f-background>\n\n <!-- Alignment guides + marquee selection are `f-flow` children (NOT\n `f-canvas` children \u2014 `f-canvas` only projects connections/nodes/groups,\n so helpers placed inside it are silently dropped). This mirrors the\n Foblex call-center reference layout. -->\n <f-line-alignment [fAlignThreshold]=\"20\" />\n <f-selection-area />\n\n <!-- Auto-pan: when dragging a node / connection near the viewport edge, the\n canvas pans to follow, so you can wire across off-screen nodes without\n letting go. (Foblex `f-auto-pan` plugin.) -->\n <f-auto-pan [fEdgeThreshold]=\"36\" [fSpeed]=\"8\" />\n\n <f-canvas\n #canvas\n fZoom\n [debounceTime]=\"200\"\n [fLayers]=\"canvasLayers\"\n (fCanvasChange)=\"onCanvasChange($event)\"\n >\n <!-- Floating behavior anchors the preview at the connector boundary along\n the center\u2192pointer axis, so a connection dragged from the \"+\" outlet\n leaves it cleanly (NOT from its bottom edge \u2014 `fixed` defaults an AUTO\n connectable side to bottom) and snaps to the target's nearest edge. -->\n <f-connection-for-create\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-connection-for-create>\n\n <!-- Auto-snap: while dragging a new/reassigned connection, snap to the\n nearest connector within the threshold (forgiving connect UX). -->\n <f-snap-connection\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fSnapThreshold]=\"40\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-snap-connection>\n\n <!-- ngProjectAs is REQUIRED: `f-canvas` distributes projected content\n into its layer containers via selective `<ng-content select=\"...\">`\n with NO catch-all slot. A wrapper component (`fp-flow-node`, etc.)\n does not match `[fNode]` / `f-connection` on its host, so without\n `ngProjectAs` Foblex silently drops it and the canvas renders empty.\n The actual Foblex directive lives on the wrapper's inner element and\n self-registers via the mediator, so routing the wrapper into the\n right layer is all that's needed. -->\n @for (note of canvasNotes(); track note.id) {\n <fp-canvas-note\n fGroup\n fDragHandle\n [attr.data-fp-note]=\"note.id\"\n [fGroupId]=\"canvasNoteGroupId(note.id)\"\n [fGroupPosition]=\"{ x: note.x, y: note.y }\"\n [fGroupSize]=\"{ width: note.width, height: note.height }\"\n [fGroupDraggingDisabled]=\"editingNoteId() === note.id\"\n [note]=\"note\"\n [selected]=\"selectedCanvasNoteIds().includes(note.id)\"\n [editing]=\"editingNoteId() === note.id\"\n (fGroupPositionChange)=\"onNotePositionChange(note.id, $event)\"\n (fGroupSizeChange)=\"onNoteSizeChange(note.id, $event)\"\n (contentChange)=\"onNoteContentChange($event)\"\n (colorChange)=\"onNoteColorChange($event)\"\n (duplicate)=\"onNoteDuplicate($event)\"\n (remove)=\"onNoteDelete($event)\"\n (editStart)=\"onNoteEditStart($event.noteId)\"\n (editEnd)=\"editingNoteId.set(null)\"\n />\n }\n\n @for (lane of branchLanes(); track lane.id) {\n <div\n ngProjectAs=\"[fGroup]\"\n class=\"pointer-events-none absolute z-0 rounded-[14px] border border-dashed border-[color-mix(in_srgb,rgb(var(--fp-parallel))_55%,transparent)] bg-[color-mix(in_srgb,rgb(var(--fp-parallel))_8%,transparent)]\"\n [attr.data-color-token]=\"lane.colorToken\"\n [style.left.px]=\"lane.x\"\n [style.top.px]=\"lane.y\"\n [style.width.px]=\"lane.width\"\n [style.height.px]=\"lane.height\"\n >\n <span\n class=\"pointer-events-auto absolute -top-2.5 start-3 rounded-full border border-[color-mix(in_srgb,rgb(var(--fp-parallel))_40%,transparent)] bg-(--p-content-background) px-2 py-px text-[10.5px] font-semibold text-[rgb(var(--fp-parallel))]\"\n >{{ lane.label }}</span\n >\n </div>\n }\n\n <!-- Connections are inlined here (NOT wrapped in a component) so each\n <f-connection> is a DIRECT child of Foblex's connections container.\n A wrapper would make `hostElement.parentElement` the wrapper instead\n of the container, which makes Foblex's select layer-raise throw\n \"Unknown container\" the moment an edge is selected. Same call-center\n pattern used for nodes/triggers. -->\n @for (edge of edges(); track edge.id) {\n <f-connection\n class=\"group\"\n [attr.data-fp-edge]=\"edge.connectionId\"\n [fConnectionId]=\"edge.id\"\n [fOutputId]=\"edge.sourcePortId\"\n [fInputId]=\"edge.targetPortId\"\n [fBehavior]=\"'fixed'\"\n [fType]=\"'adaptive-curve'\"\n [fOffset]=\"32\"\n fInputSide=\"calculate\"\n [fReassignableStart]=\"edge.edgeKind !== 'triggerStart'\"\n [fReassignDisabled]=\"edge.edgeKind === 'triggerStart'\"\n [class.fp-edge]=\"true\"\n [class.is-trigger-start]=\"edge.edgeKind === 'triggerStart'\"\n [class.is-drop-target]=\"isDropTargetEdge(edge.connectionId)\"\n [class.is-selected]=\"isConnectionSelected(edge.connectionId)\"\n [class.is-error]=\"edge.isInvalid\"\n [class.is-formula]=\"edge.isFormula\"\n [class.is-runtime-active]=\"edge.runtimeState === 'active'\"\n [class.is-runtime-completed]=\"edge.runtimeState === 'completed'\"\n [class.is-runtime-failed]=\"edge.runtimeState === 'failed'\"\n [class.is-runtime-waiting]=\"edge.runtimeState === 'waiting'\"\n (dblclick)=\"\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n >\n <!-- Arrow marker at the target \u2014 the connection carries the arrowhead;\n the input lives on the node host (no separate input element). -->\n <f-connection-marker-arrow [type]=\"markerEnd\" />\n\n <!-- Editable waypoints are intentionally NOT rendered: there is no\n backend persistence wired for manual bends, so exposing draggable\n waypoints would silently lose the user's edits on reload. -->\n\n <!-- Label / formula badge \u2014 pinned to the CENTER of the line\n (connection-content position 0.5). Fades out on hover/selected so\n the centered action box can take its place. -->\n @if (edge.label) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-[rgb(var(--fp-connector))] bg-(--p-content-background) py-1 pe-2.5 ps-2 text-[11px] font-semibold text-(--p-text-color) shadow-[0_1px_3px_rgba(15,23,42,0.1)] transition-colors group-[.is-selected]:border-(--p-primary-color) group-[.is-selected]:text-(--p-primary-color)\"\n >\n <span\n class=\"size-1.5 flex-none rounded-full bg-[rgb(var(--fp-connector))] group-[.is-selected]:bg-(--p-primary-color)\"\n ></span>\n {{ edge.label }}\n </span>\n </div>\n } @else if (edge.isFormula) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"grid h-5 w-5 place-items-center rounded-full border border-(--p-content-border-color) bg-(--p-content-background) font-mono text-[12px] italic text-(--p-primary-color) shadow-sm\"\n title=\"Conditional route\"\n >\u0192</span\n >\n </div>\n }\n\n <!-- Centered action box \u2014 edit (opens the connection MODAL) + delete.\n Same content anchor (position 0.5), revealed on hover/selected and\n overlapping the label so the actions stay centered ON the line. -->\n @if (edgeIssueCount(edge) > 0) {\n <div\n fConnectionContent\n [position]=\"0.38\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"fp-node-badge grid h-[18px] w-[18px] cursor-help place-items-center rounded-sm bg-(--p-content-background) shadow-sm outline-none transition-transform focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [style.color]=\"edgeIssueColor(edge)\"\n tabindex=\"0\"\n role=\"img\"\n [attr.aria-label]=\"edgeIssueTooltip(edge)\"\n [mtTooltip]=\"edgeIssueTooltip(edge)\"\n [tooltipStyleClass]=\"edgeIssueTooltipClass(edge)\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"\n $event.stopPropagation();\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M10 3.4 18 16.8 2 16.8 Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"2.6\"\n stroke-linejoin=\"round\"\n />\n <rect x=\"9.05\" y=\"8\" width=\"1.9\" height=\"4.6\" rx=\"0.95\" fill=\"#fff\" />\n <circle cx=\"10\" cy=\"14.6\" r=\"1.05\" fill=\"#fff\" />\n </svg>\n </span>\n </div>\n }\n\n @if (edge.runtimeState && edge.runtimeTooltip) {\n <div\n fConnectionContent\n [position]=\"0.62\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"inline-flex h-[18px] w-[18px] cursor-help items-center justify-center rounded-full border bg-(--p-content-background) shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [class.animate-pulse]=\"edge.runtimeState === 'active'\"\n [style.borderColor]=\"edgeRuntimeColor(edge)\"\n [style.color]=\"edgeRuntimeColor(edge)\"\n tabindex=\"0\"\n role=\"status\"\n [attr.aria-label]=\"edge.runtimeTooltip\"\n [mtTooltip]=\"edge.runtimeTooltip\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <mt-icon [icon]=\"edgeRuntimeIcon(edge)\" class=\"[&_svg]:size-3\" />\n </span>\n </div>\n }\n\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100 group-[.is-selected]:pointer-events-auto group-[.is-selected]:opacity-100\"\n >\n <div\n class=\"flex items-center gap-0.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background) p-1 shadow-md\"\n role=\"toolbar\"\n aria-label=\"Connection actions\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (edge.edgeKind === \"triggerStart\" && edge.triggerId != null) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.settings-01\"\n [tooltip]=\"'flowplus.trigger.node.configure' | transloco\"\n (onClick)=\"onTriggerOpenDetails({ triggerId: edge.triggerId })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.link-broken-01\"\n [tooltip]=\"'flowplus.trigger.node.unlink' | transloco\"\n (onClick)=\"\n onTriggerStartDisconnect({ triggerId: edge.triggerId })\n \"\n />\n } @else {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n [tooltip]=\"'flowplus.inspector.connection.title' | transloco\"\n (onClick)=\"\n onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n [tooltip]=\"'flowplus.edge.delete' | transloco\"\n (onClick)=\"onEdgeRemove({ connectionId: edge.connectionId })\"\n />\n }\n </div>\n </div>\n </f-connection>\n }\n\n <!-- The Foblex `fNode` directive lives on the component element itself\n (not an inner div). This keeps the node element a DIRECT child of\n Foblex's nodes container, so `hostElement.parentElement` IS that\n container \u2014 required by the select/move layer-raise (otherwise it\n throws \"Unknown container\"). This is the Foblex call-center pattern;\n the `fNode` attribute also routes it into the `[fNode]` projection\n slot, so `ngProjectAs` is not needed. -->\n @for (node of nodes(); track node.id) {\n <fp-flow-node\n fNode\n fDragHandle\n fNodeInput\n [attr.data-fp-node]=\"node.stepId\"\n [fInputId]=\"node.inputs[0]?.id\"\n [fInputMultiple]=\"node.inputs[0]?.allowMultiple ?? true\"\n [fInputDisabled]=\"!node.inputs.length\"\n [fNodeId]=\"node.id\"\n [fNodePosition]=\"{ x: node.x, y: node.y }\"\n (fNodePositionChange)=\"onStepPositionChange(node.stepId, $event)\"\n [node]=\"node\"\n [connectedOutputKeys]=\"connectedOutputKeys(node.stepId)\"\n (quickAdd)=\"onNodeQuickAdd($event)\"\n (portPlusClick)=\"onNodePortPlus($event)\"\n (duplicate)=\"onNodeDuplicate($event)\"\n (remove)=\"onNodeRemove($event)\"\n (openDetails)=\"onNodeOpenDetails($event)\"\n (openChild)=\"onOpenChild($event)\"\n />\n }\n\n @for (t of triggerNodes(); track t.triggerId) {\n <fp-trigger-node\n fNode\n fDragHandle\n [attr.data-fp-trigger]=\"t.triggerId\"\n [fNodeId]=\"'trigger:' + t.triggerId\"\n [fNodePosition]=\"{ x: t.x, y: t.y }\"\n (fNodePositionChange)=\"onTriggerPositionChange(t.triggerId, $event)\"\n [trigger]=\"t\"\n [noFirstStep]=\"!t.startStepId\"\n (addFirstStep)=\"onTriggerAddFirstStep($event)\"\n (configure)=\"onTriggerOpenDetails($event)\"\n (execute)=\"onTriggerExecute($event)\"\n (toggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (remove)=\"onTriggerDelete($event)\"\n />\n }\n </f-canvas>\n\n <!-- Minimap \u2014 `f-flow` child (NOT inside `f-canvas`). Toggled from the\n canvas controls; `fMinSize` keeps a couple of nodes zoomed-out enough\n to give real spatial context. -->\n @if (minimapVisible()) {\n <f-minimap [fMinSize]=\"minimapMinSize\" />\n }\n\n @if (showStarter() && !store.loading()) {\n <fp-starter-card\n (addTrigger)=\"onStarterAddTrigger($event)\"\n (directPick)=\"onStarterDirectPick($event)\"\n />\n }\n\n <fp-canvas-controls\n [zoom]=\"zoom()\"\n [minimapVisible]=\"minimapVisible()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (fitView)=\"fitView()\"\n (resetView)=\"resetView()\"\n (toggleMinimap)=\"toggleMinimap()\"\n (autoLayout)=\"autoLayout()\"\n />\n</f-flow>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i1$2.FFlowComponent, selector: "f-flow", inputs: ["fFlowId", "fCache"], outputs: ["fNodesRendered", "fFullRendered", "fLoaded"] }, { kind: "component", type: i1$2.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime", "fLayers"], outputs: ["fCanvasChange"] }, { kind: "component", type: i1$2.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i1$2.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "component", type: i1$2.FAutoPan, selector: "f-auto-pan", inputs: ["fEdgeThreshold", "fSpeed", "fAcceleration"] }, { kind: "directive", type: i1$2.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fZoomDblClickStep"] }, { kind: "component", type: i1$2.FSelectionArea, selector: "f-selection-area", inputs: ["fTrigger"] }, { kind: "directive", type: i1$2.FConnectionContent, selector: "[fConnectionContent]", inputs: ["position", "offset", "align"] }, { kind: "component", type: i1$2.FConnectionMarkerArrow, selector: "f-connection-marker-arrow", inputs: ["type"] }, { kind: "component", type: i1$2.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "component", type: i1$2.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "component", type: i1$2.FSnapConnectionComponent, selector: "f-snap-connection", inputs: ["fSnapThreshold", "fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i1$2.FNodeInputDirective, selector: "[fNodeInput]", inputs: ["fInputId", "fInputCategory", "fInputMultiple", "fInputDisabled", "fInputConnectableSide"], exportAs: ["fNodeInput"] }, { kind: "component", type: i1$2.FLineAlignmentComponent, selector: "f-line-alignment", inputs: ["fAlignThreshold"], exportAs: ["fComponent"] }, { kind: "component", type: i1$2.FMinimapComponent, selector: "f-minimap", inputs: ["fMinSize", "fNodeRenderLimit"], exportAs: ["fComponent"] }, { kind: "directive", type: i1$2.FGroupDirective, selector: "[fGroup]", inputs: ["fGroupId", "fGroupParentId", "fGroupPosition", "fGroupSize", "fGroupRotate", "fConnectOnNode", "fMinimapClass", "fGroupDraggingDisabled", "fGroupSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fGroupPositionChange", "fGroupSizeChange", "fGroupRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i1$2.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i1$2.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i1$2.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fConnectionWaypointsTrigger", "fMoveControlPointTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fNodeIntersectedWithConnections", "fNodeConnectionsIntersection", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fConnectionWaypointsChanged", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "component", type: FlowNodeComponent, selector: "fp-flow-node", inputs: ["node", "connectedOutputKeys"], outputs: ["positionChange", "nodeClick", "quickAdd", "portPlusClick", "duplicate", "remove", "testStep", "openChild", "openDetails"] }, { kind: "component", type: CanvasControlsComponent, selector: "fp-canvas-controls", inputs: ["zoom", "minimapVisible"], outputs: ["zoomIn", "zoomOut", "fitView", "resetView", "toggleMinimap", "autoLayout"] }, { kind: "component", type: CanvasNoteComponent, selector: "fp-canvas-note", inputs: ["note", "selected", "editing", "colors"], outputs: ["contentChange", "colorChange", "duplicate", "remove", "editStart", "editEnd"] }, { kind: "component", type: StarterCardComponent, selector: "fp-starter-card", outputs: ["addTrigger", "directPick"] }, { kind: "component", type: TriggerNodeComponent, selector: "fp-trigger-node", inputs: ["trigger", "noFirstStep"], outputs: ["addFirstStep", "configure", "execute", "toggleEnabled", "remove", "positionChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
20259
20860
|
}
|
|
20260
20861
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FlowCanvasComponent, decorators: [{
|
|
20261
20862
|
type: Component,
|
|
@@ -20267,6 +20868,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20267
20868
|
Tooltip,
|
|
20268
20869
|
FlowNodeComponent,
|
|
20269
20870
|
CanvasControlsComponent,
|
|
20871
|
+
CanvasNoteComponent,
|
|
20270
20872
|
StarterCardComponent,
|
|
20271
20873
|
TriggerNodeComponent,
|
|
20272
20874
|
], providers: [
|
|
@@ -20277,7 +20879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20277
20879
|
maxCascadeDepth: 8,
|
|
20278
20880
|
maxAbsoluteShiftPerPlan: 10000,
|
|
20279
20881
|
})),
|
|
20280
|
-
], template: "<f-flow\n #flow\n fDraggable\n [vCellSize]=\"gridCellSize\"\n [hCellSize]=\"gridCellSize\"\n [fCellSizeWhileDragging]=\"false\"\n (fFullRendered)=\"onFullRendered()\"\n (fNodesRendered)=\"onNodesRendered()\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fDragStarted)=\"onDragStarted($event)\"\n (fDragEnded)=\"onDragEnded()\"\n (fMoveNodes)=\"onMoveNodes($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n>\n <!-- Background dot grid \u2014 its spacing is locked to the drag cell size so\n nodes snap exactly onto the visible dots (Foblex grid-system). -->\n <f-background>\n <f-circle-pattern [radius]=\"gridCellSize\" />\n </f-background>\n\n <!-- Alignment guides + marquee selection are `f-flow` children (NOT\n `f-canvas` children \u2014 `f-canvas` only projects connections/nodes/groups,\n so helpers placed inside it are silently dropped). This mirrors the\n Foblex call-center reference layout. -->\n <f-line-alignment [fAlignThreshold]=\"20\" />\n <f-selection-area />\n\n <!-- Auto-pan: when dragging a node / connection near the viewport edge, the\n canvas pans to follow, so you can wire across off-screen nodes without\n letting go. (Foblex `f-auto-pan` plugin.) -->\n <f-auto-pan [fEdgeThreshold]=\"36\" [fSpeed]=\"8\" />\n\n <f-canvas\n #canvas\n fZoom\n [debounceTime]=\"200\"\n (fCanvasChange)=\"onCanvasChange($event)\"\n >\n <!-- Floating behavior anchors the preview at the connector boundary along\n the center\u2192pointer axis, so a connection dragged from the \"+\" outlet\n leaves it cleanly (NOT from its bottom edge \u2014 `fixed` defaults an AUTO\n connectable side to bottom) and snaps to the target's nearest edge. -->\n <f-connection-for-create\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-connection-for-create>\n\n <!-- Auto-snap: while dragging a new/reassigned connection, snap to the\n nearest connector within the threshold (forgiving connect UX). -->\n <f-snap-connection\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fSnapThreshold]=\"40\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-snap-connection>\n\n <!-- ngProjectAs is REQUIRED: `f-canvas` distributes projected content\n into its layer containers via selective `<ng-content select=\"...\">`\n with NO catch-all slot. A wrapper component (`fp-flow-node`, etc.)\n does not match `[fNode]` / `f-connection` on its host, so without\n `ngProjectAs` Foblex silently drops it and the canvas renders empty.\n The actual Foblex directive lives on the wrapper's inner element and\n self-registers via the mediator, so routing the wrapper into the\n right layer is all that's needed. -->\n @for (lane of branchLanes(); track lane.id) {\n <div\n ngProjectAs=\"[fGroup]\"\n class=\"pointer-events-none absolute z-0 rounded-[14px] border border-dashed border-[color-mix(in_srgb,rgb(var(--fp-parallel))_55%,transparent)] bg-[color-mix(in_srgb,rgb(var(--fp-parallel))_8%,transparent)]\"\n [attr.data-color-token]=\"lane.colorToken\"\n [style.left.px]=\"lane.x\"\n [style.top.px]=\"lane.y\"\n [style.width.px]=\"lane.width\"\n [style.height.px]=\"lane.height\"\n >\n <span\n class=\"pointer-events-auto absolute -top-2.5 start-3 rounded-full border border-[color-mix(in_srgb,rgb(var(--fp-parallel))_40%,transparent)] bg-(--p-content-background) px-2 py-px text-[10.5px] font-semibold text-[rgb(var(--fp-parallel))]\"\n >{{ lane.label }}</span\n >\n </div>\n }\n\n <!-- Connections are inlined here (NOT wrapped in a component) so each\n <f-connection> is a DIRECT child of Foblex's connections container.\n A wrapper would make `hostElement.parentElement` the wrapper instead\n of the container, which makes Foblex's select layer-raise throw\n \"Unknown container\" the moment an edge is selected. Same call-center\n pattern used for nodes/triggers. -->\n @for (edge of edges(); track edge.id) {\n <f-connection\n class=\"group\"\n [attr.data-fp-edge]=\"edge.connectionId\"\n [fConnectionId]=\"edge.id\"\n [fOutputId]=\"edge.sourcePortId\"\n [fInputId]=\"edge.targetPortId\"\n [fBehavior]=\"'fixed'\"\n [fType]=\"'adaptive-curve'\"\n [fOffset]=\"32\"\n fInputSide=\"calculate\"\n [fReassignableStart]=\"edge.edgeKind !== 'triggerStart'\"\n [fReassignDisabled]=\"edge.edgeKind === 'triggerStart'\"\n [class.fp-edge]=\"true\"\n [class.is-trigger-start]=\"edge.edgeKind === 'triggerStart'\"\n [class.is-drop-target]=\"isDropTargetEdge(edge.connectionId)\"\n [class.is-selected]=\"isConnectionSelected(edge.connectionId)\"\n [class.is-error]=\"edge.isInvalid\"\n [class.is-formula]=\"edge.isFormula\"\n [class.is-runtime-active]=\"edge.runtimeState === 'active'\"\n [class.is-runtime-completed]=\"edge.runtimeState === 'completed'\"\n [class.is-runtime-failed]=\"edge.runtimeState === 'failed'\"\n [class.is-runtime-waiting]=\"edge.runtimeState === 'waiting'\"\n (dblclick)=\"\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n >\n <!-- Arrow marker at the target \u2014 the connection carries the arrowhead;\n the input lives on the node host (no separate input element). -->\n <f-connection-marker-arrow [type]=\"markerEnd\" />\n\n <!-- Editable waypoints are intentionally NOT rendered: there is no\n backend persistence wired for manual bends, so exposing draggable\n waypoints would silently lose the user's edits on reload. -->\n\n <!-- Label / formula badge \u2014 pinned to the CENTER of the line\n (connection-content position 0.5). Fades out on hover/selected so\n the centered action box can take its place. -->\n @if (edge.label) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-[rgb(var(--fp-connector))] bg-(--p-content-background) py-1 pe-2.5 ps-2 text-[11px] font-semibold text-(--p-text-color) shadow-[0_1px_3px_rgba(15,23,42,0.1)] transition-colors group-[.is-selected]:border-(--p-primary-color) group-[.is-selected]:text-(--p-primary-color)\"\n >\n <span\n class=\"size-1.5 flex-none rounded-full bg-[rgb(var(--fp-connector))] group-[.is-selected]:bg-(--p-primary-color)\"\n ></span>\n {{ edge.label }}\n </span>\n </div>\n } @else if (edge.isFormula) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"grid h-5 w-5 place-items-center rounded-full border border-(--p-content-border-color) bg-(--p-content-background) font-mono text-[12px] italic text-(--p-primary-color) shadow-sm\"\n title=\"Conditional route\"\n >\u0192</span\n >\n </div>\n }\n\n <!-- Centered action box \u2014 edit (opens the connection MODAL) + delete.\n Same content anchor (position 0.5), revealed on hover/selected and\n overlapping the label so the actions stay centered ON the line. -->\n @if (edgeIssueCount(edge) > 0) {\n <div\n fConnectionContent\n [position]=\"0.38\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"fp-node-badge grid h-[18px] w-[18px] cursor-help place-items-center rounded-sm bg-(--p-content-background) shadow-sm outline-none transition-transform focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [style.color]=\"edgeIssueColor(edge)\"\n tabindex=\"0\"\n role=\"img\"\n [attr.aria-label]=\"edgeIssueTooltip(edge)\"\n [mtTooltip]=\"edgeIssueTooltip(edge)\"\n [tooltipStyleClass]=\"edgeIssueTooltipClass(edge)\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"\n $event.stopPropagation();\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M10 3.4 18 16.8 2 16.8 Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"2.6\"\n stroke-linejoin=\"round\"\n />\n <rect x=\"9.05\" y=\"8\" width=\"1.9\" height=\"4.6\" rx=\"0.95\" fill=\"#fff\" />\n <circle cx=\"10\" cy=\"14.6\" r=\"1.05\" fill=\"#fff\" />\n </svg>\n </span>\n </div>\n }\n\n @if (edge.runtimeState && edge.runtimeTooltip) {\n <div\n fConnectionContent\n [position]=\"0.62\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"inline-flex h-[18px] w-[18px] cursor-help items-center justify-center rounded-full border bg-(--p-content-background) shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [class.animate-pulse]=\"edge.runtimeState === 'active'\"\n [style.borderColor]=\"edgeRuntimeColor(edge)\"\n [style.color]=\"edgeRuntimeColor(edge)\"\n tabindex=\"0\"\n role=\"status\"\n [attr.aria-label]=\"edge.runtimeTooltip\"\n [mtTooltip]=\"edge.runtimeTooltip\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <mt-icon [icon]=\"edgeRuntimeIcon(edge)\" class=\"[&_svg]:size-3\" />\n </span>\n </div>\n }\n\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100 group-[.is-selected]:pointer-events-auto group-[.is-selected]:opacity-100\"\n >\n <div\n class=\"flex items-center gap-0.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background) p-1 shadow-md\"\n role=\"toolbar\"\n aria-label=\"Connection actions\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (edge.edgeKind === \"triggerStart\" && edge.triggerId != null) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.settings-01\"\n [tooltip]=\"'flowplus.trigger.node.configure' | transloco\"\n (onClick)=\"onTriggerOpenDetails({ triggerId: edge.triggerId })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.link-broken-01\"\n [tooltip]=\"'flowplus.trigger.node.unlink' | transloco\"\n (onClick)=\"\n onTriggerStartDisconnect({ triggerId: edge.triggerId })\n \"\n />\n } @else {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n [tooltip]=\"'flowplus.inspector.connection.title' | transloco\"\n (onClick)=\"\n onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n [tooltip]=\"'flowplus.edge.delete' | transloco\"\n (onClick)=\"onEdgeRemove({ connectionId: edge.connectionId })\"\n />\n }\n </div>\n </div>\n </f-connection>\n }\n\n <!-- The Foblex `fNode` directive lives on the component element itself\n (not an inner div). This keeps the node element a DIRECT child of\n Foblex's nodes container, so `hostElement.parentElement` IS that\n container \u2014 required by the select/move layer-raise (otherwise it\n throws \"Unknown container\"). This is the Foblex call-center pattern;\n the `fNode` attribute also routes it into the `[fNode]` projection\n slot, so `ngProjectAs` is not needed. -->\n @for (node of nodes(); track node.id) {\n <fp-flow-node\n fNode\n fDragHandle\n fNodeInput\n [attr.data-fp-node]=\"node.stepId\"\n [fInputId]=\"node.inputs[0]?.id\"\n [fInputMultiple]=\"node.inputs[0]?.allowMultiple ?? true\"\n [fInputDisabled]=\"!node.inputs.length\"\n [fNodeId]=\"node.id\"\n [fNodePosition]=\"{ x: node.x, y: node.y }\"\n (fNodePositionChange)=\"onStepPositionChange(node.stepId, $event)\"\n [node]=\"node\"\n [connectedOutputKeys]=\"connectedOutputKeys(node.stepId)\"\n (quickAdd)=\"onNodeQuickAdd($event)\"\n (portPlusClick)=\"onNodePortPlus($event)\"\n (duplicate)=\"onNodeDuplicate($event)\"\n (remove)=\"onNodeRemove($event)\"\n (openDetails)=\"onNodeOpenDetails($event)\"\n (openChild)=\"onOpenChild($event)\"\n />\n }\n\n @for (t of triggerNodes(); track t.triggerId) {\n <fp-trigger-node\n fNode\n fDragHandle\n [attr.data-fp-trigger]=\"t.triggerId\"\n [fNodeId]=\"'trigger:' + t.triggerId\"\n [fNodePosition]=\"{ x: t.x, y: t.y }\"\n (fNodePositionChange)=\"onTriggerPositionChange(t.triggerId, $event)\"\n [trigger]=\"t\"\n [noFirstStep]=\"!t.startStepId\"\n (addFirstStep)=\"onTriggerAddFirstStep($event)\"\n (configure)=\"onTriggerOpenDetails($event)\"\n (execute)=\"onTriggerExecute($event)\"\n (toggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (remove)=\"onTriggerDelete($event)\"\n />\n }\n </f-canvas>\n\n <!-- Minimap \u2014 `f-flow` child (NOT inside `f-canvas`). Toggled from the\n canvas controls; `fMinSize` keeps a couple of nodes zoomed-out enough\n to give real spatial context. -->\n @if (minimapVisible()) {\n <f-minimap [fMinSize]=\"minimapMinSize\" />\n }\n\n @if (showStarter() && !store.loading()) {\n <fp-starter-card\n (addTrigger)=\"onStarterAddTrigger($event)\"\n (directPick)=\"onStarterDirectPick($event)\"\n />\n }\n\n <fp-canvas-controls\n [zoom]=\"zoom()\"\n [minimapVisible]=\"minimapVisible()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (fitView)=\"fitView()\"\n (resetView)=\"resetView()\"\n (toggleMinimap)=\"toggleMinimap()\"\n (autoLayout)=\"autoLayout()\"\n />\n</f-flow>\n" }]
|
|
20882
|
+
], template: "<f-flow\n #flow\n fDraggable\n [vCellSize]=\"gridCellSize\"\n [hCellSize]=\"gridCellSize\"\n [fCellSizeWhileDragging]=\"false\"\n (fFullRendered)=\"onFullRendered()\"\n (fNodesRendered)=\"onNodesRendered()\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fDragStarted)=\"onDragStarted($event)\"\n (fDragEnded)=\"onDragEnded()\"\n (fMoveNodes)=\"onMoveNodes($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n>\n <!-- Background dot grid \u2014 its spacing is locked to the drag cell size so\n nodes snap exactly onto the visible dots (Foblex grid-system). -->\n <f-background>\n <f-circle-pattern [radius]=\"gridCellSize\" />\n </f-background>\n\n <!-- Alignment guides + marquee selection are `f-flow` children (NOT\n `f-canvas` children \u2014 `f-canvas` only projects connections/nodes/groups,\n so helpers placed inside it are silently dropped). This mirrors the\n Foblex call-center reference layout. -->\n <f-line-alignment [fAlignThreshold]=\"20\" />\n <f-selection-area />\n\n <!-- Auto-pan: when dragging a node / connection near the viewport edge, the\n canvas pans to follow, so you can wire across off-screen nodes without\n letting go. (Foblex `f-auto-pan` plugin.) -->\n <f-auto-pan [fEdgeThreshold]=\"36\" [fSpeed]=\"8\" />\n\n <f-canvas\n #canvas\n fZoom\n [debounceTime]=\"200\"\n [fLayers]=\"canvasLayers\"\n (fCanvasChange)=\"onCanvasChange($event)\"\n >\n <!-- Floating behavior anchors the preview at the connector boundary along\n the center\u2192pointer axis, so a connection dragged from the \"+\" outlet\n leaves it cleanly (NOT from its bottom edge \u2014 `fixed` defaults an AUTO\n connectable side to bottom) and snaps to the target's nearest edge. -->\n <f-connection-for-create\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-connection-for-create>\n\n <!-- Auto-snap: while dragging a new/reassigned connection, snap to the\n nearest connector within the threshold (forgiving connect UX). -->\n <f-snap-connection\n [fBehavior]=\"'floating'\"\n fType=\"adaptive-curve\"\n [fSnapThreshold]=\"40\"\n [fOffset]=\"0\"\n >\n <f-connection-marker-arrow />\n </f-snap-connection>\n\n <!-- ngProjectAs is REQUIRED: `f-canvas` distributes projected content\n into its layer containers via selective `<ng-content select=\"...\">`\n with NO catch-all slot. A wrapper component (`fp-flow-node`, etc.)\n does not match `[fNode]` / `f-connection` on its host, so without\n `ngProjectAs` Foblex silently drops it and the canvas renders empty.\n The actual Foblex directive lives on the wrapper's inner element and\n self-registers via the mediator, so routing the wrapper into the\n right layer is all that's needed. -->\n @for (note of canvasNotes(); track note.id) {\n <fp-canvas-note\n fGroup\n fDragHandle\n [attr.data-fp-note]=\"note.id\"\n [fGroupId]=\"canvasNoteGroupId(note.id)\"\n [fGroupPosition]=\"{ x: note.x, y: note.y }\"\n [fGroupSize]=\"{ width: note.width, height: note.height }\"\n [fGroupDraggingDisabled]=\"editingNoteId() === note.id\"\n [note]=\"note\"\n [selected]=\"selectedCanvasNoteIds().includes(note.id)\"\n [editing]=\"editingNoteId() === note.id\"\n (fGroupPositionChange)=\"onNotePositionChange(note.id, $event)\"\n (fGroupSizeChange)=\"onNoteSizeChange(note.id, $event)\"\n (contentChange)=\"onNoteContentChange($event)\"\n (colorChange)=\"onNoteColorChange($event)\"\n (duplicate)=\"onNoteDuplicate($event)\"\n (remove)=\"onNoteDelete($event)\"\n (editStart)=\"onNoteEditStart($event.noteId)\"\n (editEnd)=\"editingNoteId.set(null)\"\n />\n }\n\n @for (lane of branchLanes(); track lane.id) {\n <div\n ngProjectAs=\"[fGroup]\"\n class=\"pointer-events-none absolute z-0 rounded-[14px] border border-dashed border-[color-mix(in_srgb,rgb(var(--fp-parallel))_55%,transparent)] bg-[color-mix(in_srgb,rgb(var(--fp-parallel))_8%,transparent)]\"\n [attr.data-color-token]=\"lane.colorToken\"\n [style.left.px]=\"lane.x\"\n [style.top.px]=\"lane.y\"\n [style.width.px]=\"lane.width\"\n [style.height.px]=\"lane.height\"\n >\n <span\n class=\"pointer-events-auto absolute -top-2.5 start-3 rounded-full border border-[color-mix(in_srgb,rgb(var(--fp-parallel))_40%,transparent)] bg-(--p-content-background) px-2 py-px text-[10.5px] font-semibold text-[rgb(var(--fp-parallel))]\"\n >{{ lane.label }}</span\n >\n </div>\n }\n\n <!-- Connections are inlined here (NOT wrapped in a component) so each\n <f-connection> is a DIRECT child of Foblex's connections container.\n A wrapper would make `hostElement.parentElement` the wrapper instead\n of the container, which makes Foblex's select layer-raise throw\n \"Unknown container\" the moment an edge is selected. Same call-center\n pattern used for nodes/triggers. -->\n @for (edge of edges(); track edge.id) {\n <f-connection\n class=\"group\"\n [attr.data-fp-edge]=\"edge.connectionId\"\n [fConnectionId]=\"edge.id\"\n [fOutputId]=\"edge.sourcePortId\"\n [fInputId]=\"edge.targetPortId\"\n [fBehavior]=\"'fixed'\"\n [fType]=\"'adaptive-curve'\"\n [fOffset]=\"32\"\n fInputSide=\"calculate\"\n [fReassignableStart]=\"edge.edgeKind !== 'triggerStart'\"\n [fReassignDisabled]=\"edge.edgeKind === 'triggerStart'\"\n [class.fp-edge]=\"true\"\n [class.is-trigger-start]=\"edge.edgeKind === 'triggerStart'\"\n [class.is-drop-target]=\"isDropTargetEdge(edge.connectionId)\"\n [class.is-selected]=\"isConnectionSelected(edge.connectionId)\"\n [class.is-error]=\"edge.isInvalid\"\n [class.is-formula]=\"edge.isFormula\"\n [class.is-runtime-active]=\"edge.runtimeState === 'active'\"\n [class.is-runtime-completed]=\"edge.runtimeState === 'completed'\"\n [class.is-runtime-failed]=\"edge.runtimeState === 'failed'\"\n [class.is-runtime-waiting]=\"edge.runtimeState === 'waiting'\"\n (dblclick)=\"\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n >\n <!-- Arrow marker at the target \u2014 the connection carries the arrowhead;\n the input lives on the node host (no separate input element). -->\n <f-connection-marker-arrow [type]=\"markerEnd\" />\n\n <!-- Editable waypoints are intentionally NOT rendered: there is no\n backend persistence wired for manual bends, so exposing draggable\n waypoints would silently lose the user's edits on reload. -->\n\n <!-- Label / formula badge \u2014 pinned to the CENTER of the line\n (connection-content position 0.5). Fades out on hover/selected so\n the centered action box can take its place. -->\n @if (edge.label) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-[rgb(var(--fp-connector))] bg-(--p-content-background) py-1 pe-2.5 ps-2 text-[11px] font-semibold text-(--p-text-color) shadow-[0_1px_3px_rgba(15,23,42,0.1)] transition-colors group-[.is-selected]:border-(--p-primary-color) group-[.is-selected]:text-(--p-primary-color)\"\n >\n <span\n class=\"size-1.5 flex-none rounded-full bg-[rgb(var(--fp-connector))] group-[.is-selected]:bg-(--p-primary-color)\"\n ></span>\n {{ edge.label }}\n </span>\n </div>\n } @else if (edge.isFormula) {\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-100 transition-opacity duration-150 group-hover:opacity-0 group-[.is-selected]:opacity-0\"\n >\n <span\n class=\"grid h-5 w-5 place-items-center rounded-full border border-(--p-content-border-color) bg-(--p-content-background) font-mono text-[12px] italic text-(--p-primary-color) shadow-sm\"\n title=\"Conditional route\"\n >\u0192</span\n >\n </div>\n }\n\n <!-- Centered action box \u2014 edit (opens the connection MODAL) + delete.\n Same content anchor (position 0.5), revealed on hover/selected and\n overlapping the label so the actions stay centered ON the line. -->\n @if (edgeIssueCount(edge) > 0) {\n <div\n fConnectionContent\n [position]=\"0.38\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"fp-node-badge grid h-[18px] w-[18px] cursor-help place-items-center rounded-sm bg-(--p-content-background) shadow-sm outline-none transition-transform focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [style.color]=\"edgeIssueColor(edge)\"\n tabindex=\"0\"\n role=\"img\"\n [attr.aria-label]=\"edgeIssueTooltip(edge)\"\n [mtTooltip]=\"edgeIssueTooltip(edge)\"\n [tooltipStyleClass]=\"edgeIssueTooltipClass(edge)\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"\n $event.stopPropagation();\n edge.edgeKind === 'triggerStart' && edge.triggerId != null\n ? onTriggerOpenDetails({ triggerId: edge.triggerId })\n : onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M10 3.4 18 16.8 2 16.8 Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"2.6\"\n stroke-linejoin=\"round\"\n />\n <rect x=\"9.05\" y=\"8\" width=\"1.9\" height=\"4.6\" rx=\"0.95\" fill=\"#fff\" />\n <circle cx=\"10\" cy=\"14.6\" r=\"1.05\" fill=\"#fff\" />\n </svg>\n </span>\n </div>\n }\n\n @if (edge.runtimeState && edge.runtimeTooltip) {\n <div\n fConnectionContent\n [position]=\"0.62\"\n class=\"pointer-events-auto\"\n >\n <span\n class=\"inline-flex h-[18px] w-[18px] cursor-help items-center justify-center rounded-full border bg-(--p-content-background) shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-(--p-primary-color)\"\n [class.animate-pulse]=\"edge.runtimeState === 'active'\"\n [style.borderColor]=\"edgeRuntimeColor(edge)\"\n [style.color]=\"edgeRuntimeColor(edge)\"\n tabindex=\"0\"\n role=\"status\"\n [attr.aria-label]=\"edge.runtimeTooltip\"\n [mtTooltip]=\"edge.runtimeTooltip\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [escape]=\"true\"\n [showDelay]=\"180\"\n [hideDelay]=\"80\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n >\n <mt-icon [icon]=\"edgeRuntimeIcon(edge)\" class=\"[&_svg]:size-3\" />\n </span>\n </div>\n }\n\n <div\n fConnectionContent\n [position]=\"0.5\"\n class=\"pointer-events-none opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100 group-[.is-selected]:pointer-events-auto group-[.is-selected]:opacity-100\"\n >\n <div\n class=\"flex items-center gap-0.5 rounded-lg border border-(--p-content-border-color) bg-(--p-content-background) p-1 shadow-md\"\n role=\"toolbar\"\n aria-label=\"Connection actions\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (edge.edgeKind === \"triggerStart\" && edge.triggerId != null) {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.settings-01\"\n [tooltip]=\"'flowplus.trigger.node.configure' | transloco\"\n (onClick)=\"onTriggerOpenDetails({ triggerId: edge.triggerId })\"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.link-broken-01\"\n [tooltip]=\"'flowplus.trigger.node.unlink' | transloco\"\n (onClick)=\"\n onTriggerStartDisconnect({ triggerId: edge.triggerId })\n \"\n />\n } @else {\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.edit-05\"\n [tooltip]=\"'flowplus.inspector.connection.title' | transloco\"\n (onClick)=\"\n onEdgeOpenDetails({ connectionId: edge.connectionId })\n \"\n />\n <mt-button\n variant=\"text\"\n severity=\"danger\"\n size=\"small\"\n icon=\"general.trash-01\"\n [tooltip]=\"'flowplus.edge.delete' | transloco\"\n (onClick)=\"onEdgeRemove({ connectionId: edge.connectionId })\"\n />\n }\n </div>\n </div>\n </f-connection>\n }\n\n <!-- The Foblex `fNode` directive lives on the component element itself\n (not an inner div). This keeps the node element a DIRECT child of\n Foblex's nodes container, so `hostElement.parentElement` IS that\n container \u2014 required by the select/move layer-raise (otherwise it\n throws \"Unknown container\"). This is the Foblex call-center pattern;\n the `fNode` attribute also routes it into the `[fNode]` projection\n slot, so `ngProjectAs` is not needed. -->\n @for (node of nodes(); track node.id) {\n <fp-flow-node\n fNode\n fDragHandle\n fNodeInput\n [attr.data-fp-node]=\"node.stepId\"\n [fInputId]=\"node.inputs[0]?.id\"\n [fInputMultiple]=\"node.inputs[0]?.allowMultiple ?? true\"\n [fInputDisabled]=\"!node.inputs.length\"\n [fNodeId]=\"node.id\"\n [fNodePosition]=\"{ x: node.x, y: node.y }\"\n (fNodePositionChange)=\"onStepPositionChange(node.stepId, $event)\"\n [node]=\"node\"\n [connectedOutputKeys]=\"connectedOutputKeys(node.stepId)\"\n (quickAdd)=\"onNodeQuickAdd($event)\"\n (portPlusClick)=\"onNodePortPlus($event)\"\n (duplicate)=\"onNodeDuplicate($event)\"\n (remove)=\"onNodeRemove($event)\"\n (openDetails)=\"onNodeOpenDetails($event)\"\n (openChild)=\"onOpenChild($event)\"\n />\n }\n\n @for (t of triggerNodes(); track t.triggerId) {\n <fp-trigger-node\n fNode\n fDragHandle\n [attr.data-fp-trigger]=\"t.triggerId\"\n [fNodeId]=\"'trigger:' + t.triggerId\"\n [fNodePosition]=\"{ x: t.x, y: t.y }\"\n (fNodePositionChange)=\"onTriggerPositionChange(t.triggerId, $event)\"\n [trigger]=\"t\"\n [noFirstStep]=\"!t.startStepId\"\n (addFirstStep)=\"onTriggerAddFirstStep($event)\"\n (configure)=\"onTriggerOpenDetails($event)\"\n (execute)=\"onTriggerExecute($event)\"\n (toggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (remove)=\"onTriggerDelete($event)\"\n />\n }\n </f-canvas>\n\n <!-- Minimap \u2014 `f-flow` child (NOT inside `f-canvas`). Toggled from the\n canvas controls; `fMinSize` keeps a couple of nodes zoomed-out enough\n to give real spatial context. -->\n @if (minimapVisible()) {\n <f-minimap [fMinSize]=\"minimapMinSize\" />\n }\n\n @if (showStarter() && !store.loading()) {\n <fp-starter-card\n (addTrigger)=\"onStarterAddTrigger($event)\"\n (directPick)=\"onStarterDirectPick($event)\"\n />\n }\n\n <fp-canvas-controls\n [zoom]=\"zoom()\"\n [minimapVisible]=\"minimapVisible()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (fitView)=\"fitView()\"\n (resetView)=\"resetView()\"\n (toggleMinimap)=\"toggleMinimap()\"\n (autoLayout)=\"autoLayout()\"\n />\n</f-flow>\n" }]
|
|
20281
20883
|
}], ctorParameters: () => [], propDecorators: { flow: [{ type: i0.ViewChild, args: ['flow', { isSignal: true }] }], canvas: [{ type: i0.ViewChild, args: ['canvas', { isSignal: true }] }], paletteDrop: [{
|
|
20282
20884
|
type: Output
|
|
20283
20885
|
}], connectionCreate: [{
|
|
@@ -20334,6 +20936,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20334
20936
|
type: Output
|
|
20335
20937
|
}], requestAddStep: [{
|
|
20336
20938
|
type: Output
|
|
20939
|
+
}], noteUpdate: [{
|
|
20940
|
+
type: Output
|
|
20941
|
+
}], noteDuplicate: [{
|
|
20942
|
+
type: Output
|
|
20943
|
+
}], noteDelete: [{
|
|
20944
|
+
type: Output
|
|
20337
20945
|
}] } });
|
|
20338
20946
|
function triggerStarterKindMatchesCatalogItem(kind, item) {
|
|
20339
20947
|
const metadata = item.metadata && typeof item.metadata === 'object'
|
|
@@ -20359,7 +20967,8 @@ function readTranslatePosition(el) {
|
|
|
20359
20967
|
function isCanvasPositionElement(target) {
|
|
20360
20968
|
return (target instanceof HTMLElement &&
|
|
20361
20969
|
(target.matches('fp-flow-node[data-fp-node]') ||
|
|
20362
|
-
target.matches('fp-trigger-node[data-fp-trigger]')
|
|
20970
|
+
target.matches('fp-trigger-node[data-fp-trigger]') ||
|
|
20971
|
+
target.matches('fp-canvas-note[data-fp-note]')));
|
|
20363
20972
|
}
|
|
20364
20973
|
function normalizeOutputPortKey(portKey, fallback) {
|
|
20365
20974
|
const key = portKey || fallback;
|
|
@@ -20526,6 +21135,8 @@ class PaletteComponent {
|
|
|
20526
21135
|
add = new EventEmitter();
|
|
20527
21136
|
/** Add a trigger from the "Add another trigger" section. */
|
|
20528
21137
|
addTrigger = new EventEmitter();
|
|
21138
|
+
/** Add a sticky canvas note directly from the rail. */
|
|
21139
|
+
addNote = new EventEmitter();
|
|
20529
21140
|
searchModel = '';
|
|
20530
21141
|
/** Two-level navigation state. */
|
|
20531
21142
|
view = signal('root', ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
|
|
@@ -20624,6 +21235,9 @@ class PaletteComponent {
|
|
|
20624
21235
|
openTriggers() {
|
|
20625
21236
|
this.view.set('triggers');
|
|
20626
21237
|
}
|
|
21238
|
+
addCanvasNote() {
|
|
21239
|
+
this.addNote.emit();
|
|
21240
|
+
}
|
|
20627
21241
|
back() {
|
|
20628
21242
|
this.view.set('root');
|
|
20629
21243
|
this.activeCategory.set(null);
|
|
@@ -20729,7 +21343,7 @@ class PaletteComponent {
|
|
|
20729
21343
|
return v && v !== key ? v : fallback;
|
|
20730
21344
|
}
|
|
20731
21345
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20732
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PaletteComponent, isStandalone: true, selector: "fp-palette", outputs: { closeRequested: "closeRequested", openRequested: "openRequested", add: "add", addTrigger: "addTrigger" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)" }, classAttribute: "block absolute top-0 bottom-0 start-0 w-11 z-[5] overflow-visible bg-(--p-surface-200) dark:bg-(--p-surface-800) border-e border-(--p-content-border-color)" }, ngImport: i0, template: "<div\r\n class=\"flex h-full w-11 flex-col items-center gap-2 bg-transparent py-3\"\r\n role=\"toolbar\"\r\n [attr.aria-label]=\"'flowplus.palette.rail' | transloco\"\r\n>\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"isExpanded() ? 'general.x-close' : 'general.plus'\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.toggle' | transloco\"\n [mtTooltip]=\"'flowplus.palette.toggle' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"isExpanded() ? closeDrawer() : openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.search-md\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.search' | transloco\"\n [mtTooltip]=\"'flowplus.palette.search' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"openDrawer()\"\n />\n</div>\r\n\r\n@if (isExpanded()) {\r\n <aside\r\n class=\"absolute start-11 top-0 bottom-10 z-[6] flex w-80 min-h-0 flex-col overflow-hidden border-e border-(--p-content-border-color) bg-(--p-surface-50) shadow-lg animate-[fp-palette-slide-in_280ms_cubic-bezier(0,0,0.2,1)_both] rtl:animate-[fp-palette-slide-in-rtl_280ms_cubic-bezier(0,0,0.2,1)_both]\"\r\n role=\"complementary\"\r\n [attr.aria-label]=\"'flowplus.palette.title' | transloco\"\r\n >\r\n <header class=\"flex flex-col gap-2.5 px-3 pt-3 pb-2.5\">\r\n <div class=\"flex items-center gap-2\">\r\n @if (!searching() && view() !== \"root\") {\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"arrow.chevron-left\"\n styleClass=\"fp-palette-back-button\"\n (onClick)=\"back()\"\n [attr.aria-label]=\"'flowplus.palette.back' | transloco\"\n [mtTooltip]=\"'flowplus.palette.back' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n />\n }\r\n <h3\r\n class=\"min-w-0 flex-1 truncate text-[13.5px] font-bold text-(--p-text-color)\"\r\n >\r\n {{ headerTitle() }}\r\n </h3>\r\n </div>\r\n\r\n <mt-text-field\r\n [(ngModel)]=\"searchModel\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n [placeholder]=\"'flowplus.palette.search' | transloco\"\r\n icon=\"general.search-md\"\r\n />\r\n </header>\r\n\r\n <div\r\n class=\"fp-scroll fp-pal-list flex flex-1 flex-col gap-0.5 overflow-y-auto px-2.5 pt-1 pb-6\"\r\n role=\"list\"\r\n >\r\n @if (searching() && view() !== \"triggers\") {\n @for (item of searchResults(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n @if (searchResults().length === 0) {\r\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\r\n }\r\n } @else if (view() === \"triggers\") {\n @for (option of visibleTriggerOptions(); track option.key) {\n <div\n fExternalItem\n [fData]=\"triggerPaletteItem(option)\"\n [fExternalItemId]=\"triggerPaletteItemKey(option, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\n tabindex=\"0\"\n [attr.title]=\"\n resolve(option.description) || resolve(option.displayName)\n \"\n (click)=\"pickTrigger(option)\"\n (keydown.enter)=\"pickTrigger(option)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n triggerDragPreview;\n context: { $implicit: option }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n [style.--fp-avatar-color]=\"triggerOptionVars(option).color\"\n [style.--fp-avatar-bg]=\"triggerOptionVars(option).bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ resolve(option.displayName) }}</span\r\n >\r\n @if (option.description) {\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ resolve(option.description) }}</span\r\n >\n }\n </span>\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\n icon=\"general.dots-grid\"\n />\n </div>\n }\n @if (visibleTriggerOptions().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n }\n } @else if (view() === \"category\") {\n @for (item of activeItems(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groups(); track group.category) {\r\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openCategory(group.category)\"\n (keydown.enter)=\"openCategory(group.category)\"\n (keydown.space)=\"$event.preventDefault(); openCategory(group.category)\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n [icon]=\"group.icon\"\r\n [style.--fp-avatar-color]=\"group.color\"\r\n [style.--fp-avatar-bg]=\"group.bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ group.label }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ group.description }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n\n @if (groups().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n } @else {\n <div class=\"mx-2.5 my-1.5 h-px bg-(--p-content-border-color)\"></div>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openTriggers()\"\n (keydown.enter)=\"openTriggers()\"\n (keydown.space)=\"$event.preventDefault(); openTriggers()\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n icon=\"general.zap-fast\"\r\n [style.--fp-avatar-color]=\"triggerVars().color\"\r\n [style.--fp-avatar-bg]=\"triggerVars().bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ \"flowplus.palette.addAnotherTrigger\" | transloco }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{\r\n \"flowplus.palette.addAnotherTriggerDesc\" | transloco\r\n }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n }\r\n </div>\r\n </aside>\r\n}\r\n\r\n<ng-template #emptyRow>\r\n <div\r\n class=\"flex flex-col items-center justify-center px-6 py-8 text-center text-(--p-text-muted-color)\"\r\n >\r\n <p>{{ \"flowplus.common.empty\" | transloco }}</p>\r\n </div>\n</ng-template>\n\n<ng-template #stepDragPreview let-item>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,var(--fp-avatar-color)_28%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(15,23,42,0.18),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[var(--fp-avatar-bg)] text-[var(--fp-avatar-color)] shadow-inner ring-1 ring-[color-mix(in_srgb,var(--fp-avatar-color)_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar size=\"normal\" shape=\"square\" [icon]=\"iconFor(item)\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(item.displayName) }}\n </span>\n @if (item.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(item.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,var(--fp-avatar-color)_7%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n {{ item.category || item.type }}\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[var(--fp-avatar-color)] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n\n<ng-template #triggerDragPreview let-option>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,rgb(var(--fp-app-action))_30%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(245,158,11,0.20),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_16%,transparent)] text-[rgb(var(--fp-app-action))] shadow-inner ring-1 ring-[color-mix(in_srgb,rgb(var(--fp-app-action))_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar\n size=\"normal\"\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(option.displayName) }}\n </span>\n @if (option.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(option.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_8%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n Trigger\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[rgb(var(--fp-app-action))] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "directive", type:
|
|
21346
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PaletteComponent, isStandalone: true, selector: "fp-palette", outputs: { closeRequested: "closeRequested", openRequested: "openRequested", add: "add", addTrigger: "addTrigger", addNote: "addNote" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)" }, classAttribute: "block absolute top-0 bottom-0 start-0 w-11 z-[5] overflow-visible bg-(--p-surface-200) dark:bg-(--p-surface-800) border-e border-(--p-content-border-color)" }, ngImport: i0, template: "<div\r\n class=\"flex h-full w-11 flex-col items-center gap-2 bg-transparent py-3\"\r\n role=\"toolbar\"\r\n [attr.aria-label]=\"'flowplus.palette.rail' | transloco\"\r\n>\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"isExpanded() ? 'general.x-close' : 'general.plus'\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.toggle' | transloco\"\n [mtTooltip]=\"'flowplus.palette.toggle' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"isExpanded() ? closeDrawer() : openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.search-md\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.search' | transloco\"\n [mtTooltip]=\"'flowplus.palette.search' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"communication.annotation-plus\"\n styleClass=\"fp-palette-rail-button\"\n [attr.aria-label]=\"'flowplus.canvas.addNote' | transloco\"\n [mtTooltip]=\"'flowplus.canvas.addNote' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"addCanvasNote()\"\n />\n</div>\n\r\n@if (isExpanded()) {\r\n <aside\r\n class=\"absolute start-11 top-0 bottom-10 z-[6] flex w-80 min-h-0 flex-col overflow-hidden border-e border-(--p-content-border-color) bg-(--p-surface-50) shadow-lg animate-[fp-palette-slide-in_280ms_cubic-bezier(0,0,0.2,1)_both] rtl:animate-[fp-palette-slide-in-rtl_280ms_cubic-bezier(0,0,0.2,1)_both]\"\r\n role=\"complementary\"\r\n [attr.aria-label]=\"'flowplus.palette.title' | transloco\"\r\n >\r\n <header class=\"flex flex-col gap-2.5 px-3 pt-3 pb-2.5\">\r\n <div class=\"flex items-center gap-2\">\r\n @if (!searching() && view() !== \"root\") {\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"arrow.chevron-left\"\n styleClass=\"fp-palette-back-button\"\n (onClick)=\"back()\"\n [attr.aria-label]=\"'flowplus.palette.back' | transloco\"\n [mtTooltip]=\"'flowplus.palette.back' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n />\n }\r\n <h3\r\n class=\"min-w-0 flex-1 truncate text-[13.5px] font-bold text-(--p-text-color)\"\r\n >\r\n {{ headerTitle() }}\r\n </h3>\r\n </div>\r\n\r\n <mt-text-field\r\n [(ngModel)]=\"searchModel\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n [placeholder]=\"'flowplus.palette.search' | transloco\"\r\n icon=\"general.search-md\"\r\n />\r\n </header>\r\n\r\n <div\r\n class=\"fp-scroll fp-pal-list flex flex-1 flex-col gap-0.5 overflow-y-auto px-2.5 pt-1 pb-6\"\r\n role=\"list\"\r\n >\r\n @if (searching() && view() !== \"triggers\") {\n @for (item of searchResults(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n @if (searchResults().length === 0) {\r\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\r\n }\r\n } @else if (view() === \"triggers\") {\n @for (option of visibleTriggerOptions(); track option.key) {\n <div\n fExternalItem\n [fData]=\"triggerPaletteItem(option)\"\n [fExternalItemId]=\"triggerPaletteItemKey(option, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\n tabindex=\"0\"\n [attr.title]=\"\n resolve(option.description) || resolve(option.displayName)\n \"\n (click)=\"pickTrigger(option)\"\n (keydown.enter)=\"pickTrigger(option)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n triggerDragPreview;\n context: { $implicit: option }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n [style.--fp-avatar-color]=\"triggerOptionVars(option).color\"\n [style.--fp-avatar-bg]=\"triggerOptionVars(option).bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ resolve(option.displayName) }}</span\r\n >\r\n @if (option.description) {\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ resolve(option.description) }}</span\r\n >\n }\n </span>\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\n icon=\"general.dots-grid\"\n />\n </div>\n }\n @if (visibleTriggerOptions().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n }\n } @else if (view() === \"category\") {\n @for (item of activeItems(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groups(); track group.category) {\r\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openCategory(group.category)\"\n (keydown.enter)=\"openCategory(group.category)\"\n (keydown.space)=\"$event.preventDefault(); openCategory(group.category)\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n [icon]=\"group.icon\"\r\n [style.--fp-avatar-color]=\"group.color\"\r\n [style.--fp-avatar-bg]=\"group.bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ group.label }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ group.description }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n\n @if (groups().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n } @else {\n <div class=\"mx-2.5 my-1.5 h-px bg-(--p-content-border-color)\"></div>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openTriggers()\"\n (keydown.enter)=\"openTriggers()\"\n (keydown.space)=\"$event.preventDefault(); openTriggers()\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n icon=\"general.zap-fast\"\r\n [style.--fp-avatar-color]=\"triggerVars().color\"\r\n [style.--fp-avatar-bg]=\"triggerVars().bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ \"flowplus.palette.addAnotherTrigger\" | transloco }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{\r\n \"flowplus.palette.addAnotherTriggerDesc\" | transloco\r\n }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n }\r\n </div>\r\n </aside>\r\n}\r\n\r\n<ng-template #emptyRow>\r\n <div\r\n class=\"flex flex-col items-center justify-center px-6 py-8 text-center text-(--p-text-muted-color)\"\r\n >\r\n <p>{{ \"flowplus.common.empty\" | transloco }}</p>\r\n </div>\n</ng-template>\n\n<ng-template #stepDragPreview let-item>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,var(--fp-avatar-color)_28%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(15,23,42,0.18),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[var(--fp-avatar-bg)] text-[var(--fp-avatar-color)] shadow-inner ring-1 ring-[color-mix(in_srgb,var(--fp-avatar-color)_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar size=\"normal\" shape=\"square\" [icon]=\"iconFor(item)\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(item.displayName) }}\n </span>\n @if (item.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(item.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,var(--fp-avatar-color)_7%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n {{ item.category || item.type }}\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[var(--fp-avatar-color)] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n\n<ng-template #triggerDragPreview let-option>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,rgb(var(--fp-app-action))_30%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(245,158,11,0.20),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_16%,transparent)] text-[rgb(var(--fp-app-action))] shadow-inner ring-1 ring-[color-mix(in_srgb,rgb(var(--fp-app-action))_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar\n size=\"normal\"\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(option.displayName) }}\n </span>\n @if (option.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(option.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_8%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n Trigger\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[rgb(var(--fp-app-action))] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "directive", type:
|
|
20733
21347
|
// Native Foblex external-item drag (clone preview, like the official
|
|
20734
21348
|
// add-node-from-palette example).
|
|
20735
21349
|
FExternalItem, selector: "[fExternalItem]", inputs: ["fExternalItemId", "fData", "fDisabled", "fPreview", "fPreviewMatchSize", "fPlaceholder"], outputs: ["fPreviewChange", "fPlaceholderChange"] }, { kind: "directive", type: FExternalItemPreview, selector: "ng-template[fExternalItemPreview]" }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
@@ -20751,7 +21365,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20751
21365
|
FExternalItemPreview,
|
|
20752
21366
|
], host: {
|
|
20753
21367
|
class: 'block absolute top-0 bottom-0 start-0 w-11 z-[5] overflow-visible bg-(--p-surface-200) dark:bg-(--p-surface-800) border-e border-(--p-content-border-color)',
|
|
20754
|
-
}, template: "<div\r\n class=\"flex h-full w-11 flex-col items-center gap-2 bg-transparent py-3\"\r\n role=\"toolbar\"\r\n [attr.aria-label]=\"'flowplus.palette.rail' | transloco\"\r\n>\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"isExpanded() ? 'general.x-close' : 'general.plus'\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.toggle' | transloco\"\n [mtTooltip]=\"'flowplus.palette.toggle' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"isExpanded() ? closeDrawer() : openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.search-md\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.search' | transloco\"\n [mtTooltip]=\"'flowplus.palette.search' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"openDrawer()\"\n />\n</div>\r\n\r\n@if (isExpanded()) {\r\n <aside\r\n class=\"absolute start-11 top-0 bottom-10 z-[6] flex w-80 min-h-0 flex-col overflow-hidden border-e border-(--p-content-border-color) bg-(--p-surface-50) shadow-lg animate-[fp-palette-slide-in_280ms_cubic-bezier(0,0,0.2,1)_both] rtl:animate-[fp-palette-slide-in-rtl_280ms_cubic-bezier(0,0,0.2,1)_both]\"\r\n role=\"complementary\"\r\n [attr.aria-label]=\"'flowplus.palette.title' | transloco\"\r\n >\r\n <header class=\"flex flex-col gap-2.5 px-3 pt-3 pb-2.5\">\r\n <div class=\"flex items-center gap-2\">\r\n @if (!searching() && view() !== \"root\") {\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"arrow.chevron-left\"\n styleClass=\"fp-palette-back-button\"\n (onClick)=\"back()\"\n [attr.aria-label]=\"'flowplus.palette.back' | transloco\"\n [mtTooltip]=\"'flowplus.palette.back' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n />\n }\r\n <h3\r\n class=\"min-w-0 flex-1 truncate text-[13.5px] font-bold text-(--p-text-color)\"\r\n >\r\n {{ headerTitle() }}\r\n </h3>\r\n </div>\r\n\r\n <mt-text-field\r\n [(ngModel)]=\"searchModel\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n [placeholder]=\"'flowplus.palette.search' | transloco\"\r\n icon=\"general.search-md\"\r\n />\r\n </header>\r\n\r\n <div\r\n class=\"fp-scroll fp-pal-list flex flex-1 flex-col gap-0.5 overflow-y-auto px-2.5 pt-1 pb-6\"\r\n role=\"list\"\r\n >\r\n @if (searching() && view() !== \"triggers\") {\n @for (item of searchResults(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n @if (searchResults().length === 0) {\r\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\r\n }\r\n } @else if (view() === \"triggers\") {\n @for (option of visibleTriggerOptions(); track option.key) {\n <div\n fExternalItem\n [fData]=\"triggerPaletteItem(option)\"\n [fExternalItemId]=\"triggerPaletteItemKey(option, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\n tabindex=\"0\"\n [attr.title]=\"\n resolve(option.description) || resolve(option.displayName)\n \"\n (click)=\"pickTrigger(option)\"\n (keydown.enter)=\"pickTrigger(option)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n triggerDragPreview;\n context: { $implicit: option }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n [style.--fp-avatar-color]=\"triggerOptionVars(option).color\"\n [style.--fp-avatar-bg]=\"triggerOptionVars(option).bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ resolve(option.displayName) }}</span\r\n >\r\n @if (option.description) {\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ resolve(option.description) }}</span\r\n >\n }\n </span>\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\n icon=\"general.dots-grid\"\n />\n </div>\n }\n @if (visibleTriggerOptions().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n }\n } @else if (view() === \"category\") {\n @for (item of activeItems(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groups(); track group.category) {\r\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openCategory(group.category)\"\n (keydown.enter)=\"openCategory(group.category)\"\n (keydown.space)=\"$event.preventDefault(); openCategory(group.category)\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n [icon]=\"group.icon\"\r\n [style.--fp-avatar-color]=\"group.color\"\r\n [style.--fp-avatar-bg]=\"group.bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ group.label }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ group.description }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n\n @if (groups().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n } @else {\n <div class=\"mx-2.5 my-1.5 h-px bg-(--p-content-border-color)\"></div>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openTriggers()\"\n (keydown.enter)=\"openTriggers()\"\n (keydown.space)=\"$event.preventDefault(); openTriggers()\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n icon=\"general.zap-fast\"\r\n [style.--fp-avatar-color]=\"triggerVars().color\"\r\n [style.--fp-avatar-bg]=\"triggerVars().bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ \"flowplus.palette.addAnotherTrigger\" | transloco }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{\r\n \"flowplus.palette.addAnotherTriggerDesc\" | transloco\r\n }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n }\r\n </div>\r\n </aside>\r\n}\r\n\r\n<ng-template #emptyRow>\r\n <div\r\n class=\"flex flex-col items-center justify-center px-6 py-8 text-center text-(--p-text-muted-color)\"\r\n >\r\n <p>{{ \"flowplus.common.empty\" | transloco }}</p>\r\n </div>\n</ng-template>\n\n<ng-template #stepDragPreview let-item>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,var(--fp-avatar-color)_28%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(15,23,42,0.18),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[var(--fp-avatar-bg)] text-[var(--fp-avatar-color)] shadow-inner ring-1 ring-[color-mix(in_srgb,var(--fp-avatar-color)_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar size=\"normal\" shape=\"square\" [icon]=\"iconFor(item)\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(item.displayName) }}\n </span>\n @if (item.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(item.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,var(--fp-avatar-color)_7%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n {{ item.category || item.type }}\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[var(--fp-avatar-color)] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n\n<ng-template #triggerDragPreview let-option>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,rgb(var(--fp-app-action))_30%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(245,158,11,0.20),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_16%,transparent)] text-[rgb(var(--fp-app-action))] shadow-inner ring-1 ring-[color-mix(in_srgb,rgb(var(--fp-app-action))_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar\n size=\"normal\"\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(option.displayName) }}\n </span>\n @if (option.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(option.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_8%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n Trigger\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[rgb(var(--fp-app-action))] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n" }]
|
|
21368
|
+
}, template: "<div\r\n class=\"flex h-full w-11 flex-col items-center gap-2 bg-transparent py-3\"\r\n role=\"toolbar\"\r\n [attr.aria-label]=\"'flowplus.palette.rail' | transloco\"\r\n>\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n [icon]=\"isExpanded() ? 'general.x-close' : 'general.plus'\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.toggle' | transloco\"\n [mtTooltip]=\"'flowplus.palette.toggle' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"isExpanded() ? closeDrawer() : openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"general.search-md\"\n [styleClass]=\"\n isExpanded()\n ? 'fp-palette-rail-button is-active'\n : 'fp-palette-rail-button'\n \"\n [attr.aria-label]=\"'flowplus.palette.search' | transloco\"\n [mtTooltip]=\"'flowplus.palette.search' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"openDrawer()\"\n />\n\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"communication.annotation-plus\"\n styleClass=\"fp-palette-rail-button\"\n [attr.aria-label]=\"'flowplus.canvas.addNote' | transloco\"\n [mtTooltip]=\"'flowplus.canvas.addNote' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n (onClick)=\"addCanvasNote()\"\n />\n</div>\n\r\n@if (isExpanded()) {\r\n <aside\r\n class=\"absolute start-11 top-0 bottom-10 z-[6] flex w-80 min-h-0 flex-col overflow-hidden border-e border-(--p-content-border-color) bg-(--p-surface-50) shadow-lg animate-[fp-palette-slide-in_280ms_cubic-bezier(0,0,0.2,1)_both] rtl:animate-[fp-palette-slide-in-rtl_280ms_cubic-bezier(0,0,0.2,1)_both]\"\r\n role=\"complementary\"\r\n [attr.aria-label]=\"'flowplus.palette.title' | transloco\"\r\n >\r\n <header class=\"flex flex-col gap-2.5 px-3 pt-3 pb-2.5\">\r\n <div class=\"flex items-center gap-2\">\r\n @if (!searching() && view() !== \"root\") {\r\n <mt-button\n variant=\"text\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"arrow.chevron-left\"\n styleClass=\"fp-palette-back-button\"\n (onClick)=\"back()\"\n [attr.aria-label]=\"'flowplus.palette.back' | transloco\"\n [mtTooltip]=\"'flowplus.palette.back' | transloco\"\n tooltipPosition=\"right\"\n appendTo=\"body\"\n [showDelay]=\"220\"\n [hideDelay]=\"80\"\n />\n }\r\n <h3\r\n class=\"min-w-0 flex-1 truncate text-[13.5px] font-bold text-(--p-text-color)\"\r\n >\r\n {{ headerTitle() }}\r\n </h3>\r\n </div>\r\n\r\n <mt-text-field\r\n [(ngModel)]=\"searchModel\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n [placeholder]=\"'flowplus.palette.search' | transloco\"\r\n icon=\"general.search-md\"\r\n />\r\n </header>\r\n\r\n <div\r\n class=\"fp-scroll fp-pal-list flex flex-1 flex-col gap-0.5 overflow-y-auto px-2.5 pt-1 pb-6\"\r\n role=\"list\"\r\n >\r\n @if (searching() && view() !== \"triggers\") {\n @for (item of searchResults(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n @if (searchResults().length === 0) {\r\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\r\n }\r\n } @else if (view() === \"triggers\") {\n @for (option of visibleTriggerOptions(); track option.key) {\n <div\n fExternalItem\n [fData]=\"triggerPaletteItem(option)\"\n [fExternalItemId]=\"triggerPaletteItemKey(option, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\n tabindex=\"0\"\n [attr.title]=\"\n resolve(option.description) || resolve(option.displayName)\n \"\n (click)=\"pickTrigger(option)\"\n (keydown.enter)=\"pickTrigger(option)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n triggerDragPreview;\n context: { $implicit: option }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n [style.--fp-avatar-color]=\"triggerOptionVars(option).color\"\n [style.--fp-avatar-bg]=\"triggerOptionVars(option).bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ resolve(option.displayName) }}</span\r\n >\r\n @if (option.description) {\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ resolve(option.description) }}</span\r\n >\n }\n </span>\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\n icon=\"general.dots-grid\"\n />\n </div>\n }\n @if (visibleTriggerOptions().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n }\n } @else if (view() === \"category\") {\n @for (item of activeItems(); track paletteItemKey(item, $index)) {\r\n <div\r\n fExternalItem\n [fData]=\"item\"\n [fExternalItemId]=\"paletteItemKey(item, $index)\"\n [fPreviewMatchSize]=\"false\"\n class=\"group/item !flex w-full cursor-grab touch-none select-none items-center gap-3 rounded-lg px-2.5 py-2.5 transition-colors hover:bg-(--p-surface-100) active:cursor-grabbing focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.title]=\"\r\n resolve(item.description) || resolve(item.displayName)\r\n \"\r\n (click)=\"pickStep(item)\"\n (keydown.enter)=\"pickStep(item)\"\n >\n <ng-template fExternalItemPreview>\n <ng-container\n *ngTemplateOutlet=\"\n stepDragPreview;\n context: { $implicit: item }\n \"\n />\n </ng-template>\n <mt-avatar\n shape=\"square\"\n [icon]=\"iconFor(item)\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\r\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\r\n />\r\n <div class=\"min-w-0 flex-1\">\r\n <div\r\n class=\"truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >\r\n {{ resolve(item.displayName) }}\r\n </div>\r\n @if (item.description) {\r\n <div\r\n class=\"line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >\r\n {{ resolve(item.description) }}\r\n </div>\r\n }\r\n </div>\r\n <mt-icon\r\n class=\"flex-none text-(--p-text-muted-color)/40 transition-colors group-hover/item:text-(--p-text-muted-color) [&_svg]:size-4\"\r\n icon=\"general.dots-grid\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groups(); track group.category) {\r\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openCategory(group.category)\"\n (keydown.enter)=\"openCategory(group.category)\"\n (keydown.space)=\"$event.preventDefault(); openCategory(group.category)\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n [icon]=\"group.icon\"\r\n [style.--fp-avatar-color]=\"group.color\"\r\n [style.--fp-avatar-bg]=\"group.bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ group.label }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{ group.description }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n\n @if (groups().length === 0) {\n <ng-container *ngTemplateOutlet=\"emptyRow\" />\n } @else {\n <div class=\"mx-2.5 my-1.5 h-px bg-(--p-content-border-color)\"></div>\n <div\n role=\"button\"\n tabindex=\"0\"\n class=\"flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2.5 text-start transition-colors hover:bg-(--p-surface-100) focus-visible:bg-(--p-surface-100) focus-visible:outline-none\"\n (click)=\"openTriggers()\"\n (keydown.enter)=\"openTriggers()\"\n (keydown.space)=\"$event.preventDefault(); openTriggers()\"\n >\n <mt-avatar\r\n shape=\"square\"\r\n icon=\"general.zap-fast\"\r\n [style.--fp-avatar-color]=\"triggerVars().color\"\r\n [style.--fp-avatar-bg]=\"triggerVars().bg\"\r\n />\r\n <span class=\"min-w-0 flex-1\">\r\n <span\r\n class=\"block truncate text-[13px] font-semibold text-(--p-text-color)\"\r\n >{{ \"flowplus.palette.addAnotherTrigger\" | transloco }}</span\r\n >\r\n <span\r\n class=\"block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\r\n >{{\r\n \"flowplus.palette.addAnotherTriggerDesc\" | transloco\r\n }}</span\r\n >\r\n </span>\r\n <mt-icon\n class=\"flex-none text-(--p-text-muted-color) [&_svg]:size-4 rtl:rotate-180\"\n icon=\"arrow.chevron-right\"\n />\n </div>\n }\n }\r\n </div>\r\n </aside>\r\n}\r\n\r\n<ng-template #emptyRow>\r\n <div\r\n class=\"flex flex-col items-center justify-center px-6 py-8 text-center text-(--p-text-muted-color)\"\r\n >\r\n <p>{{ \"flowplus.common.empty\" | transloco }}</p>\r\n </div>\n</ng-template>\n\n<ng-template #stepDragPreview let-item>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,var(--fp-avatar-color)_28%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(15,23,42,0.18),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n [style.--fp-avatar-color]=\"severityFor(item).color\"\n [style.--fp-avatar-bg]=\"severityFor(item).bg\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[var(--fp-avatar-bg)] text-[var(--fp-avatar-color)] shadow-inner ring-1 ring-[color-mix(in_srgb,var(--fp-avatar-color)_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar size=\"normal\" shape=\"square\" [icon]=\"iconFor(item)\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(item.displayName) }}\n </span>\n @if (item.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(item.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,var(--fp-avatar-color)_7%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n {{ item.category || item.type }}\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[var(--fp-avatar-color)] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n\n<ng-template #triggerDragPreview let-option>\n <div\n class=\"pointer-events-none w-[280px] overflow-hidden rounded-xl border border-[color-mix(in_srgb,rgb(var(--fp-app-action))_30%,var(--p-content-border-color))] bg-(--p-content-background)/95 text-(--p-text-color) shadow-[0_18px_36px_rgba(245,158,11,0.20),0_2px_8px_rgba(15,23,42,0.08)] ring-1 ring-white/60 backdrop-blur-md dark:ring-white/10\"\n >\n <div class=\"flex items-start gap-3 p-3\">\n <span\n class=\"grid h-11 w-11 flex-none place-items-center rounded-xl bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_16%,transparent)] text-[rgb(var(--fp-app-action))] shadow-inner ring-1 ring-[color-mix(in_srgb,rgb(var(--fp-app-action))_24%,transparent)] [&_.p-avatar]:bg-transparent [&_.p-avatar]:text-inherit [&_mt-icon]:size-5 [&_svg]:size-5\"\n >\n <mt-avatar\n size=\"normal\"\n shape=\"square\"\n [icon]=\"triggerIconFor(option)\"\n />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-[13.5px] font-bold leading-5\">\n {{ resolve(option.displayName) }}\n </span>\n @if (option.description) {\n <span\n class=\"mt-0.5 block line-clamp-2 text-[11.5px] leading-[1.45] text-(--p-text-muted-color)\"\n >\n {{ resolve(option.description) }}\n </span>\n }\n </span>\n </div>\n <div\n class=\"flex items-center justify-between border-t border-(--p-content-border-color)/70 bg-[color-mix(in_srgb,rgb(var(--fp-app-action))_8%,transparent)] px-3 py-2\"\n >\n <span\n class=\"max-w-[150px] truncate text-[10.5px] font-semibold text-(--p-text-muted-color)\"\n >\n Trigger\n </span>\n <span\n class=\"inline-flex items-center gap-1 rounded-full bg-(--p-content-background) px-2 py-0.5 text-[10.5px] font-semibold text-[rgb(var(--fp-app-action))] shadow-sm\"\n >\n <mt-icon icon=\"general.plus\" class=\"[&_svg]:size-3\" />\n Drop to add\n </span>\n </div>\n </div>\n</ng-template>\n" }]
|
|
20755
21369
|
}], ctorParameters: () => [], propDecorators: { onDocumentPointerDown: [{
|
|
20756
21370
|
type: HostListener,
|
|
20757
21371
|
args: ['document:pointerdown', ['$event']]
|
|
@@ -20763,6 +21377,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20763
21377
|
type: Output
|
|
20764
21378
|
}], addTrigger: [{
|
|
20765
21379
|
type: Output
|
|
21380
|
+
}], addNote: [{
|
|
21381
|
+
type: Output
|
|
20766
21382
|
}] } });
|
|
20767
21383
|
|
|
20768
21384
|
class BuilderTopbarComponent {
|
|
@@ -20973,6 +21589,9 @@ const TRIGGER_COLUMN_X = 40;
|
|
|
20973
21589
|
const TRIGGER_COLUMN_TOP = 60;
|
|
20974
21590
|
const TRIGGER_ROW_GAP = 200;
|
|
20975
21591
|
const STEP_COLUMN_OFFSET_X = 360;
|
|
21592
|
+
const CANVAS_NOTE_AUTOLAYOUT_PADDING = 48;
|
|
21593
|
+
const TRIGGER_NOTE_WIDTH = 180;
|
|
21594
|
+
const TRIGGER_NOTE_HEIGHT = 132;
|
|
20976
21595
|
class WorkflowBuilderPageComponent {
|
|
20977
21596
|
store = inject(FlowplusWorkflowFacade);
|
|
20978
21597
|
/** The Foblex canvas adapter — used to drive real fit/center/select. */
|
|
@@ -21870,6 +22489,20 @@ class WorkflowBuilderPageComponent {
|
|
|
21870
22489
|
this.clearTransientAddIntent();
|
|
21871
22490
|
this.store.setPaletteOpen(false);
|
|
21872
22491
|
}
|
|
22492
|
+
onAddCanvasNote() {
|
|
22493
|
+
this.clearTransientAddIntent();
|
|
22494
|
+
const note = this.store.addCanvasNote(this.canvas()?.flowCenter() ?? { x: 160, y: 160 });
|
|
22495
|
+
this.canvas()?.focusNote(note.id);
|
|
22496
|
+
}
|
|
22497
|
+
onCanvasNoteUpdate(event) {
|
|
22498
|
+
this.store.updateCanvasNote(event.noteId, event.patch);
|
|
22499
|
+
}
|
|
22500
|
+
onCanvasNoteDuplicate(event) {
|
|
22501
|
+
this.store.duplicateCanvasNote(event.noteId);
|
|
22502
|
+
}
|
|
22503
|
+
onCanvasNoteDelete(event) {
|
|
22504
|
+
this.store.deleteCanvasNote(event.noteId);
|
|
22505
|
+
}
|
|
21873
22506
|
onCanvasBackgroundClick() {
|
|
21874
22507
|
// Click on empty canvas background closes the editor modal + palette drawer
|
|
21875
22508
|
// so the user has the full canvas back.
|
|
@@ -21933,6 +22566,7 @@ class WorkflowBuilderPageComponent {
|
|
|
21933
22566
|
const s = this.store.builderState();
|
|
21934
22567
|
if (!s.workflowId)
|
|
21935
22568
|
return;
|
|
22569
|
+
const noteMembers = this.canvasNoteAutoLayoutMembers();
|
|
21936
22570
|
// Triggers are virtual nodes the Dagre engine doesn't see. Place them in
|
|
21937
22571
|
// a clean left column (entry points, left→right flow) so they never sit
|
|
21938
22572
|
// on top of step nodes.
|
|
@@ -21955,19 +22589,109 @@ class WorkflowBuilderPageComponent {
|
|
|
21955
22589
|
connections: s.connections,
|
|
21956
22590
|
nodeSize: (step) => nodeSizeById.get(step.id) ?? null,
|
|
21957
22591
|
});
|
|
22592
|
+
const nextNodePositions = layout.nodes.map((n) => ({
|
|
22593
|
+
stepId: n.stepId,
|
|
22594
|
+
x: n.x + stepOffsetX,
|
|
22595
|
+
y: n.y,
|
|
22596
|
+
}));
|
|
22597
|
+
const notePositions = this.canvasNoteAutoLayoutPositions(noteMembers, nextNodePositions, triggerPositions);
|
|
21958
22598
|
this.canvas()?.suspendPositionSync();
|
|
21959
22599
|
this.store.setLayoutPositions({
|
|
21960
22600
|
triggers: triggerPositions,
|
|
21961
|
-
nodes:
|
|
21962
|
-
|
|
21963
|
-
x: n.x + stepOffsetX,
|
|
21964
|
-
y: n.y,
|
|
21965
|
-
})),
|
|
22601
|
+
nodes: nextNodePositions,
|
|
22602
|
+
notes: notePositions,
|
|
21966
22603
|
});
|
|
21967
22604
|
// Positions just changed — snap the viewport to the arranged graph once
|
|
21968
22605
|
// it re-renders.
|
|
21969
22606
|
this.canvas()?.armInitialFit();
|
|
21970
22607
|
}
|
|
22608
|
+
canvasNoteAutoLayoutMembers() {
|
|
22609
|
+
const itemRects = this.currentCanvasItemRects();
|
|
22610
|
+
const members = new Map();
|
|
22611
|
+
for (const note of this.store.canvasNotes()) {
|
|
22612
|
+
const noteRect = {
|
|
22613
|
+
id: note.id,
|
|
22614
|
+
x: note.x,
|
|
22615
|
+
y: note.y,
|
|
22616
|
+
width: note.width,
|
|
22617
|
+
height: note.height,
|
|
22618
|
+
};
|
|
22619
|
+
const overlapped = itemRects
|
|
22620
|
+
.filter((rect) => rectsOverlap(noteRect, rect))
|
|
22621
|
+
.map((rect) => rect.id);
|
|
22622
|
+
if (overlapped.length)
|
|
22623
|
+
members.set(note.id, overlapped);
|
|
22624
|
+
}
|
|
22625
|
+
return members;
|
|
22626
|
+
}
|
|
22627
|
+
canvasNoteAutoLayoutPositions(members, nodes, triggers) {
|
|
22628
|
+
if (!members.size)
|
|
22629
|
+
return [];
|
|
22630
|
+
const nextRects = this.nextCanvasItemRects(nodes, triggers);
|
|
22631
|
+
const notes = this.store.canvasNotes();
|
|
22632
|
+
const updates = [];
|
|
22633
|
+
for (const note of notes) {
|
|
22634
|
+
const ids = members.get(note.id);
|
|
22635
|
+
if (!ids?.length)
|
|
22636
|
+
continue;
|
|
22637
|
+
const rects = ids
|
|
22638
|
+
.map((id) => nextRects.get(id))
|
|
22639
|
+
.filter((rect) => rect != null);
|
|
22640
|
+
const bounds = boundsForRects(rects);
|
|
22641
|
+
if (!bounds)
|
|
22642
|
+
continue;
|
|
22643
|
+
updates.push({
|
|
22644
|
+
noteId: note.id,
|
|
22645
|
+
x: bounds.x - CANVAS_NOTE_AUTOLAYOUT_PADDING,
|
|
22646
|
+
y: bounds.y - CANVAS_NOTE_AUTOLAYOUT_PADDING,
|
|
22647
|
+
width: bounds.width + CANVAS_NOTE_AUTOLAYOUT_PADDING * 2,
|
|
22648
|
+
height: bounds.height + CANVAS_NOTE_AUTOLAYOUT_PADDING * 2,
|
|
22649
|
+
});
|
|
22650
|
+
}
|
|
22651
|
+
return updates;
|
|
22652
|
+
}
|
|
22653
|
+
currentCanvasItemRects() {
|
|
22654
|
+
return [
|
|
22655
|
+
...this.store.nodeVms().map((node) => ({
|
|
22656
|
+
id: `step:${node.stepId}`,
|
|
22657
|
+
x: node.x,
|
|
22658
|
+
y: node.y,
|
|
22659
|
+
width: node.width ?? 250,
|
|
22660
|
+
height: node.height ?? 116,
|
|
22661
|
+
})),
|
|
22662
|
+
...this.store.triggerNodeVms().map((trigger) => ({
|
|
22663
|
+
id: `trigger:${trigger.triggerId}`,
|
|
22664
|
+
x: trigger.x,
|
|
22665
|
+
y: trigger.y,
|
|
22666
|
+
width: TRIGGER_NOTE_WIDTH,
|
|
22667
|
+
height: TRIGGER_NOTE_HEIGHT,
|
|
22668
|
+
})),
|
|
22669
|
+
];
|
|
22670
|
+
}
|
|
22671
|
+
nextCanvasItemRects(nodes, triggers) {
|
|
22672
|
+
const currentNodes = new Map(this.store.nodeVms().map((node) => [node.stepId, node]));
|
|
22673
|
+
const rects = new Map();
|
|
22674
|
+
for (const node of nodes) {
|
|
22675
|
+
const vm = currentNodes.get(node.stepId);
|
|
22676
|
+
rects.set(`step:${node.stepId}`, {
|
|
22677
|
+
id: `step:${node.stepId}`,
|
|
22678
|
+
x: node.x,
|
|
22679
|
+
y: node.y,
|
|
22680
|
+
width: vm?.width ?? 250,
|
|
22681
|
+
height: vm?.height ?? 116,
|
|
22682
|
+
});
|
|
22683
|
+
}
|
|
22684
|
+
for (const trigger of triggers) {
|
|
22685
|
+
rects.set(`trigger:${trigger.triggerId}`, {
|
|
22686
|
+
id: `trigger:${trigger.triggerId}`,
|
|
22687
|
+
x: trigger.x,
|
|
22688
|
+
y: trigger.y,
|
|
22689
|
+
width: TRIGGER_NOTE_WIDTH,
|
|
22690
|
+
height: TRIGGER_NOTE_HEIGHT,
|
|
22691
|
+
});
|
|
22692
|
+
}
|
|
22693
|
+
return rects;
|
|
22694
|
+
}
|
|
21971
22695
|
deleteSelection() {
|
|
21972
22696
|
const sel = this.store.selection();
|
|
21973
22697
|
for (const stepId of sel.stepIds) {
|
|
@@ -21978,6 +22702,8 @@ class WorkflowBuilderPageComponent {
|
|
|
21978
22702
|
}
|
|
21979
22703
|
for (const connId of sel.connectionIds)
|
|
21980
22704
|
this.store.deleteConnection(connId);
|
|
22705
|
+
for (const noteId of sel.canvasNoteIds)
|
|
22706
|
+
this.store.deleteCanvasNote(noteId);
|
|
21981
22707
|
}
|
|
21982
22708
|
/* -------- node hover-bar actions (Phase 3) -------- */
|
|
21983
22709
|
onNodeQuickAdd(e) {
|
|
@@ -22216,7 +22942,7 @@ class WorkflowBuilderPageComponent {
|
|
|
22216
22942
|
this.store.setInspectorOpen(true);
|
|
22217
22943
|
}
|
|
22218
22944
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkflowBuilderPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
22219
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkflowBuilderPageComponent, isStandalone: true, selector: "fp-workflow-builder-page", viewQueries: [{ propertyName: "canvas", first: true, predicate: FlowCanvasComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"relative flex h-full min-h-full w-full flex-col overflow-hidden bg-(--p-surface-50) text-(--p-text-color)\"\n id=\"fp-builder-root\"\n>\n <fp-builder-topbar\n (validate)=\"onValidate()\"\n (testRun)=\"onOpenTestRun()\"\n (publish)=\"onPublish()\"\n (unpublish)=\"onUnpublish()\"\n (openSettings)=\"onOpenSettings()\"\n (toggleNodeFinder)=\"onTogglePalette()\"\n />\n\n <div\n class=\"relative min-h-0 flex-1 overflow-hidden\"\n id=\"fp-workspace-root\"\n [class.is-bottom-open]=\"store.ui().bottomPanelOpen\"\n [class.is-palette-expanded]=\"store.ui().paletteOpen\"\n >\n @if (store.busy()) {\n <div\n class=\"pointer-events-none absolute inset-x-0 top-0 z-[7] h-0.5 overflow-hidden bg-(--p-primary-color)/15\"\n role=\"status\"\n aria-label=\"Working...\"\n >\n <div\n class=\"h-full w-[30%] bg-(--p-primary-color) animate-[fp-busy-bar-slide_1.1s_cubic-bezier(0.4,0,0.2,1)_infinite]\"\n ></div>\n </div>\n }\n\n <fp-palette\n (openRequested)=\"onOpenPaletteFromRail()\"\n (closeRequested)=\"onClosePalette()\"\n (add)=\"onPaletteAdd($event)\"\n (addTrigger)=\"onPaletteAddTrigger($event)\"\n />\n\n <main class=\"absolute inset-0 overflow-hidden bg-(--p-surface-50)\">\n <fp-flow-canvas\n (paletteDrop)=\"onPaletteDrop($event)\"\n (connectionCreate)=\"onConnectionCreate($event)\"\n (connectionReassign)=\"onConnectionReassign($event)\"\n (triggerStartConnect)=\"onTriggerStartConnect($event)\"\n (triggerStartReassign)=\"onTriggerStartReassign($event)\"\n (triggerStartDisconnect)=\"onTriggerStartDisconnect($event)\"\n (connectionQuickAdd)=\"onConnectionQuickAdd($event)\"\n (quickAddPick)=\"onQuickAddPick($event)\"\n (autoLayoutRequested)=\"autoLayout()\"\n (nodeQuickAdd)=\"onNodeQuickAdd($event)\"\n (nodePortPlusClick)=\"onNodePortPlusClick($event)\"\n (nodeDuplicate)=\"onNodeDuplicate($event)\"\n (nodeRemove)=\"onNodeRemove($event)\"\n (nodeOpenDetails)=\"onNodeOpenDetails($event)\"\n (edgeInsertStep)=\"onEdgeInsertStep($event)\"\n (edgeRemove)=\"onEdgeRemove($event)\"\n (edgeEditFormula)=\"onEdgeEditFormula($event)\"\n (edgeOpenDetails)=\"onEdgeOpenDetails($event)\"\n (assignNodeToConnection)=\"onAssignNodeToConnection($event)\"\n (openChildWorkflow)=\"onOpenChildWorkflow($event)\"\n (starterAddTrigger)=\"onStarterAddTrigger($event)\"\n (triggerOpenDetails)=\"onTriggerOpenDetails($event)\"\n (triggerExecute)=\"onTriggerExecute($event)\"\n (triggerToggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (triggerDelete)=\"onTriggerDelete($event)\"\n (requestAddStep)=\"onRequestAddStep($event)\"\n (canvasBackgroundClick)=\"onCanvasBackgroundClick()\"\n />\n\n @if (store.loading()) {\n <div\n class=\"pointer-events-none absolute inset-0 z-[7] flex flex-col items-center justify-center gap-3.5 bg-(--p-surface-50)/70 text-[12.5px] text-(--p-text-muted-color) backdrop-blur-[2px] animate-[fp-fade-in_240ms_ease-out]\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <div\n class=\"h-9 w-9 rounded-full border-[3px] border-(--p-primary-color)/20 border-t-(--p-primary-color) animate-[fp-loading-spin_720ms_linear_infinite]\"\n aria-hidden=\"true\"\n ></div>\n <span>{{ \"flowplus.common.loading\" | transloco }}</span>\n </div>\n }\n </main>\n\n <fp-bottom-panel\n [class.h-96]=\"store.ui().bottomPanelOpen\"\n [class.h-10]=\"!store.ui().bottomPanelOpen\"\n (focus)=\"onFocusIssue($event)\"\n />\n </div>\n\n <fp-command-palette\n [open]=\"commandPaletteOpen()\"\n [actions]=\"commandPaletteActions()\"\n (pick)=\"onCommandPalettePick($event)\"\n (dismiss)=\"closeCommandPalette()\"\n />\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: BuilderTopbarComponent, selector: "fp-builder-topbar", outputs: ["validate", "testRun", "publish", "unpublish", "openSettings", "toggleNodeFinder"] }, { kind: "component", type: PaletteComponent, selector: "fp-palette", outputs: ["closeRequested", "openRequested", "add", "addTrigger"] }, { kind: "component", type: FlowCanvasComponent, selector: "fp-flow-canvas", outputs: ["paletteDrop", "connectionCreate", "connectionReassign", "triggerStartConnect", "triggerStartReassign", "triggerStartDisconnect", "connectionQuickAdd", "quickAddPick", "autoLayoutRequested", "loaded", "nodeQuickAdd", "nodePortPlusClick", "nodeDuplicate", "nodeRemove", "nodeOpenDetails", "edgeInsertStep", "edgeRemove", "edgeEditFormula", "edgeOpenDetails", "assignNodeToConnection", "openChildWorkflow", "starterAddTrigger", "triggerOpenDetails", "triggerExecute", "triggerToggleEnabled", "triggerDelete", "canvasBackgroundClick", "requestAddStep"] }, { kind: "component", type: BottomPanelComponent, selector: "fp-bottom-panel", outputs: ["focus"] }, { kind: "component", type: CommandPaletteComponent, selector: "fp-command-palette", inputs: ["open", "actions"], outputs: ["pick", "dismiss"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
22945
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkflowBuilderPageComponent, isStandalone: true, selector: "fp-workflow-builder-page", viewQueries: [{ propertyName: "canvas", first: true, predicate: FlowCanvasComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"relative flex h-full min-h-full w-full flex-col overflow-hidden bg-(--p-surface-50) text-(--p-text-color)\"\n id=\"fp-builder-root\"\n>\n <fp-builder-topbar\n (validate)=\"onValidate()\"\n (testRun)=\"onOpenTestRun()\"\n (publish)=\"onPublish()\"\n (unpublish)=\"onUnpublish()\"\n (openSettings)=\"onOpenSettings()\"\n (toggleNodeFinder)=\"onTogglePalette()\"\n />\n\n <div\n class=\"relative min-h-0 flex-1 overflow-hidden\"\n id=\"fp-workspace-root\"\n [class.is-bottom-open]=\"store.ui().bottomPanelOpen\"\n [class.is-palette-expanded]=\"store.ui().paletteOpen\"\n >\n @if (store.busy()) {\n <div\n class=\"pointer-events-none absolute inset-x-0 top-0 z-[7] h-0.5 overflow-hidden bg-(--p-primary-color)/15\"\n role=\"status\"\n aria-label=\"Working...\"\n >\n <div\n class=\"h-full w-[30%] bg-(--p-primary-color) animate-[fp-busy-bar-slide_1.1s_cubic-bezier(0.4,0,0.2,1)_infinite]\"\n ></div>\n </div>\n }\n\n <fp-palette\n (openRequested)=\"onOpenPaletteFromRail()\"\n (closeRequested)=\"onClosePalette()\"\n (add)=\"onPaletteAdd($event)\"\n (addTrigger)=\"onPaletteAddTrigger($event)\"\n (addNote)=\"onAddCanvasNote()\"\n />\n\n <main class=\"absolute inset-0 overflow-hidden bg-(--p-surface-50)\">\n <fp-flow-canvas\n (paletteDrop)=\"onPaletteDrop($event)\"\n (connectionCreate)=\"onConnectionCreate($event)\"\n (connectionReassign)=\"onConnectionReassign($event)\"\n (triggerStartConnect)=\"onTriggerStartConnect($event)\"\n (triggerStartReassign)=\"onTriggerStartReassign($event)\"\n (triggerStartDisconnect)=\"onTriggerStartDisconnect($event)\"\n (connectionQuickAdd)=\"onConnectionQuickAdd($event)\"\n (quickAddPick)=\"onQuickAddPick($event)\"\n (autoLayoutRequested)=\"autoLayout()\"\n (nodeQuickAdd)=\"onNodeQuickAdd($event)\"\n (nodePortPlusClick)=\"onNodePortPlusClick($event)\"\n (nodeDuplicate)=\"onNodeDuplicate($event)\"\n (nodeRemove)=\"onNodeRemove($event)\"\n (nodeOpenDetails)=\"onNodeOpenDetails($event)\"\n (edgeInsertStep)=\"onEdgeInsertStep($event)\"\n (edgeRemove)=\"onEdgeRemove($event)\"\n (edgeEditFormula)=\"onEdgeEditFormula($event)\"\n (edgeOpenDetails)=\"onEdgeOpenDetails($event)\"\n (assignNodeToConnection)=\"onAssignNodeToConnection($event)\"\n (openChildWorkflow)=\"onOpenChildWorkflow($event)\"\n (starterAddTrigger)=\"onStarterAddTrigger($event)\"\n (triggerOpenDetails)=\"onTriggerOpenDetails($event)\"\n (triggerExecute)=\"onTriggerExecute($event)\"\n (triggerToggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (triggerDelete)=\"onTriggerDelete($event)\"\n (requestAddStep)=\"onRequestAddStep($event)\"\n (noteUpdate)=\"onCanvasNoteUpdate($event)\"\n (noteDuplicate)=\"onCanvasNoteDuplicate($event)\"\n (noteDelete)=\"onCanvasNoteDelete($event)\"\n (canvasBackgroundClick)=\"onCanvasBackgroundClick()\"\n />\n\n @if (store.loading()) {\n <div\n class=\"pointer-events-none absolute inset-0 z-[7] flex flex-col items-center justify-center gap-3.5 bg-(--p-surface-50)/70 text-[12.5px] text-(--p-text-muted-color) backdrop-blur-[2px] animate-[fp-fade-in_240ms_ease-out]\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <div\n class=\"h-9 w-9 rounded-full border-[3px] border-(--p-primary-color)/20 border-t-(--p-primary-color) animate-[fp-loading-spin_720ms_linear_infinite]\"\n aria-hidden=\"true\"\n ></div>\n <span>{{ \"flowplus.common.loading\" | transloco }}</span>\n </div>\n }\n </main>\n\n <fp-bottom-panel\n [class.h-96]=\"store.ui().bottomPanelOpen\"\n [class.h-10]=\"!store.ui().bottomPanelOpen\"\n (focus)=\"onFocusIssue($event)\"\n />\n </div>\n\n <fp-command-palette\n [open]=\"commandPaletteOpen()\"\n [actions]=\"commandPaletteActions()\"\n (pick)=\"onCommandPalettePick($event)\"\n (dismiss)=\"closeCommandPalette()\"\n />\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: BuilderTopbarComponent, selector: "fp-builder-topbar", outputs: ["validate", "testRun", "publish", "unpublish", "openSettings", "toggleNodeFinder"] }, { kind: "component", type: PaletteComponent, selector: "fp-palette", outputs: ["closeRequested", "openRequested", "add", "addTrigger", "addNote"] }, { kind: "component", type: FlowCanvasComponent, selector: "fp-flow-canvas", outputs: ["paletteDrop", "connectionCreate", "connectionReassign", "triggerStartConnect", "triggerStartReassign", "triggerStartDisconnect", "connectionQuickAdd", "quickAddPick", "autoLayoutRequested", "loaded", "nodeQuickAdd", "nodePortPlusClick", "nodeDuplicate", "nodeRemove", "nodeOpenDetails", "edgeInsertStep", "edgeRemove", "edgeEditFormula", "edgeOpenDetails", "assignNodeToConnection", "openChildWorkflow", "starterAddTrigger", "triggerOpenDetails", "triggerExecute", "triggerToggleEnabled", "triggerDelete", "canvasBackgroundClick", "requestAddStep", "noteUpdate", "noteDuplicate", "noteDelete"] }, { kind: "component", type: BottomPanelComponent, selector: "fp-bottom-panel", outputs: ["focus"] }, { kind: "component", type: CommandPaletteComponent, selector: "fp-command-palette", inputs: ["open", "actions"], outputs: ["pick", "dismiss"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
22220
22946
|
}
|
|
22221
22947
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkflowBuilderPageComponent, decorators: [{
|
|
22222
22948
|
type: Component,
|
|
@@ -22228,7 +22954,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
22228
22954
|
FlowCanvasComponent,
|
|
22229
22955
|
BottomPanelComponent,
|
|
22230
22956
|
CommandPaletteComponent,
|
|
22231
|
-
], template: "<div\n class=\"relative flex h-full min-h-full w-full flex-col overflow-hidden bg-(--p-surface-50) text-(--p-text-color)\"\n id=\"fp-builder-root\"\n>\n <fp-builder-topbar\n (validate)=\"onValidate()\"\n (testRun)=\"onOpenTestRun()\"\n (publish)=\"onPublish()\"\n (unpublish)=\"onUnpublish()\"\n (openSettings)=\"onOpenSettings()\"\n (toggleNodeFinder)=\"onTogglePalette()\"\n />\n\n <div\n class=\"relative min-h-0 flex-1 overflow-hidden\"\n id=\"fp-workspace-root\"\n [class.is-bottom-open]=\"store.ui().bottomPanelOpen\"\n [class.is-palette-expanded]=\"store.ui().paletteOpen\"\n >\n @if (store.busy()) {\n <div\n class=\"pointer-events-none absolute inset-x-0 top-0 z-[7] h-0.5 overflow-hidden bg-(--p-primary-color)/15\"\n role=\"status\"\n aria-label=\"Working...\"\n >\n <div\n class=\"h-full w-[30%] bg-(--p-primary-color) animate-[fp-busy-bar-slide_1.1s_cubic-bezier(0.4,0,0.2,1)_infinite]\"\n ></div>\n </div>\n }\n\n <fp-palette\n (openRequested)=\"onOpenPaletteFromRail()\"\n (closeRequested)=\"onClosePalette()\"\n (add)=\"onPaletteAdd($event)\"\n (addTrigger)=\"onPaletteAddTrigger($event)\"\n />\n\n <main class=\"absolute inset-0 overflow-hidden bg-(--p-surface-50)\">\n <fp-flow-canvas\n (paletteDrop)=\"onPaletteDrop($event)\"\n (connectionCreate)=\"onConnectionCreate($event)\"\n (connectionReassign)=\"onConnectionReassign($event)\"\n (triggerStartConnect)=\"onTriggerStartConnect($event)\"\n (triggerStartReassign)=\"onTriggerStartReassign($event)\"\n (triggerStartDisconnect)=\"onTriggerStartDisconnect($event)\"\n (connectionQuickAdd)=\"onConnectionQuickAdd($event)\"\n (quickAddPick)=\"onQuickAddPick($event)\"\n (autoLayoutRequested)=\"autoLayout()\"\n (nodeQuickAdd)=\"onNodeQuickAdd($event)\"\n (nodePortPlusClick)=\"onNodePortPlusClick($event)\"\n (nodeDuplicate)=\"onNodeDuplicate($event)\"\n (nodeRemove)=\"onNodeRemove($event)\"\n (nodeOpenDetails)=\"onNodeOpenDetails($event)\"\n (edgeInsertStep)=\"onEdgeInsertStep($event)\"\n (edgeRemove)=\"onEdgeRemove($event)\"\n (edgeEditFormula)=\"onEdgeEditFormula($event)\"\n (edgeOpenDetails)=\"onEdgeOpenDetails($event)\"\n (assignNodeToConnection)=\"onAssignNodeToConnection($event)\"\n (openChildWorkflow)=\"onOpenChildWorkflow($event)\"\n (starterAddTrigger)=\"onStarterAddTrigger($event)\"\n (triggerOpenDetails)=\"onTriggerOpenDetails($event)\"\n (triggerExecute)=\"onTriggerExecute($event)\"\n (triggerToggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (triggerDelete)=\"onTriggerDelete($event)\"\n (requestAddStep)=\"onRequestAddStep($event)\"\n (canvasBackgroundClick)=\"onCanvasBackgroundClick()\"\n />\n\n @if (store.loading()) {\n <div\n class=\"pointer-events-none absolute inset-0 z-[7] flex flex-col items-center justify-center gap-3.5 bg-(--p-surface-50)/70 text-[12.5px] text-(--p-text-muted-color) backdrop-blur-[2px] animate-[fp-fade-in_240ms_ease-out]\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <div\n class=\"h-9 w-9 rounded-full border-[3px] border-(--p-primary-color)/20 border-t-(--p-primary-color) animate-[fp-loading-spin_720ms_linear_infinite]\"\n aria-hidden=\"true\"\n ></div>\n <span>{{ \"flowplus.common.loading\" | transloco }}</span>\n </div>\n }\n </main>\n\n <fp-bottom-panel\n [class.h-96]=\"store.ui().bottomPanelOpen\"\n [class.h-10]=\"!store.ui().bottomPanelOpen\"\n (focus)=\"onFocusIssue($event)\"\n />\n </div>\n\n <fp-command-palette\n [open]=\"commandPaletteOpen()\"\n [actions]=\"commandPaletteActions()\"\n (pick)=\"onCommandPalettePick($event)\"\n (dismiss)=\"closeCommandPalette()\"\n />\n</div>\n" }]
|
|
22957
|
+
], template: "<div\n class=\"relative flex h-full min-h-full w-full flex-col overflow-hidden bg-(--p-surface-50) text-(--p-text-color)\"\n id=\"fp-builder-root\"\n>\n <fp-builder-topbar\n (validate)=\"onValidate()\"\n (testRun)=\"onOpenTestRun()\"\n (publish)=\"onPublish()\"\n (unpublish)=\"onUnpublish()\"\n (openSettings)=\"onOpenSettings()\"\n (toggleNodeFinder)=\"onTogglePalette()\"\n />\n\n <div\n class=\"relative min-h-0 flex-1 overflow-hidden\"\n id=\"fp-workspace-root\"\n [class.is-bottom-open]=\"store.ui().bottomPanelOpen\"\n [class.is-palette-expanded]=\"store.ui().paletteOpen\"\n >\n @if (store.busy()) {\n <div\n class=\"pointer-events-none absolute inset-x-0 top-0 z-[7] h-0.5 overflow-hidden bg-(--p-primary-color)/15\"\n role=\"status\"\n aria-label=\"Working...\"\n >\n <div\n class=\"h-full w-[30%] bg-(--p-primary-color) animate-[fp-busy-bar-slide_1.1s_cubic-bezier(0.4,0,0.2,1)_infinite]\"\n ></div>\n </div>\n }\n\n <fp-palette\n (openRequested)=\"onOpenPaletteFromRail()\"\n (closeRequested)=\"onClosePalette()\"\n (add)=\"onPaletteAdd($event)\"\n (addTrigger)=\"onPaletteAddTrigger($event)\"\n (addNote)=\"onAddCanvasNote()\"\n />\n\n <main class=\"absolute inset-0 overflow-hidden bg-(--p-surface-50)\">\n <fp-flow-canvas\n (paletteDrop)=\"onPaletteDrop($event)\"\n (connectionCreate)=\"onConnectionCreate($event)\"\n (connectionReassign)=\"onConnectionReassign($event)\"\n (triggerStartConnect)=\"onTriggerStartConnect($event)\"\n (triggerStartReassign)=\"onTriggerStartReassign($event)\"\n (triggerStartDisconnect)=\"onTriggerStartDisconnect($event)\"\n (connectionQuickAdd)=\"onConnectionQuickAdd($event)\"\n (quickAddPick)=\"onQuickAddPick($event)\"\n (autoLayoutRequested)=\"autoLayout()\"\n (nodeQuickAdd)=\"onNodeQuickAdd($event)\"\n (nodePortPlusClick)=\"onNodePortPlusClick($event)\"\n (nodeDuplicate)=\"onNodeDuplicate($event)\"\n (nodeRemove)=\"onNodeRemove($event)\"\n (nodeOpenDetails)=\"onNodeOpenDetails($event)\"\n (edgeInsertStep)=\"onEdgeInsertStep($event)\"\n (edgeRemove)=\"onEdgeRemove($event)\"\n (edgeEditFormula)=\"onEdgeEditFormula($event)\"\n (edgeOpenDetails)=\"onEdgeOpenDetails($event)\"\n (assignNodeToConnection)=\"onAssignNodeToConnection($event)\"\n (openChildWorkflow)=\"onOpenChildWorkflow($event)\"\n (starterAddTrigger)=\"onStarterAddTrigger($event)\"\n (triggerOpenDetails)=\"onTriggerOpenDetails($event)\"\n (triggerExecute)=\"onTriggerExecute($event)\"\n (triggerToggleEnabled)=\"onTriggerToggleEnabled($event)\"\n (triggerDelete)=\"onTriggerDelete($event)\"\n (requestAddStep)=\"onRequestAddStep($event)\"\n (noteUpdate)=\"onCanvasNoteUpdate($event)\"\n (noteDuplicate)=\"onCanvasNoteDuplicate($event)\"\n (noteDelete)=\"onCanvasNoteDelete($event)\"\n (canvasBackgroundClick)=\"onCanvasBackgroundClick()\"\n />\n\n @if (store.loading()) {\n <div\n class=\"pointer-events-none absolute inset-0 z-[7] flex flex-col items-center justify-center gap-3.5 bg-(--p-surface-50)/70 text-[12.5px] text-(--p-text-muted-color) backdrop-blur-[2px] animate-[fp-fade-in_240ms_ease-out]\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <div\n class=\"h-9 w-9 rounded-full border-[3px] border-(--p-primary-color)/20 border-t-(--p-primary-color) animate-[fp-loading-spin_720ms_linear_infinite]\"\n aria-hidden=\"true\"\n ></div>\n <span>{{ \"flowplus.common.loading\" | transloco }}</span>\n </div>\n }\n </main>\n\n <fp-bottom-panel\n [class.h-96]=\"store.ui().bottomPanelOpen\"\n [class.h-10]=\"!store.ui().bottomPanelOpen\"\n (focus)=\"onFocusIssue($event)\"\n />\n </div>\n\n <fp-command-palette\n [open]=\"commandPaletteOpen()\"\n [actions]=\"commandPaletteActions()\"\n (pick)=\"onCommandPalettePick($event)\"\n (dismiss)=\"closeCommandPalette()\"\n />\n</div>\n" }]
|
|
22232
22958
|
}], ctorParameters: () => [], propDecorators: { canvas: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FlowCanvasComponent), { isSignal: true }] }] } });
|
|
22233
22959
|
function readObject(value) {
|
|
22234
22960
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -22333,6 +23059,27 @@ function uniqueStrings(values) {
|
|
|
22333
23059
|
}
|
|
22334
23060
|
return out;
|
|
22335
23061
|
}
|
|
23062
|
+
function rectsOverlap(a, b) {
|
|
23063
|
+
return !(a.x + a.width < b.x ||
|
|
23064
|
+
b.x + b.width < a.x ||
|
|
23065
|
+
a.y + a.height < b.y ||
|
|
23066
|
+
b.y + b.height < a.y);
|
|
23067
|
+
}
|
|
23068
|
+
function boundsForRects(rects) {
|
|
23069
|
+
if (!rects.length)
|
|
23070
|
+
return null;
|
|
23071
|
+
const minX = Math.min(...rects.map((rect) => rect.x));
|
|
23072
|
+
const minY = Math.min(...rects.map((rect) => rect.y));
|
|
23073
|
+
const maxX = Math.max(...rects.map((rect) => rect.x + rect.width));
|
|
23074
|
+
const maxY = Math.max(...rects.map((rect) => rect.y + rect.height));
|
|
23075
|
+
return {
|
|
23076
|
+
id: 'bounds',
|
|
23077
|
+
x: minX,
|
|
23078
|
+
y: minY,
|
|
23079
|
+
width: maxX - minX,
|
|
23080
|
+
height: maxY - minY,
|
|
23081
|
+
};
|
|
23082
|
+
}
|
|
22336
23083
|
function readString$1(record, key) {
|
|
22337
23084
|
const value = record[key];
|
|
22338
23085
|
return typeof value === 'string' && value.trim() ? value : null;
|
|
@@ -23166,5 +23913,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
23166
23913
|
* Generated bundle index. Do not edit.
|
|
23167
23914
|
*/
|
|
23168
23915
|
|
|
23169
|
-
export { APP_STATES, ApplyAutomationExecutionDetail, ApplyBuilderCommand, ApplyBuilderSnapshot, AutomationBuilderCatalogApiService, AutomationDesignApiService, AutomationExecutionApiService, AutomationExecutionsPageComponent, BottomPanelComponent, BuilderTopbarComponent, ClearAutomationRuntimeState, ClearCommandHistory, ClearConflict, ClearPendingOperation, ClearSelection, ClearWorkflowBuilder, CommitStepUpdates, CommitWorkflowMetadata, ConnectionCreated, ConnectionCreationFailed, ContextPickerComponent, ContextPillButtonComponent, ContextPillComponent, CreateConnection, CreateStep, CreateTrigger, CreateWorkflow, DagreFlowLayoutEngine, DeleteConnection, DeleteStep, DeleteTrigger, DeleteWorkflow, DuplicateWorkflow, EndpointBuilder, FLOWPLUS_FORM_DESIGNER_ADAPTER, FLOWPLUS_WORKFLOW_CONFIG, FLOWPLUS_WORKFLOW_DEFAULT_RUNTIME, FLOWPLUS_WORKFLOW_DEFAULT_STATE, FLOWPLUS_WORKFLOW_NAVIGATION, FLOWPLUS_WORKFLOW_ROUTES, FLOW_NODE_BASE_HEIGHT, FLOW_NODE_CARD_WIDTH, FLOW_NODE_MULTI_OUTPUT_GAP, FLOW_NODE_OUTPUT_SIZE, FlowCanvasComponent, FlowNodeComponent, FlowplusWorkflowActionKey, FlowplusWorkflowFacade, FlowplusWorkflowNavigationService, FlowplusWorkflowOverlayService, FlowplusWorkflowState, InspectorShellComponent, KeyboardShortcutsService, LOCAL_FALLBACK_CATALOG, LoadAutomationExecution, LoadContextCatalog, LoadContextCatalogForStep, LoadLatestAutomationExecution, LoadLayout, LoadTriggers, LoadWorkflowBuilder, LoadWorkflowCatalog, LoadWorkflowList, MarkLayoutDirty, MoveStep, NODE_COLOR_TOKEN, NODE_DEFAULT_ICON, NODE_MT_ICON, NoopFlowplusFormDesignerAdapter, PaletteComponent, PaletteDragSourceDirective, PollAutomationExecution, ProblemsPanelComponent, ProcessCreateDialogComponent, PublishWorkflow, RedoBuilderCommand, ReloadWorkflowBuilder, RunAutomationTrigger, RunWorkflowTest, SaveLayout, SelectConnection, SelectRuntimeNodeRun, SelectStep, SelectTrigger, SetActiveInspectorTab, SetBottomPanelOpen, SetBottomPanelTab, SetCanvasViewport, SetContextCatalog, SetCreateDialogOpen, SetInspectorOpen, SetLayout, SetLayoutAutosavePaused, SetMinimap, SetPaletteOpen, SetPaletteSearch, SetPendingOperation, SetReadonly, SetSelectedRuntimeTrigger, SetSelection, SetSelectionFromCanvas, SetStudioFilter, SetValidation, SetWorkflowCatalog, SetWorkflowDefinition, StepCreated, StepCreationFailed, TRIGGER_MT_ICON, TestRunPanelComponent, UnconfiguredFormDesignerAdapter, UndoBuilderCommand, UnpublishWorkflow, UpdateConnection, UpdateStep, UpdateTrigger, UpdateWorkflowMetadata, UpdateWorkflowResources, UpdateWorkflowVariables, ValidateWorkflow, WorkflowBuilderPageComponent, WorkflowCatalogApiService, WorkflowContextApiService, WorkflowDebugApiService, WorkflowDefinitionApiService, WorkflowFormApiService, WorkflowRunDebuggerPageComponent, WorkflowRuntimeApiService, WorkflowStudioPageComponent, WorkflowValidationApiService, applyBuilderSnapshot, avatarSeverityForStep, avatarSeverityForTrigger, canonicalTriggerTypeForStarterKind, coerceTranslatable, colorVarFor, computeBranchLanes, computeSaveStatus, connectionCanvasId, derivePortsForStep, extractMessage, flowNodeCardHeightForOutputs, flowNodeLayoutHeightForOutputs, flowNodeOutputCenterY, flowNodeOutputStackHeight, fromWorkflowConnectionDomain, fromWorkflowStepDomain, hasOtherPending, iconFor, indexValidationByConnectionId, indexValidationByStepId, indexValidationByTriggerId, inputPortId, isEntityDirty, mapHttpError, mtIconForStep, mtIconForTrigger, newClientMutationId, nextOperationId, nodeCanvasId, outputPortId, parseConnectionId, parseNodeId, parsePortId, parseTriggerOutputPortId, parseTriggerStartConnectionId, patchLayoutPosition, patchTriggerLayoutPosition, provideFlowplusFormDesignerAdapter, provideFlowplusWorkflow, provideFlowplusWorkflowNavigation, provideFlowplusWorkflowNavigationDefaults, readRecord, removeStepWithEdges, resolveTranslatable, resolveTriggerStartNodeKey, resolveTriggerStartStep, resolveTriggerStartStepId, resolveWorkflowTriggerKey, savingOrSaved, tempNodeCanvasId, toWorkflowConnectionDomain, toWorkflowDefinitionDomain, toWorkflowStepDomain, toWorkflowTriggerDomain, triggerCanvasId, triggerOutputPortId, triggerStartConnectionCanvasId, triggerStarterKindFor, unwrap, unwrapApiData, upsertConnection, upsertStep };
|
|
23916
|
+
export { APP_STATES, AddCanvasNote, ApplyAutomationExecutionDetail, ApplyBuilderCommand, ApplyBuilderSnapshot, AutomationBuilderCatalogApiService, AutomationDesignApiService, AutomationExecutionApiService, AutomationExecutionsPageComponent, BottomPanelComponent, BuilderTopbarComponent, ClearAutomationRuntimeState, ClearCommandHistory, ClearConflict, ClearPendingOperation, ClearSelection, ClearWorkflowBuilder, CommitStepUpdates, CommitWorkflowMetadata, ConnectionCreated, ConnectionCreationFailed, ContextPickerComponent, ContextPillButtonComponent, ContextPillComponent, CreateConnection, CreateStep, CreateTrigger, CreateWorkflow, DagreFlowLayoutEngine, DeleteCanvasNote, DeleteConnection, DeleteStep, DeleteTrigger, DeleteWorkflow, DuplicateCanvasNote, DuplicateWorkflow, EndpointBuilder, FLOWPLUS_FORM_DESIGNER_ADAPTER, FLOWPLUS_WORKFLOW_CONFIG, FLOWPLUS_WORKFLOW_DEFAULT_RUNTIME, FLOWPLUS_WORKFLOW_DEFAULT_STATE, FLOWPLUS_WORKFLOW_NAVIGATION, FLOWPLUS_WORKFLOW_ROUTES, FLOW_NODE_BASE_HEIGHT, FLOW_NODE_CARD_WIDTH, FLOW_NODE_MULTI_OUTPUT_GAP, FLOW_NODE_OUTPUT_SIZE, FlowCanvasComponent, FlowNodeComponent, FlowplusWorkflowActionKey, FlowplusWorkflowFacade, FlowplusWorkflowNavigationService, FlowplusWorkflowOverlayService, FlowplusWorkflowState, InspectorShellComponent, KeyboardShortcutsService, LOCAL_FALLBACK_CATALOG, LoadAutomationExecution, LoadContextCatalog, LoadContextCatalogForStep, LoadLatestAutomationExecution, LoadLayout, LoadTriggers, LoadWorkflowBuilder, LoadWorkflowCatalog, LoadWorkflowList, MarkLayoutDirty, MoveStep, NODE_COLOR_TOKEN, NODE_DEFAULT_ICON, NODE_MT_ICON, NoopFlowplusFormDesignerAdapter, PaletteComponent, PaletteDragSourceDirective, PollAutomationExecution, ProblemsPanelComponent, ProcessCreateDialogComponent, PublishWorkflow, RedoBuilderCommand, ReloadWorkflowBuilder, RunAutomationTrigger, RunWorkflowTest, SaveLayout, SelectCanvasNote, SelectConnection, SelectRuntimeNodeRun, SelectStep, SelectTrigger, SetActiveInspectorTab, SetBottomPanelOpen, SetBottomPanelTab, SetCanvasViewport, SetContextCatalog, SetCreateDialogOpen, SetInspectorOpen, SetLayout, SetLayoutAutosavePaused, SetMinimap, SetPaletteOpen, SetPaletteSearch, SetPendingOperation, SetReadonly, SetSelectedRuntimeTrigger, SetSelection, SetSelectionFromCanvas, SetStudioFilter, SetValidation, SetWorkflowCatalog, SetWorkflowDefinition, StepCreated, StepCreationFailed, TRIGGER_MT_ICON, TestRunPanelComponent, UnconfiguredFormDesignerAdapter, UndoBuilderCommand, UnpublishWorkflow, UpdateCanvasNote, UpdateConnection, UpdateStep, UpdateTrigger, UpdateWorkflowMetadata, UpdateWorkflowResources, UpdateWorkflowVariables, ValidateWorkflow, WorkflowBuilderPageComponent, WorkflowCatalogApiService, WorkflowContextApiService, WorkflowDebugApiService, WorkflowDefinitionApiService, WorkflowFormApiService, WorkflowRunDebuggerPageComponent, WorkflowRuntimeApiService, WorkflowStudioPageComponent, WorkflowValidationApiService, applyBuilderSnapshot, avatarSeverityForStep, avatarSeverityForTrigger, canonicalTriggerTypeForStarterKind, coerceTranslatable, colorVarFor, computeBranchLanes, computeSaveStatus, connectionCanvasId, derivePortsForStep, extractMessage, flowNodeCardHeightForOutputs, flowNodeLayoutHeightForOutputs, flowNodeOutputCenterY, flowNodeOutputStackHeight, fromWorkflowConnectionDomain, fromWorkflowStepDomain, hasOtherPending, iconFor, indexValidationByConnectionId, indexValidationByStepId, indexValidationByTriggerId, inputPortId, isEntityDirty, mapHttpError, mtIconForStep, mtIconForTrigger, newClientMutationId, nextOperationId, nodeCanvasId, outputPortId, parseConnectionId, parseNodeId, parsePortId, parseTriggerOutputPortId, parseTriggerStartConnectionId, patchLayoutPosition, patchTriggerLayoutPosition, provideFlowplusFormDesignerAdapter, provideFlowplusWorkflow, provideFlowplusWorkflowNavigation, provideFlowplusWorkflowNavigationDefaults, readRecord, removeStepWithEdges, resolveTranslatable, resolveTriggerStartNodeKey, resolveTriggerStartStep, resolveTriggerStartStepId, resolveWorkflowTriggerKey, savingOrSaved, tempNodeCanvasId, toWorkflowConnectionDomain, toWorkflowDefinitionDomain, toWorkflowStepDomain, toWorkflowTriggerDomain, triggerCanvasId, triggerOutputPortId, triggerStartConnectionCanvasId, triggerStarterKindFor, unwrap, unwrapApiData, upsertConnection, upsertStep };
|
|
23170
23917
|
//# sourceMappingURL=masterteam-flowplus-workflow.mjs.map
|