@memberjunction/core-actions 6.2.0-edge.2 → 6.2.0-edge.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/dist/custom/ai/execute-agent.action.d.ts +10 -0
- package/dist/custom/ai/execute-agent.action.d.ts.map +1 -1
- package/dist/custom/ai/execute-agent.action.js +24 -1
- package/dist/custom/ai/execute-agent.action.js.map +1 -1
- package/dist/custom/ai/execute-ai-prompt.action.d.ts.map +1 -1
- package/dist/custom/ai/execute-ai-prompt.action.js +3 -0
- package/dist/custom/ai/execute-ai-prompt.action.js.map +1 -1
- package/dist/custom/ai/generate-image.action.d.ts +5 -2
- package/dist/custom/ai/generate-image.action.d.ts.map +1 -1
- package/dist/custom/ai/generate-image.action.js +18 -8
- package/dist/custom/ai/generate-image.action.js.map +1 -1
- package/dist/custom/ai/summarize-content.action.d.ts.map +1 -1
- package/dist/custom/ai/summarize-content.action.js +3 -0
- package/dist/custom/ai/summarize-content.action.js.map +1 -1
- package/dist/custom/data/run-adhoc-query.action.d.ts.map +1 -1
- package/dist/custom/data/run-adhoc-query.action.js +3 -0
- package/dist/custom/data/run-adhoc-query.action.js.map +1 -1
- package/dist/custom/interactive-forms/_shared.d.ts +113 -31
- package/dist/custom/interactive-forms/_shared.d.ts.map +1 -1
- package/dist/custom/interactive-forms/_shared.js +198 -74
- package/dist/custom/interactive-forms/_shared.js.map +1 -1
- package/dist/custom/interactive-forms/activate-form-contribution-version.action.d.ts +23 -0
- package/dist/custom/interactive-forms/activate-form-contribution-version.action.d.ts.map +1 -0
- package/dist/custom/interactive-forms/activate-form-contribution-version.action.js +151 -0
- package/dist/custom/interactive-forms/activate-form-contribution-version.action.js.map +1 -0
- package/dist/custom/interactive-forms/activate-interactive-form-version.action.d.ts +23 -7
- package/dist/custom/interactive-forms/activate-interactive-form-version.action.d.ts.map +1 -1
- package/dist/custom/interactive-forms/activate-interactive-form-version.action.js +114 -58
- package/dist/custom/interactive-forms/activate-interactive-form-version.action.js.map +1 -1
- package/dist/custom/interactive-forms/create-form-contribution.action.d.ts +35 -0
- package/dist/custom/interactive-forms/create-form-contribution.action.d.ts.map +1 -0
- package/dist/custom/interactive-forms/create-form-contribution.action.js +149 -0
- package/dist/custom/interactive-forms/create-form-contribution.action.js.map +1 -0
- package/dist/custom/interactive-forms/get-active-form-for-entity.action.d.ts +3 -0
- package/dist/custom/interactive-forms/get-active-form-for-entity.action.d.ts.map +1 -1
- package/dist/custom/interactive-forms/get-active-form-for-entity.action.js +5 -1
- package/dist/custom/interactive-forms/get-active-form-for-entity.action.js.map +1 -1
- package/dist/custom/interactive-forms/get-form-composition-for-entity.action.d.ts +59 -0
- package/dist/custom/interactive-forms/get-form-composition-for-entity.action.d.ts.map +1 -0
- package/dist/custom/interactive-forms/get-form-composition-for-entity.action.js +313 -0
- package/dist/custom/interactive-forms/get-form-composition-for-entity.action.js.map +1 -0
- package/dist/custom/interactive-forms/get-form-contributions-for-entity.action.d.ts +47 -0
- package/dist/custom/interactive-forms/get-form-contributions-for-entity.action.d.ts.map +1 -0
- package/dist/custom/interactive-forms/get-form-contributions-for-entity.action.js +115 -0
- package/dist/custom/interactive-forms/get-form-contributions-for-entity.action.js.map +1 -0
- package/dist/custom/interactive-forms/index.d.ts +5 -0
- package/dist/custom/interactive-forms/index.d.ts.map +1 -1
- package/dist/custom/interactive-forms/index.js +5 -0
- package/dist/custom/interactive-forms/index.js.map +1 -1
- package/dist/custom/interactive-forms/modify-form-contribution.action.d.ts +36 -0
- package/dist/custom/interactive-forms/modify-form-contribution.action.d.ts.map +1 -0
- package/dist/custom/interactive-forms/modify-form-contribution.action.js +181 -0
- package/dist/custom/interactive-forms/modify-form-contribution.action.js.map +1 -0
- package/dist/custom/interactive-forms/modify-interactive-form.action.d.ts +13 -11
- package/dist/custom/interactive-forms/modify-interactive-form.action.d.ts.map +1 -1
- package/dist/custom/interactive-forms/modify-interactive-form.action.js +65 -64
- package/dist/custom/interactive-forms/modify-interactive-form.action.js.map +1 -1
- package/dist/custom/interactive-forms/revert-interactive-form.action.d.ts +12 -0
- package/dist/custom/interactive-forms/revert-interactive-form.action.d.ts.map +1 -1
- package/dist/custom/interactive-forms/revert-interactive-form.action.js +29 -4
- package/dist/custom/interactive-forms/revert-interactive-form.action.js.map +1 -1
- package/package.json +42 -42
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-form-contribution.action.d.ts","sourceRoot":"","sources":["../../../src/custom/interactive-forms/create-form-contribution.action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAiBrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,4BAA6B,SAAQ,UAAU;cAExC,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiEvF;;;;OAIG;YACW,iBAAiB;IAwB/B,OAAO,CAAC,aAAa;CAkBxB;AAED,wBAAgB,gCAAgC,IAAI,IAAI,CAEvD"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseAction } from "@memberjunction/actions";
|
|
8
|
+
import { Metadata, LogError, RunView } from "@memberjunction/core";
|
|
9
|
+
import { EscapeSQLString, RegisterClass } from "@memberjunction/global";
|
|
10
|
+
import { AddOutput, Failure, GetPrecedenceParam, GetStringParam, InsertComponent, InsertContribution, LintFormPanelSpec, ParseSpecParam, ResolveContributionRegistration, WriteAtomically, } from "./_shared.js";
|
|
11
|
+
/**
|
|
12
|
+
* Create a net-new form contribution for the requesting user.
|
|
13
|
+
*
|
|
14
|
+
* Reads the registration intent from `spec.formContribution` (slot, key, claims,
|
|
15
|
+
* presentation, title). Writes a `MJ: Components` row (Type='Widget', v1.0.0, Draft)
|
|
16
|
+
* and a `MJ: Entity Form Contributions` row (Scope='User', Status='Pending').
|
|
17
|
+
* Activation is a separate step (`Activate Form Contribution Version`), which the
|
|
18
|
+
* "Add to my form" apply flow runs immediately after Create.
|
|
19
|
+
*
|
|
20
|
+
* **Security clamp — Scope.** This action *always* writes `Scope='User'`,
|
|
21
|
+
* `UserID=ctx.user.ID`. An agent cannot write Global or Role contributions that would
|
|
22
|
+
* change other users' forms. Promotion is a deliberate human act.
|
|
23
|
+
*
|
|
24
|
+
* `Precedence` is honored when supplied (the apply flow passes `incumbent + 1` after
|
|
25
|
+
* the user confirms replacing an installed contribution). It only ever affects the
|
|
26
|
+
* calling user's own form, so it is not clamped.
|
|
27
|
+
*
|
|
28
|
+
* **Atomicity.** The spec's claim is checked (INVALID_CLAIM) before anything is written, and
|
|
29
|
+
* the Component and row inserts run in one entity transaction, so a refused row leaves no
|
|
30
|
+
* Component behind.
|
|
31
|
+
*/
|
|
32
|
+
let CreateFormContributionAction = class CreateFormContributionAction extends BaseAction {
|
|
33
|
+
async InternalRunAction(params) {
|
|
34
|
+
try {
|
|
35
|
+
const inputs = this.extractInputs(params);
|
|
36
|
+
if ('error' in inputs)
|
|
37
|
+
return inputs.error;
|
|
38
|
+
const provider = params.Provider ?? Metadata.Provider;
|
|
39
|
+
if (!provider)
|
|
40
|
+
return Failure("NO_PROVIDER", "No metadata provider available.");
|
|
41
|
+
const user = params.ContextUser;
|
|
42
|
+
if (!user)
|
|
43
|
+
return Failure("NO_USER", "Action requires a ContextUser to clamp contribution scope.");
|
|
44
|
+
const entityInfo = provider.EntityByName(inputs.EntityName);
|
|
45
|
+
if (!entityInfo) {
|
|
46
|
+
return Failure("ENTITY_NOT_FOUND", `Entity '${inputs.EntityName}' is not registered with the active metadata provider.`);
|
|
47
|
+
}
|
|
48
|
+
// Lint before any persistence — fail-hard.
|
|
49
|
+
const lintFail = await LintFormPanelSpec(inputs.Spec, user);
|
|
50
|
+
if (lintFail)
|
|
51
|
+
return lintFail;
|
|
52
|
+
const registration = ResolveContributionRegistration(provider, inputs.Spec);
|
|
53
|
+
if ('error' in registration)
|
|
54
|
+
return registration.error;
|
|
55
|
+
// The duplicate check runs before the Component row is written, so a rejected
|
|
56
|
+
// create leaves nothing behind.
|
|
57
|
+
const writeKey = registration.WriteKey;
|
|
58
|
+
const keyCheck = writeKey
|
|
59
|
+
? await this.checkKeyAvailable(provider, user, entityInfo.ID, inputs.EntityName, writeKey)
|
|
60
|
+
: null;
|
|
61
|
+
if (keyCheck)
|
|
62
|
+
return keyCheck;
|
|
63
|
+
const written = await WriteAtomically(provider, async () => {
|
|
64
|
+
const componentInsert = await InsertComponent({
|
|
65
|
+
provider, user, spec: inputs.Spec, fallbackName: inputs.Name, description: inputs.Description,
|
|
66
|
+
version: "1.0.0", versionSequence: 1, componentStatus: 'Pending', componentType: 'Widget',
|
|
67
|
+
});
|
|
68
|
+
if ('error' in componentInsert)
|
|
69
|
+
return componentInsert;
|
|
70
|
+
const rowInsert = await InsertContribution({
|
|
71
|
+
provider, user, entityID: entityInfo.ID, componentID: componentInsert.id,
|
|
72
|
+
name: inputs.Name, description: inputs.Description, notes: inputs.Notes,
|
|
73
|
+
registration, status: 'Pending', precedence: inputs.Precedence,
|
|
74
|
+
});
|
|
75
|
+
if ('error' in rowInsert)
|
|
76
|
+
return rowInsert;
|
|
77
|
+
return { componentID: componentInsert.id, contributionID: rowInsert.id };
|
|
78
|
+
});
|
|
79
|
+
if ('error' in written)
|
|
80
|
+
return written.error;
|
|
81
|
+
AddOutput(params, "ContributionID", written.contributionID);
|
|
82
|
+
AddOutput(params, "ComponentID", written.componentID);
|
|
83
|
+
AddOutput(params, "Version", "1.0.0");
|
|
84
|
+
return {
|
|
85
|
+
Success: true, ResultCode: "SUCCESS",
|
|
86
|
+
Message: JSON.stringify({
|
|
87
|
+
ContributionID: written.contributionID, ComponentID: written.componentID, EntityName: entityInfo.Name,
|
|
88
|
+
ContributionKey: writeKey, Slot: registration.Contribution.slot,
|
|
89
|
+
Scope: "User", Status: "Pending", Version: "1.0.0",
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
95
|
+
LogError(`CreateFormContributionAction: ${message}`);
|
|
96
|
+
return Failure("UNEXPECTED_ERROR", message);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Rejects a key the caller already holds on this entity, and fails with QUERY_FAILED when
|
|
101
|
+
* that cannot be checked. Covers derived keys too, because the key it tests is the one the
|
|
102
|
+
* row will actually carry.
|
|
103
|
+
*/
|
|
104
|
+
async checkKeyAvailable(provider, user, entityID, entityName, writeKey) {
|
|
105
|
+
const rv = RunView.FromMetadataProvider(provider);
|
|
106
|
+
const dup = await rv.RunView({
|
|
107
|
+
EntityName: "MJ: Entity Form Contributions",
|
|
108
|
+
ExtraFilter: `EntityID='${EscapeSQLString(entityID)}' AND Scope='User' AND UserID='${EscapeSQLString(user.ID)}' AND ContributionKey='${EscapeSQLString(writeKey)}' AND Status IN ('Active','Pending')`,
|
|
109
|
+
Fields: ['ID', 'Status'], ResultType: 'simple', MaxRows: 1,
|
|
110
|
+
}, user);
|
|
111
|
+
if (!dup.Success) {
|
|
112
|
+
return Failure("QUERY_FAILED", `Duplicate-key lookup failed: ${dup.ErrorMessage ?? 'unknown error'}`);
|
|
113
|
+
}
|
|
114
|
+
if ((dup.Results ?? []).length > 0) {
|
|
115
|
+
const existing = dup.Results[0];
|
|
116
|
+
return Failure("ALREADY_EXISTS", `A ${existing.Status} User-scope contribution '${writeKey}' already exists on '${entityName}' (ContributionID=${existing.ID}). Use 'Modify Form Contribution' on it.`);
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
extractInputs(params) {
|
|
121
|
+
const entityName = GetStringParam(params, "EntityName");
|
|
122
|
+
if (!entityName)
|
|
123
|
+
return { error: Failure("MISSING_PARAMETER", "Parameter 'EntityName' is required.") };
|
|
124
|
+
const name = GetStringParam(params, "Name");
|
|
125
|
+
if (!name)
|
|
126
|
+
return { error: Failure("MISSING_PARAMETER", "Parameter 'Name' is required.") };
|
|
127
|
+
const specRaw = params.Params.find(x => x.Name?.trim().toLowerCase() === "spec")?.Value;
|
|
128
|
+
if (specRaw == null)
|
|
129
|
+
return { error: Failure("MISSING_PARAMETER", "Parameter 'Spec' is required.") };
|
|
130
|
+
const parsed = ParseSpecParam(specRaw);
|
|
131
|
+
if ('error' in parsed)
|
|
132
|
+
return { error: Failure("LINT_FAILED", `Spec is not valid JSON: ${parsed.error}`) };
|
|
133
|
+
return {
|
|
134
|
+
EntityName: entityName, Spec: parsed, Name: name,
|
|
135
|
+
Description: GetStringParam(params, "Description"), Notes: GetStringParam(params, "Notes"),
|
|
136
|
+
Precedence: GetPrecedenceParam(params) ?? 0,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
CreateFormContributionAction = __decorate([
|
|
141
|
+
RegisterClass(BaseAction, "__CreateFormContribution")
|
|
142
|
+
], CreateFormContributionAction);
|
|
143
|
+
export { CreateFormContributionAction };
|
|
144
|
+
export function LoadCreateFormContributionAction() {
|
|
145
|
+
if (false) {
|
|
146
|
+
const _ = CreateFormContributionAction;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=create-form-contribution.action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-form-contribution.action.js","sourceRoot":"","sources":["../../../src/custom/interactive-forms/create-form-contribution.action.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,9 @@ import { BaseAction } from "@memberjunction/actions";
|
|
|
13
13
|
* full variants list includes 'Pending' rows so the agent can recognize
|
|
14
14
|
* an in-flight refinement loop and reuse the Pending row instead of
|
|
15
15
|
* spawning a new one.
|
|
16
|
+
* - On an identity or permission entity only the caller's own `User` rows
|
|
17
|
+
* apply ({@link FormScopeAllowedOnEntity}), so a Role or Global form there
|
|
18
|
+
* is neither active nor listed.
|
|
16
19
|
*
|
|
17
20
|
* Output shape (JSON in `Message`, also surfaced as a `Result` output param):
|
|
18
21
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-active-form-for-entity.action.d.ts","sourceRoot":"","sources":["../../../src/custom/interactive-forms/get-active-form-for-entity.action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-active-form-for-entity.action.d.ts","sourceRoot":"","sources":["../../../src/custom/interactive-forms/get-active-form-for-entity.action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAMrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBACa,4BAA6B,SAAQ,UAAU;cAExC,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkKvF,OAAO,CAAC,cAAc;CAOzB;AAMD,qDAAqD;AACrD,wBAAgB,gCAAgC,IAAI,IAAI,CAIvD"}
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from "@memberjunction/actions";
|
|
8
8
|
import { Metadata, LogError, RunView } from "@memberjunction/core";
|
|
9
9
|
import { RegisterClass } from "@memberjunction/global";
|
|
10
|
+
import { FormScopeAllowedOnEntity } from "@memberjunction/core-entities";
|
|
10
11
|
/**
|
|
11
12
|
* Read-only action that returns the currently-resolved interactive-form
|
|
12
13
|
* override (if any) for the (entity, user) pair plus the full list of
|
|
@@ -20,6 +21,9 @@ import { RegisterClass } from "@memberjunction/global";
|
|
|
20
21
|
* full variants list includes 'Pending' rows so the agent can recognize
|
|
21
22
|
* an in-flight refinement loop and reuse the Pending row instead of
|
|
22
23
|
* spawning a new one.
|
|
24
|
+
* - On an identity or permission entity only the caller's own `User` rows
|
|
25
|
+
* apply ({@link FormScopeAllowedOnEntity}), so a Role or Global form there
|
|
26
|
+
* is neither active nor listed.
|
|
23
27
|
*
|
|
24
28
|
* Output shape (JSON in `Message`, also surfaced as a `Result` output param):
|
|
25
29
|
* ```
|
|
@@ -83,7 +87,7 @@ let GetActiveFormForEntityAction = class GetActiveFormForEntityAction extends Ba
|
|
|
83
87
|
if (!overrideResult.Success) {
|
|
84
88
|
return failure("QUERY_FAILED", `Override lookup failed: ${overrideResult.ErrorMessage ?? 'unknown error'}`);
|
|
85
89
|
}
|
|
86
|
-
const overrides = overrideResult.Results ?? [];
|
|
90
|
+
const overrides = (overrideResult.Results ?? []).filter(o => FormScopeAllowedOnEntity(entity.Name, o.Scope));
|
|
87
91
|
if (overrides.length === 0) {
|
|
88
92
|
const payload = { EntityName: entityName, Active: null, Variants: [] };
|
|
89
93
|
params.Params.push({ Name: "Result", Type: "Output", Value: payload });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-active-form-for-entity.action.js","sourceRoot":"","sources":["../../../src/custom/interactive-forms/get-active-form-for-entity.action.ts"],"names":[],"mappings":";;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-active-form-for-entity.action.js","sourceRoot":"","sources":["../../../src/custom/interactive-forms/get-active-form-for-entity.action.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ActionResultSimple, RunActionParams } from "@memberjunction/actions-base";
|
|
2
|
+
import { BaseAction } from "@memberjunction/actions";
|
|
3
|
+
/**
|
|
4
|
+
* Server-side composition of an entity's form, for agents with no browser snapshot.
|
|
5
|
+
*
|
|
6
|
+
* The client context is the better source for sections — it reports what a form actually
|
|
7
|
+
* rendered. This reproduces the part derivable from metadata alone: field sections by CodeGen
|
|
8
|
+
* rule, `DisplayInForm` related grids with their L1 inclusion, the caller's Active metadata
|
|
9
|
+
* contributions as the caller's form draws them, and the L3 rule count.
|
|
10
|
+
*
|
|
11
|
+
* Contributions are reported for the form this user sees: one row per key (highest
|
|
12
|
+
* `Precedence`, then the narrower scope, the browser's collapse rule), the panels the user hid
|
|
13
|
+
* marked `Hidden`, and on an identity or permission entity only the user's own rows
|
|
14
|
+
* ({@link FormScopeAllowedOnEntity}). Any failed query returns `QUERY_FAILED` rather than an
|
|
15
|
+
* answer built from a partial read. With metadata contributions switched off
|
|
16
|
+
* ({@link MetadataContributionsOn}) no row is read or listed, and `MetadataContributionsEnabled`
|
|
17
|
+
* is false.
|
|
18
|
+
*
|
|
19
|
+
* Compiled `BaseFormPanel` registrations live in the browser bundle, so they are absent and
|
|
20
|
+
* the `Note` says so.
|
|
21
|
+
*
|
|
22
|
+
* Slots are reported from `GENERATED_FORM_CONTRIBUTION_SLOTS` rather than guessed: what CodeGen
|
|
23
|
+
* emits is fixed, so the set is known for every generated form without opening one. A
|
|
24
|
+
* hand-written custom form can emit a different set, and the `Note` says so.
|
|
25
|
+
*/
|
|
26
|
+
export declare class GetFormCompositionForEntityAction extends BaseAction {
|
|
27
|
+
protected InternalRunAction(params: RunActionParams): Promise<ActionResultSimple>;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a full custom form renders for this caller.
|
|
30
|
+
*
|
|
31
|
+
* Mirrors `FormResolverService.pickActive` in the browser, which is what actually
|
|
32
|
+
* decides. A stored pick wins when the user may pick it: an Active form, or their own
|
|
33
|
+
* form set aside by a later apply ({@link IsSelectableFormOverride}). The explicit-default sentinel
|
|
34
|
+
* means they asked for the generated form, so no custom form renders at all. With no
|
|
35
|
+
* pick, or a pick naming a form that has gone or cannot be picked, the auto-pick rule
|
|
36
|
+
* applies: the first Active override, if there is one.
|
|
37
|
+
*/
|
|
38
|
+
private rendersFullCustomForm;
|
|
39
|
+
private readLayout;
|
|
40
|
+
/**
|
|
41
|
+
* Field sections, by CodeGen's own rule: a field marked `Category` groups under its
|
|
42
|
+
* category title, everything else lands in Details, and primary-key / `__mj_` audit
|
|
43
|
+
* fields form System Metadata, which CodeGen always emits last.
|
|
44
|
+
*/
|
|
45
|
+
private deriveSections;
|
|
46
|
+
/**
|
|
47
|
+
* Related grids the form shows, in the order it shows them. IS-A children are excluded:
|
|
48
|
+
* they share the parent's key and render as part of the record, not as a grid beside it.
|
|
49
|
+
*/
|
|
50
|
+
private deriveRelated;
|
|
51
|
+
/**
|
|
52
|
+
* Two relationships to the same entity (Bill-To and Ship-To, say) would collide on a
|
|
53
|
+
* bare entity-name key, so those are disambiguated by join field — matching what the
|
|
54
|
+
* form itself does.
|
|
55
|
+
*/
|
|
56
|
+
private relatedSectionKey;
|
|
57
|
+
}
|
|
58
|
+
export declare function LoadGetFormCompositionForEntityAction(): void;
|
|
59
|
+
//# sourceMappingURL=get-form-composition-for-entity.action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-form-composition-for-entity.action.d.ts","sourceRoot":"","sources":["../../../src/custom/interactive-forms/get-form-composition-for-entity.action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AA8DrD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,iCAAkC,SAAQ,UAAU;cAE7C,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAwFvF;;;;;;;;;OASG;IACH,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,UAAU;IAMlB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAqCtB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAerB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CAI5B;AA8GD,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseAction } from "@memberjunction/actions";
|
|
8
|
+
import { Metadata, LogError, RunView, ReadRelationshipInclusion } from "@memberjunction/core";
|
|
9
|
+
import { EscapeSQLString, RegisterClass, UUIDsEqual } from "@memberjunction/global";
|
|
10
|
+
import { FormContributionOutranks, FormPanelHideSettingKey, FormScopeAllowedOnEntity, IsSelectableFormOverride, ParseClaimedFieldNames, ParseHiddenFormPanelKeys, } from "@memberjunction/core-entities";
|
|
11
|
+
import { AddOutput, Failure, GetStringParam, ContributionScopeFilter, MetadataContributionsOn } from "./_shared.js";
|
|
12
|
+
import { FORM_VARIANT_EXPLICIT_DEFAULT, FormSectionCamelCase, FormVariantSettingKey, GENERATED_FORM_CONTRIBUTION_SLOTS, RelatedGridSectionKey, ResolveContributionWriteKey, StripJoinFieldBrackets, } from "@memberjunction/interactive-component-types/forms";
|
|
13
|
+
const SERVER_DERIVATION_NOTE = 'Derived from metadata on the server. Compiled BaseFormPanel contributions exist only in the ' +
|
|
14
|
+
'browser and are not listed. SlotsPresent is what CodeGen emits plus the container terminator; ' +
|
|
15
|
+
'a hand-written custom form can differ. Section keys and field names come from current field ' +
|
|
16
|
+
'metadata, which a ' +
|
|
17
|
+
'form generated earlier may not match. The client form context (AppContext.AdditionalContext.Form), ' +
|
|
18
|
+
'when present, lists the sections the open form actually draws and is authoritative for those.';
|
|
19
|
+
const FULL_CUSTOM_FORM_NOTE = 'A full custom entity form is the one THIS USER sees for this entity, and it renders the whole ' +
|
|
20
|
+
'body: no field sections, no related grids, no panel contribution and no slot. Propose a new ' +
|
|
21
|
+
'version of the full form rather than a panel. The container still supplies the toolbar, ' +
|
|
22
|
+
'Save/Delete, History and Record Changes, so the form body does not implement those. The user ' +
|
|
23
|
+
'can switch to the generated form from the form picker in the toolbar, and a panel becomes ' +
|
|
24
|
+
'possible again the moment they do.';
|
|
25
|
+
/**
|
|
26
|
+
* Server-side composition of an entity's form, for agents with no browser snapshot.
|
|
27
|
+
*
|
|
28
|
+
* The client context is the better source for sections — it reports what a form actually
|
|
29
|
+
* rendered. This reproduces the part derivable from metadata alone: field sections by CodeGen
|
|
30
|
+
* rule, `DisplayInForm` related grids with their L1 inclusion, the caller's Active metadata
|
|
31
|
+
* contributions as the caller's form draws them, and the L3 rule count.
|
|
32
|
+
*
|
|
33
|
+
* Contributions are reported for the form this user sees: one row per key (highest
|
|
34
|
+
* `Precedence`, then the narrower scope, the browser's collapse rule), the panels the user hid
|
|
35
|
+
* marked `Hidden`, and on an identity or permission entity only the user's own rows
|
|
36
|
+
* ({@link FormScopeAllowedOnEntity}). Any failed query returns `QUERY_FAILED` rather than an
|
|
37
|
+
* answer built from a partial read. With metadata contributions switched off
|
|
38
|
+
* ({@link MetadataContributionsOn}) no row is read or listed, and `MetadataContributionsEnabled`
|
|
39
|
+
* is false.
|
|
40
|
+
*
|
|
41
|
+
* Compiled `BaseFormPanel` registrations live in the browser bundle, so they are absent and
|
|
42
|
+
* the `Note` says so.
|
|
43
|
+
*
|
|
44
|
+
* Slots are reported from `GENERATED_FORM_CONTRIBUTION_SLOTS` rather than guessed: what CodeGen
|
|
45
|
+
* emits is fixed, so the set is known for every generated form without opening one. A
|
|
46
|
+
* hand-written custom form can emit a different set, and the `Note` says so.
|
|
47
|
+
*/
|
|
48
|
+
let GetFormCompositionForEntityAction = class GetFormCompositionForEntityAction extends BaseAction {
|
|
49
|
+
async InternalRunAction(params) {
|
|
50
|
+
try {
|
|
51
|
+
const entityName = GetStringParam(params, "EntityName");
|
|
52
|
+
if (!entityName)
|
|
53
|
+
return Failure("MISSING_PARAMETER", "Parameter 'EntityName' is required.");
|
|
54
|
+
const provider = params.Provider ?? Metadata.Provider;
|
|
55
|
+
if (!provider)
|
|
56
|
+
return Failure("NO_PROVIDER", "No metadata provider available.");
|
|
57
|
+
const user = params.ContextUser;
|
|
58
|
+
if (!user)
|
|
59
|
+
return Failure("NO_USER", "Action requires a ContextUser — contributions are user-scoped.");
|
|
60
|
+
const entity = provider.EntityByName(entityName);
|
|
61
|
+
if (!entity)
|
|
62
|
+
return Failure("ENTITY_NOT_FOUND", `Entity '${entityName}' is not registered.`);
|
|
63
|
+
const rv = RunView.FromMetadataProvider(provider);
|
|
64
|
+
const contributionsOn = await MetadataContributionsOn(provider, user);
|
|
65
|
+
const scope = ContributionScopeFilter(entity.ID, user);
|
|
66
|
+
const variantKey = FormVariantSettingKey(entity.Name);
|
|
67
|
+
const hideKey = FormPanelHideSettingKey(entity.Name);
|
|
68
|
+
const [rules, rows, overrides, settings] = await Promise.all([
|
|
69
|
+
rv.RunView({
|
|
70
|
+
EntityName: "MJ: Form Chrome Rules",
|
|
71
|
+
ExtraFilter: `EntityID='${EscapeSQLString(entity.ID)}'`,
|
|
72
|
+
Fields: ['ID'],
|
|
73
|
+
ResultType: 'simple',
|
|
74
|
+
}, user),
|
|
75
|
+
contributionsOn
|
|
76
|
+
? rv.RunView({
|
|
77
|
+
EntityName: "MJ: Entity Form Contributions",
|
|
78
|
+
ExtraFilter: `${scope} AND Status='Active'`,
|
|
79
|
+
Fields: ['ID', 'ContributionKey', 'Scope', 'Slot', 'Title', 'Name', 'Presentation', 'Precedence', 'Inclusion', 'SortKey',
|
|
80
|
+
'InSectionKey', 'SectionPosition', 'ReplacesFieldNames', 'ReplacesSectionKey', 'ReplacesSectionKeys',
|
|
81
|
+
'RelatedEntityID', 'RelatedEntity', 'RelatedJoinField'],
|
|
82
|
+
OrderBy: 'Precedence DESC, SortKey DESC',
|
|
83
|
+
ResultType: 'simple',
|
|
84
|
+
}, user)
|
|
85
|
+
: Promise.resolve(noRows()),
|
|
86
|
+
rv.RunView({
|
|
87
|
+
EntityName: "MJ: Entity Form Overrides",
|
|
88
|
+
ExtraFilter: `${scope} AND Status<>'Pending'`,
|
|
89
|
+
Fields: ['ID', 'Status', 'Scope'],
|
|
90
|
+
ResultType: 'simple',
|
|
91
|
+
}, user),
|
|
92
|
+
rv.RunView({
|
|
93
|
+
EntityName: "MJ: User Settings",
|
|
94
|
+
ExtraFilter: `UserID='${EscapeSQLString(user.ID)}' AND Setting IN ('${EscapeSQLString(variantKey)}','${EscapeSQLString(hideKey)}')`,
|
|
95
|
+
Fields: ['Setting', 'Value'],
|
|
96
|
+
ResultType: 'simple',
|
|
97
|
+
}, user),
|
|
98
|
+
]);
|
|
99
|
+
const failed = firstFailure([
|
|
100
|
+
["MJ: Form Chrome Rules", rules], ["MJ: Entity Form Contributions", rows],
|
|
101
|
+
["MJ: Entity Form Overrides", overrides], ["MJ: User Settings", settings],
|
|
102
|
+
]);
|
|
103
|
+
if (failed)
|
|
104
|
+
return Failure("QUERY_FAILED", failed);
|
|
105
|
+
// Which form the CALLER sees, not merely whether a custom one exists. They can
|
|
106
|
+
// pick any form on offer, the generated one included, and that pick is a
|
|
107
|
+
// per-user setting — reading only the override rows answered for a form the
|
|
108
|
+
// user may have switched away from, and refused a panel on the form they were
|
|
109
|
+
// looking at.
|
|
110
|
+
const offered = (overrides.Results ?? []).filter(o => FormScopeAllowedOnEntity(entity.Name, o.Scope));
|
|
111
|
+
const fullCustomForm = this.rendersFullCustomForm(offered, settingValue(settings.Results ?? [], variantKey));
|
|
112
|
+
const hidden = new Set(ParseHiddenFormPanelKeys(settingValue(settings.Results ?? [], hideKey)));
|
|
113
|
+
const applicable = (rows.Results ?? []).filter(r => FormScopeAllowedOnEntity(entity.Name, r.Scope));
|
|
114
|
+
const payload = {
|
|
115
|
+
Entity: entity.Name,
|
|
116
|
+
Layout: this.readLayout(entity),
|
|
117
|
+
FullCustomForm: fullCustomForm,
|
|
118
|
+
MetadataContributionsEnabled: contributionsOn,
|
|
119
|
+
Sections: fullCustomForm ? [] : this.deriveSections(entity),
|
|
120
|
+
Related: fullCustomForm ? [] : this.deriveRelated(entity),
|
|
121
|
+
Contributions: fullCustomForm ? [] : contributionsUserSees(applicable, hidden),
|
|
122
|
+
SlotsPresent: fullCustomForm ? [] : [...GENERATED_FORM_CONTRIBUTION_SLOTS],
|
|
123
|
+
ChromeRuleCount: (rules.Results ?? []).length,
|
|
124
|
+
Note: fullCustomForm ? FULL_CUSTOM_FORM_NOTE : SERVER_DERIVATION_NOTE,
|
|
125
|
+
};
|
|
126
|
+
AddOutput(params, "Result", payload);
|
|
127
|
+
return { Success: true, ResultCode: "SUCCESS", Message: JSON.stringify(payload) };
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
131
|
+
LogError(`GetFormCompositionForEntityAction: ${message}`);
|
|
132
|
+
return Failure("UNEXPECTED_ERROR", message);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Whether a full custom form renders for this caller.
|
|
137
|
+
*
|
|
138
|
+
* Mirrors `FormResolverService.pickActive` in the browser, which is what actually
|
|
139
|
+
* decides. A stored pick wins when the user may pick it: an Active form, or their own
|
|
140
|
+
* form set aside by a later apply ({@link IsSelectableFormOverride}). The explicit-default sentinel
|
|
141
|
+
* means they asked for the generated form, so no custom form renders at all. With no
|
|
142
|
+
* pick, or a pick naming a form that has gone or cannot be picked, the auto-pick rule
|
|
143
|
+
* applies: the first Active override, if there is one.
|
|
144
|
+
*/
|
|
145
|
+
rendersFullCustomForm(overrides, preference) {
|
|
146
|
+
const selected = (preference ?? '').trim();
|
|
147
|
+
if (selected === FORM_VARIANT_EXPLICIT_DEFAULT)
|
|
148
|
+
return false;
|
|
149
|
+
if (selected && overrides.some(o => IsSelectableFormOverride(o) && UUIDsEqual(o.ID, selected)))
|
|
150
|
+
return true;
|
|
151
|
+
return overrides.some(o => o.Status === 'Active');
|
|
152
|
+
}
|
|
153
|
+
readLayout(entity) {
|
|
154
|
+
const configured = entity
|
|
155
|
+
.ConfigurationObject?.UI?.Form?.Layout;
|
|
156
|
+
return configured === 'left-nav' ? 'left-nav' : 'accordion';
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Field sections, by CodeGen's own rule: a field marked `Category` groups under its
|
|
160
|
+
* category title, everything else lands in Details, and primary-key / `__mj_` audit
|
|
161
|
+
* fields form System Metadata, which CodeGen always emits last.
|
|
162
|
+
*/
|
|
163
|
+
deriveSections(entity) {
|
|
164
|
+
const fieldsByTitle = new Map();
|
|
165
|
+
const titleOrder = [];
|
|
166
|
+
const fileUnder = (title, field) => {
|
|
167
|
+
if (!fieldsByTitle.has(title)) {
|
|
168
|
+
fieldsByTitle.set(title, []);
|
|
169
|
+
titleOrder.push(title);
|
|
170
|
+
}
|
|
171
|
+
fieldsByTitle.get(title).push(field);
|
|
172
|
+
};
|
|
173
|
+
for (const f of entity.Fields) {
|
|
174
|
+
if (f.Name.startsWith('__mj_') || f.Name === 'ID')
|
|
175
|
+
continue;
|
|
176
|
+
const category = f.Category?.trim();
|
|
177
|
+
const type = f.GeneratedFormSectionType;
|
|
178
|
+
const field = { Name: f.Name, Label: f.DisplayNameOrName };
|
|
179
|
+
fileUnder(type === 'Category' && category ? category : 'Details', field);
|
|
180
|
+
}
|
|
181
|
+
const ordered = [
|
|
182
|
+
...(fieldsByTitle.has('Details') ? ['Details'] : []),
|
|
183
|
+
...titleOrder.filter(t => t !== 'Details'),
|
|
184
|
+
'System Metadata',
|
|
185
|
+
];
|
|
186
|
+
return ordered.map(title => ({
|
|
187
|
+
Key: FormSectionCamelCase(title),
|
|
188
|
+
Title: title,
|
|
189
|
+
Variant: 'default',
|
|
190
|
+
Group: null,
|
|
191
|
+
Hidden: false,
|
|
192
|
+
// Named so a contribution can stand in for one field rather than the whole
|
|
193
|
+
// section. Metadata-derived, so these are the entity's fields rather than the
|
|
194
|
+
// ones a form generated earlier actually draws — SERVER_DERIVATION_NOTE says so.
|
|
195
|
+
Fields: fieldsByTitle.get(title) ?? [],
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Related grids the form shows, in the order it shows them. IS-A children are excluded:
|
|
200
|
+
* they share the parent's key and render as part of the record, not as a grid beside it.
|
|
201
|
+
*/
|
|
202
|
+
deriveRelated(entity) {
|
|
203
|
+
const isaChildIDs = (entity.ChildEntities ?? []).map(c => c.ID);
|
|
204
|
+
const visible = entity.RelatedEntities
|
|
205
|
+
.filter(r => r.DisplayInForm && !isaChildIDs.some(id => UUIDsEqual(id, r.RelatedEntityID)))
|
|
206
|
+
.sort((a, b) => (a.Sequence ?? 999999) - (b.Sequence ?? 999999) || a.RelatedEntity.localeCompare(b.RelatedEntity));
|
|
207
|
+
return visible.map(r => ({
|
|
208
|
+
Entity: r.RelatedEntity,
|
|
209
|
+
JoinField: StripJoinFieldBrackets(r.RelatedEntityJoinField),
|
|
210
|
+
SectionKey: this.relatedSectionKey(r, visible),
|
|
211
|
+
Inclusion: ReadRelationshipInclusion(r.Configuration) ?? 'Auto',
|
|
212
|
+
Source: 'baked',
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Two relationships to the same entity (Bill-To and Ship-To, say) would collide on a
|
|
217
|
+
* bare entity-name key, so those are disambiguated by join field — matching what the
|
|
218
|
+
* form itself does.
|
|
219
|
+
*/
|
|
220
|
+
relatedSectionKey(rel, peers) {
|
|
221
|
+
const sharesRelatedEntity = peers.filter(p => UUIDsEqual(p.RelatedEntityID, rel.RelatedEntityID)).length > 1;
|
|
222
|
+
return RelatedGridSectionKey(rel.RelatedEntity, rel.RelatedEntityJoinField, sharesRelatedEntity);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
GetFormCompositionForEntityAction = __decorate([
|
|
226
|
+
RegisterClass(BaseAction, "__GetFormCompositionForEntity")
|
|
227
|
+
], GetFormCompositionForEntityAction);
|
|
228
|
+
export { GetFormCompositionForEntityAction };
|
|
229
|
+
/** An empty, successful result, which stands in for a query that is not run. */
|
|
230
|
+
function noRows() {
|
|
231
|
+
return { Success: true, Results: [], RowCount: 0, TotalRowCount: 0, ExecutionTime: 0, ErrorMessage: '' };
|
|
232
|
+
}
|
|
233
|
+
/** The message for the first failed query, or null when every query succeeded. */
|
|
234
|
+
function firstFailure(results) {
|
|
235
|
+
const failed = results.find(([, result]) => !result.Success);
|
|
236
|
+
if (!failed)
|
|
237
|
+
return null;
|
|
238
|
+
const [entityName, result] = failed;
|
|
239
|
+
return `Could not read the form's composition: the ${entityName} lookup failed (${result.ErrorMessage || 'unknown error'}).`;
|
|
240
|
+
}
|
|
241
|
+
/** The stored value of one setting. Keys are matched case-insensitively, as the database compares them. */
|
|
242
|
+
function settingValue(rows, key) {
|
|
243
|
+
return rows.find(r => (r.Setting ?? '').toLowerCase() === key.toLowerCase())?.Value ?? null;
|
|
244
|
+
}
|
|
245
|
+
/** The key a row is collapsed and hidden by, as the browser derives it; null for a row with none. */
|
|
246
|
+
function contributionRowKey(row) {
|
|
247
|
+
return ResolveContributionWriteKey({ contributionKey: row.ContributionKey ?? undefined, relatedJoinField: row.RelatedJoinField ?? undefined }, row.RelatedEntity ?? null);
|
|
248
|
+
}
|
|
249
|
+
/** One row per key, the one {@link FormContributionOutranks} picks; rows without a key never collapse. */
|
|
250
|
+
function collapseByKey(rows) {
|
|
251
|
+
const winners = new Map();
|
|
252
|
+
let unique = 0;
|
|
253
|
+
for (const row of rows) {
|
|
254
|
+
const key = contributionRowKey(row) ?? `__unique:${unique++}`;
|
|
255
|
+
const incumbent = winners.get(key);
|
|
256
|
+
if (!incumbent || FormContributionOutranks(row, incumbent))
|
|
257
|
+
winners.set(key, row);
|
|
258
|
+
}
|
|
259
|
+
return [...winners.values()];
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The contributions on the form this user sees.
|
|
263
|
+
*
|
|
264
|
+
* A panel the user hid is out of the collapse, so a row it outranked can draw in its place, as
|
|
265
|
+
* in the browser. The user's own rows are never hidden. A hidden panel whose key nothing else
|
|
266
|
+
* draws is still listed, marked `Hidden`, because it holds that key.
|
|
267
|
+
*/
|
|
268
|
+
function contributionsUserSees(rows, hiddenKeys) {
|
|
269
|
+
const isHidden = (row) => {
|
|
270
|
+
if (row.Scope === 'User')
|
|
271
|
+
return false;
|
|
272
|
+
const key = contributionRowKey(row);
|
|
273
|
+
return !!key && hiddenKeys.has(key);
|
|
274
|
+
};
|
|
275
|
+
const drawn = collapseByKey(rows.filter(r => !isHidden(r)));
|
|
276
|
+
const drawnKeys = new Set(drawn.map(contributionRowKey).filter((k) => !!k));
|
|
277
|
+
const hiddenOnly = collapseByKey(rows.filter(isHidden)).filter(r => !drawnKeys.has(contributionRowKey(r) ?? ''));
|
|
278
|
+
return [
|
|
279
|
+
...drawn.map(r => contributionSummary(r, r.Inclusion === 'None')),
|
|
280
|
+
...hiddenOnly.map(r => contributionSummary(r, true)),
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
function contributionSummary(r, hidden) {
|
|
284
|
+
return {
|
|
285
|
+
Key: contributionRowKey(r) ?? `contribution:${r.ID}`,
|
|
286
|
+
Slot: r.Slot,
|
|
287
|
+
Source: 'metadata',
|
|
288
|
+
Title: r.Title ?? r.Name ?? r.ID,
|
|
289
|
+
Presentation: r.Presentation,
|
|
290
|
+
Hidden: hidden,
|
|
291
|
+
Precedence: r.Precedence ?? 0,
|
|
292
|
+
SortKey: r.SortKey ?? 0,
|
|
293
|
+
InSectionKey: r.InSectionKey ?? undefined,
|
|
294
|
+
SectionPosition: r.SectionPosition ?? undefined,
|
|
295
|
+
FieldNames: ParseClaimedFieldNames(r.ReplacesFieldNames),
|
|
296
|
+
SectionKeys: replacedSectionKeyList(r),
|
|
297
|
+
ReplacesPlace: !!(r.ReplacesSectionKey || r.ReplacesSectionKeys || r.RelatedEntityID),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/** The blocks a row stands in for: the list when set, else the single key. */
|
|
301
|
+
function replacedSectionKeyList(row) {
|
|
302
|
+
const listed = ParseClaimedFieldNames(row.ReplacesSectionKeys);
|
|
303
|
+
if (listed.length > 0)
|
|
304
|
+
return listed;
|
|
305
|
+
const single = (row.ReplacesSectionKey ?? '').trim();
|
|
306
|
+
return single ? [single] : [];
|
|
307
|
+
}
|
|
308
|
+
export function LoadGetFormCompositionForEntityAction() {
|
|
309
|
+
if (false) {
|
|
310
|
+
const _ = GetFormCompositionForEntityAction;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=get-form-composition-for-entity.action.js.map
|