@memberjunction/ng-artifacts 5.40.1 → 5.41.0
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/lib/__tests__/interactive-form-apply.service.test.js +6 -1
- package/dist/lib/__tests__/interactive-form-apply.service.test.js.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +14 -2
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.js +165 -62
- package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/component-permission-evaluation.d.ts +19 -0
- package/dist/lib/components/plugins/component-permission-evaluation.d.ts.map +1 -0
- package/dist/lib/components/plugins/component-permission-evaluation.js +64 -0
- package/dist/lib/components/plugins/component-permission-evaluation.js.map +1 -0
- package/dist/lib/services/interactive-form-apply.service.d.ts +15 -0
- package/dist/lib/services/interactive-form-apply.service.d.ts.map +1 -1
- package/dist/lib/services/interactive-form-apply.service.js +91 -18
- package/dist/lib/services/interactive-form-apply.service.js.map +1 -1
- package/package.json +19 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-form-apply.service.js","sourceRoot":"","sources":["../../../src/lib/services/interactive-form-apply.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Apply-to-my-form service.\n *\n * When the form-aware artifact viewer's \"Apply to my form\" button fires\n * `applyFormRequested`, the host calls this service. It:\n * 1. Looks up the entity to confirm it's registered.\n * 2. Reads the current Active override for the (entity, user) pair via\n * the `Get Active Form For Entity` action.\n * 3. Shows a confirmation dialog explaining what's about to happen\n * (Create new vs. Modify existing → Pending).\n * 4. On confirmation, runs `Create Interactive Form` or\n * `Modify Interactive Form` accordingly.\n * 5. Surfaces success / failure via the notification service.\n *\n * The service centralizes the Create-vs-Modify decision so every host\n * (standalone artifact viewer in Explorer, chat conversation surfaces,\n * eventually the cockpit's chat-pane Apply flow) follows the same rules.\n */\nimport { Injectable, inject } from '@angular/core';\nimport { Metadata, LogError, type IMetadataProvider, type UserInfo } from '@memberjunction/core';\nimport { GraphQLActionClient, GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { MJDialogService } from '@memberjunction/ng-ui-components';\nimport type { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n/** Result of an apply attempt — surfaced to the caller for any post-apply UI. */\nexport interface InteractiveFormApplyResult {\n Success: boolean;\n /** Mode the server ran: 'create' / 'modify-new-version' / 'modify-in-place'. */\n Mode?: 'create' | 'modify-new-version' | 'modify-in-place';\n /** OverrideID the user can now reference. */\n OverrideID?: string;\n /** ComponentID that now holds the spec. */\n ComponentID?: string;\n /** Version string (e.g. '1.0.0' for create, '1.1.0' for modify-new). */\n Version?: string;\n Message?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class InteractiveFormApplyService {\n private readonly dialog = inject(MJDialogService);\n private readonly notifications = inject(MJNotificationService);\n\n /**\n * Confirm with the user and apply the spec. Routes to Create / Modify\n * automatically based on whether an Active override already exists.\n */\n public async ConfirmAndApply(\n spec: ComponentSpec,\n entityName: string,\n provider?: IMetadataProvider,\n ): Promise<InteractiveFormApplyResult> {\n const p = provider ?? Metadata.Provider;\n if (!p) {\n return this.fail('No metadata provider configured.');\n }\n const entity = p.EntityByName(entityName);\n if (!entity) {\n return this.fail(`Entity '${entityName}' is not registered.`);\n }\n const user = p.CurrentUser;\n if (!user) {\n return this.fail('No current user.');\n }\n const gqlProvider = p as unknown as GraphQLDataProvider;\n if (!gqlProvider || typeof (gqlProvider as { ExecuteGQL?: unknown }).ExecuteGQL !== 'function') {\n return this.fail('Action invocation requires a GraphQL provider.');\n }\n\n const client = new GraphQLActionClient(gqlProvider);\n\n // Step 1: detect existing state via Get Active Form For Entity.\n const activeResult = await this.runActionByName(client, 'Get Active Form For Entity', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n ]);\n if (!activeResult.Success) {\n return this.fail(`Could not check for existing override: ${activeResult.Message ?? 'unknown error'}`);\n }\n const payload = this.parseActiveResult(activeResult.Message);\n const hasExistingActive = !!payload?.Active?.OverrideID;\n\n // Step 2: confirm with the user.\n const proceed = await this.confirm(hasExistingActive, entityName, payload?.Active?.ComponentVersion);\n if (!proceed) {\n return { Success: false, Message: 'Cancelled by user.' };\n }\n\n // Step 3: run Create or Modify.\n const formName = (spec as unknown as { name?: string }).name ?? 'Custom Form';\n if (hasExistingActive) {\n const modifyResult = await this.runActionByName(client, 'Modify Interactive Form', [\n { Name: 'OverrideID', Value: payload!.Active!.OverrideID!, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n { Name: 'Notes', Value: `Applied from chat artifact at ${new Date().toISOString()}`, Type: 'Input' },\n ]);\n return this.summarize(modifyResult, 'modify', user);\n }\n const createResult = await this.runActionByName(client, 'Create Interactive Form', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n { Name: 'Name', Value: formName, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n ]);\n return this.summarize(createResult, 'create', user);\n }\n\n // ── internals ────────────────────────────────────────────────────────\n\n /**\n * Look up an action by name and run it. The actions module ships with\n * `__CreateInteractiveForm` / `__ModifyInteractiveForm` / etc. as their\n * DriverClass names but registers under the human-readable form name.\n * GraphQLActionClient.RunAction() takes the action ID; we fetch it by\n * name from the action metadata loaded on the provider.\n */\n private async runActionByName(\n client: GraphQLActionClient,\n actionName: string,\n params: Array<{ Name: string; Value: string; Type: 'Input' }>,\n ): Promise<{ Success: boolean; Message?: string; ResultCode?: string }> {\n try {\n // The action ID is required by RunAction. We look it up from the\n // action engine's cached metadata if available; otherwise we ask\n // the GraphQL provider directly.\n const actionId = await this.resolveActionIdByName(actionName);\n if (!actionId) {\n return { Success: false, Message: `Action '${actionName}' not found.` };\n }\n const result = await client.RunAction(actionId, params);\n // ActionResult.Result is the MJActionResultCodeEntity carrying\n // the string ResultCode; surface it on the failure path for\n // diagnostic messaging. ActionResult itself doesn't expose\n // ResultCode directly.\n const resultCode = (result as { Result?: { ResultCode?: string } })?.Result?.ResultCode;\n return {\n Success: !!result.Success,\n Message: result.Message ?? undefined,\n ResultCode: resultCode ?? undefined,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n LogError(`InteractiveFormApplyService.runActionByName(${actionName}): ${message}`);\n return { Success: false, Message: message };\n }\n }\n\n /**\n * Resolve an action ID by Name. Falls back to a direct RunView against\n * the Action entity when ActionEngine isn't loaded.\n */\n private async resolveActionIdByName(name: string): Promise<string | null> {\n try {\n // ActionEngine may not be initialised in the chat surface — query directly.\n const { RunView } = await import('@memberjunction/core');\n const rv = new RunView();\n const result = await rv.RunView<{ ID: string }>({\n EntityName: 'Actions',\n ExtraFilter: `Name='${name.replace(/'/g, \"''\")}'`,\n Fields: ['ID'],\n MaxRows: 1,\n ResultType: 'simple',\n });\n return result.Success ? (result.Results?.[0]?.ID ?? null) : null;\n } catch (err) {\n LogError(`InteractiveFormApplyService.resolveActionIdByName(${name}): ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n /** Show a confirmation dialog explaining what's about to happen. */\n private async confirm(\n hasExistingActive: boolean,\n entityName: string,\n currentVersion: string | null | undefined,\n ): Promise<boolean> {\n const content = hasExistingActive\n ? `You already have an active custom form for <strong>${escape(entityName)}</strong> (v${escape(currentVersion ?? '?')}). Applying this artifact will create a <strong>new Pending version</strong> — your live form stays active until you explicitly activate the new version in Form Builder.`\n : `This will create a custom form for <strong>${escape(entityName)}</strong> scoped to your user. Other users will continue to see the default form.`;\n // MJDialogAction surface is {text, primary?, themeColor?}; the\n // dialog's Result observable emits the entire clicked action (or\n // undefined for backdrop/X dismissal). Detect intent via the\n // `primary` flag — Apply / Create Pending are the primary actions;\n // Cancel and dismissal both resolve false.\n const ref = this.dialog.Open({\n title: hasExistingActive ? 'Apply as new Pending version?' : 'Apply this form?',\n content,\n width: 540,\n actions: [\n { text: hasExistingActive ? 'Create Pending' : 'Apply', primary: true, themeColor: 'primary' },\n { text: 'Cancel' },\n ],\n });\n return new Promise<boolean>(resolve => {\n ref.Result.subscribe((res: unknown) => {\n resolve((res as { primary?: boolean })?.primary === true);\n });\n });\n }\n\n private parseActiveResult(message: string | undefined): {\n Active?: { OverrideID?: string; ComponentVersion?: string };\n } | null {\n if (!message) return null;\n try {\n return JSON.parse(message) as { Active?: { OverrideID?: string; ComponentVersion?: string } };\n } catch {\n return null;\n }\n }\n\n private summarize(\n result: { Success: boolean; Message?: string; ResultCode?: string },\n kind: 'create' | 'modify',\n _user: UserInfo,\n ): InteractiveFormApplyResult {\n if (!result.Success) {\n this.notifications.CreateSimpleNotification(\n `Apply failed: ${result.Message ?? result.ResultCode ?? 'unknown error'}`,\n 'error', 5000,\n );\n return { Success: false, Message: result.Message };\n }\n let payload: Record<string, unknown> = {};\n try { payload = JSON.parse(result.Message ?? '{}'); } catch { /* best effort */ }\n const mode: InteractiveFormApplyResult['Mode'] = kind === 'create'\n ? 'create'\n : (payload.Mode === 'in-place' ? 'modify-in-place' : 'modify-new-version');\n const note = kind === 'create'\n ? 'Custom form is now active for your user.'\n : (mode === 'modify-in-place'\n ? 'Pending version updated. Activate it from Form Builder when ready.'\n : `Pending v${payload.Version ?? '?'} created. Activate it from Form Builder when ready.`);\n this.notifications.CreateSimpleNotification(note, 'success', 4000);\n return {\n Success: true,\n Mode: mode,\n OverrideID: payload.OverrideID as string | undefined,\n ComponentID: payload.ComponentID as string | undefined,\n Version: payload.Version as string | undefined,\n Message: result.Message,\n };\n }\n\n private fail(message: string): InteractiveFormApplyResult {\n this.notifications.CreateSimpleNotification(`Apply failed: ${message}`, 'error', 5000);\n return { Success: false, Message: message };\n }\n}\n\n/** Minimal HTML escape — the dialog content goes through `[innerHTML]` upstream. */\nfunction escape(s: string): string {\n return s.replace(/[&<>\"']/g, c => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c] ?? c));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"interactive-form-apply.service.js","sourceRoot":"","sources":["../../../src/lib/services/interactive-form-apply.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Apply-to-my-form service.\n *\n * When the form-aware artifact viewer's \"Apply to my form\" button fires\n * `applyFormRequested`, the host calls this service. It:\n * 1. Looks up the entity to confirm it's registered.\n * 2. Reads the current Active override for the (entity, user) pair via\n * the `Get Active Form For Entity` action.\n * 3. Shows a confirmation dialog explaining what's about to happen\n * (Create new vs. Modify existing → Pending).\n * 4. On confirmation, runs `Create Interactive Form` or\n * `Modify Interactive Form` accordingly.\n * 5. Surfaces success / failure via the notification service.\n *\n * The service centralizes the Create-vs-Modify decision so every host\n * (standalone artifact viewer in Explorer, chat conversation surfaces,\n * eventually the cockpit's chat-pane Apply flow) follows the same rules.\n */\nimport { Injectable, inject } from '@angular/core';\nimport { Metadata, LogError, type IMetadataProvider, type UserInfo } from '@memberjunction/core';\nimport { GraphQLActionClient, GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { MJDialogService } from '@memberjunction/ng-ui-components';\nimport type { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n/** Result of an apply attempt — surfaced to the caller for any post-apply UI. */\nexport interface InteractiveFormApplyResult {\n Success: boolean;\n /** Mode the server ran: 'create' / 'modify-new-version' / 'modify-in-place'. */\n Mode?: 'create' | 'modify-new-version' | 'modify-in-place';\n /** OverrideID the user can now reference. */\n OverrideID?: string;\n /** ComponentID that now holds the spec. */\n ComponentID?: string;\n /** Version string (e.g. '1.0.0' for create, '1.1.0' for modify-new). */\n Version?: string;\n Message?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class InteractiveFormApplyService {\n private readonly dialog = inject(MJDialogService);\n private readonly notifications = inject(MJNotificationService);\n\n /**\n * Confirm with the user and apply the spec. Routes to Create / Modify\n * automatically based on whether an Active override already exists.\n */\n public async ConfirmAndApply(\n spec: ComponentSpec,\n entityName: string,\n provider?: IMetadataProvider,\n ): Promise<InteractiveFormApplyResult> {\n const p = provider ?? Metadata.Provider;\n if (!p) {\n return this.fail('No metadata provider configured.');\n }\n const entity = p.EntityByName(entityName);\n if (!entity) {\n return this.fail(`Entity '${entityName}' is not registered.`);\n }\n const user = p.CurrentUser;\n if (!user) {\n return this.fail('No current user.');\n }\n const gqlProvider = p as unknown as GraphQLDataProvider;\n if (!gqlProvider || typeof (gqlProvider as { ExecuteGQL?: unknown }).ExecuteGQL !== 'function') {\n return this.fail('Action invocation requires a GraphQL provider.');\n }\n\n const client = new GraphQLActionClient(gqlProvider);\n\n // Step 1: detect existing state via Get Active Form For Entity.\n const activeResult = await this.runActionByName(client, 'Get Active Form For Entity', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n ]);\n if (!activeResult.Success) {\n return this.fail(`Could not check for existing override: ${activeResult.Message ?? 'unknown error'}`);\n }\n const payload = this.parseActiveResult(activeResult.Message);\n const hasExistingActive = !!payload?.Active?.OverrideID;\n\n // Step 2: confirm with the user.\n const proceed = await this.confirm(hasExistingActive, entityName, payload?.Active?.ComponentVersion);\n if (!proceed) {\n return { Success: false, Message: 'Cancelled by user.' };\n }\n\n // Step 3: run Create or Modify.\n const formName = (spec as unknown as { name?: string }).name ?? 'Custom Form';\n if (hasExistingActive) {\n // MJ's Modify operates on a Component *lineage* keyed by Name — the spec\n // name must match the existing Component across versions. A freshly\n // generated form usually has a different name, so align it to the existing\n // lineage (spec.name + the root `function` declaration the linter checks)\n // before modifying.\n if (payload?.Active?.ComponentName) {\n this.alignSpecToLineage(spec, payload.Active.ComponentName);\n }\n const modifyResult = await this.runActionByName(client, 'Modify Interactive Form', [\n { Name: 'OverrideID', Value: payload!.Active!.OverrideID!, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n { Name: 'Notes', Value: `Applied from chat artifact at ${new Date().toISOString()}`, Type: 'Input' },\n // A user \"Apply\" is a deliberate save, never an in-flight refinement —\n // so always snapshot a new restorable version rather than risk an\n // in-place overwrite. Passing an explicit bump makes this deterministic\n // across every source status (the 'in-place' default only applies to a\n // Pending source, which is the agent's iteration loop, not this path).\n // The prior version is demoted to Inactive on activation and stays in\n // Form Builder's version rail.\n { Name: 'VersionBumpKind', Value: 'minor', Type: 'Input' },\n ]);\n // Auto-activate the resulting version too. \"Apply to my form\" is an explicit\n // user action — they expect the applied form to go live, not sit as a Pending\n // draft the runtime variant switcher (Active variants only) can't reach. The\n // prior version is preserved as history and restorable from Form Builder.\n const modifyActivated = modifyResult.Success\n ? await this.activateCreatedOverride(client, modifyResult.Message)\n : false;\n return this.summarize(modifyResult, 'modify', user, modifyActivated);\n }\n const createResult = await this.runActionByName(client, 'Create Interactive Form', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n { Name: 'Name', Value: formName, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n ]);\n // Net-new \"Apply to my form\" is an explicit, confirmed user action, so we\n // activate the freshly-created (Pending) override immediately — the form goes\n // live in one step. Refining an EXISTING active form (the branch above) stays\n // Pending so a live form is never silently replaced.\n const activated = createResult.Success\n ? await this.activateCreatedOverride(client, createResult.Message)\n : false;\n return this.summarize(createResult, 'create', user, activated);\n }\n\n // ── internals ────────────────────────────────────────────────────────\n\n /**\n * Look up an action by name and run it. The actions module ships with\n * `__CreateInteractiveForm` / `__ModifyInteractiveForm` / etc. as their\n * DriverClass names but registers under the human-readable form name.\n * GraphQLActionClient.RunAction() takes the action ID; we fetch it by\n * name from the action metadata loaded on the provider.\n */\n private async runActionByName(\n client: GraphQLActionClient,\n actionName: string,\n params: Array<{ Name: string; Value: string; Type: 'Input' }>,\n ): Promise<{ Success: boolean; Message?: string; ResultCode?: string }> {\n try {\n // The action ID is required by RunAction. We look it up from the\n // action engine's cached metadata if available; otherwise we ask\n // the GraphQL provider directly.\n const actionId = await this.resolveActionIdByName(actionName);\n if (!actionId) {\n return { Success: false, Message: `Action '${actionName}' not found.` };\n }\n const result = await client.RunAction(actionId, params);\n // ActionResult.Result is the MJActionResultCodeEntity carrying\n // the string ResultCode; surface it on the failure path for\n // diagnostic messaging. ActionResult itself doesn't expose\n // ResultCode directly.\n const resultCode = (result as { Result?: { ResultCode?: string } })?.Result?.ResultCode;\n return {\n Success: !!result.Success,\n Message: result.Message ?? undefined,\n ResultCode: resultCode ?? undefined,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n LogError(`InteractiveFormApplyService.runActionByName(${actionName}): ${message}`);\n return { Success: false, Message: message };\n }\n }\n\n /**\n * Resolve an action ID by Name. Falls back to a direct RunView against\n * the Action entity when ActionEngine isn't loaded.\n */\n private async resolveActionIdByName(name: string): Promise<string | null> {\n try {\n // ActionEngine may not be initialised in the chat surface — query directly.\n // The core Action table is registered as the \"MJ: Actions\" entity.\n const { RunView } = await import('@memberjunction/core');\n const rv = new RunView();\n const result = await rv.RunView<{ ID: string }>({\n EntityName: 'MJ: Actions',\n ExtraFilter: `Name='${name.replace(/'/g, \"''\")}'`,\n Fields: ['ID'],\n MaxRows: 1,\n ResultType: 'simple',\n });\n return result.Success ? (result.Results?.[0]?.ID ?? null) : null;\n } catch (err) {\n LogError(`InteractiveFormApplyService.resolveActionIdByName(${name}): ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n /**\n * Activate the override produced by a successful Create so a net-new form goes\n * live immediately. Best-effort: on failure the form stays a Pending draft the\n * user can activate manually, so we log and return false rather than failing the\n * whole apply.\n */\n private async activateCreatedOverride(\n client: GraphQLActionClient,\n createMessage: string | undefined,\n ): Promise<boolean> {\n let overrideId: string | undefined;\n try {\n overrideId = (JSON.parse(createMessage ?? '{}') as { OverrideID?: string }).OverrideID;\n } catch {\n overrideId = undefined;\n }\n if (!overrideId) return false;\n const activateResult = await this.runActionByName(client, 'Activate Interactive Form Version', [\n { Name: 'OverrideID', Value: overrideId, Type: 'Input' },\n ]);\n if (!activateResult.Success) {\n LogError(`InteractiveFormApplyService: created override ${overrideId} but auto-activation failed: ${activateResult.Message ?? 'unknown error'}`);\n }\n return activateResult.Success;\n }\n\n /**\n * Align a freshly generated spec to an existing Component lineage before Modify.\n * MJ identifies a form lineage by Component Name and refuses to change it between\n * versions, so we rename the incoming spec — both `spec.name` and the root\n * `function` declaration in `spec.code` (the linter requires them to match) — to\n * the existing lineage name.\n */\n private alignSpecToLineage(spec: ComponentSpec, existingName: string): void {\n const s = spec as { name?: string; code?: string };\n const currentName = s.name;\n if (!currentName || currentName === existingName) return;\n s.name = existingName;\n if (typeof s.code === 'string' && s.code.length > 0) {\n const escaped = currentName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n s.code = s.code.replace(new RegExp(`function\\\\s+${escaped}\\\\s*\\\\(`), `function ${existingName}(`);\n }\n }\n\n /** Show a confirmation dialog explaining what's about to happen. */\n private async confirm(\n hasExistingActive: boolean,\n entityName: string,\n currentVersion: string | null | undefined,\n ): Promise<boolean> {\n // The dialog renders string content as plain text (not innerHTML), so use\n // plain text here — HTML tags would show raw.\n const content = hasExistingActive\n ? `You already have a custom form for \"${entityName}\" (v${currentVersion ?? '?'}). Applying this will create a new version and make it your active form. The previous version is preserved and can be restored from Form Builder.`\n : `This will create a custom form for \"${entityName}\" scoped to your user and make it active. Other users will continue to see the default form.`;\n // MJDialogAction surface is {text, primary?, themeColor?}; the\n // dialog's Result observable emits the entire clicked action (or\n // undefined for backdrop/X dismissal). Detect intent via the\n // `primary` flag — Apply / Create Pending are the primary actions;\n // Cancel and dismissal both resolve false.\n const ref = this.dialog.Open({\n title: 'Apply this form?',\n content,\n width: 540,\n actions: [\n { text: 'Apply', primary: true, themeColor: 'primary' },\n { text: 'Cancel' },\n ],\n });\n return new Promise<boolean>(resolve => {\n ref.Result.subscribe((res: unknown) => {\n resolve((res as { primary?: boolean })?.primary === true);\n });\n });\n }\n\n private parseActiveResult(message: string | undefined): {\n Active?: { OverrideID?: string; ComponentVersion?: string; ComponentName?: string };\n } | null {\n if (!message) return null;\n try {\n return JSON.parse(message) as { Active?: { OverrideID?: string; ComponentVersion?: string; ComponentName?: string } };\n } catch {\n return null;\n }\n }\n\n private summarize(\n result: { Success: boolean; Message?: string; ResultCode?: string },\n kind: 'create' | 'modify',\n _user: UserInfo,\n activated: boolean = false,\n ): InteractiveFormApplyResult {\n if (!result.Success) {\n this.notifications.CreateSimpleNotification(\n `Apply failed: ${result.Message ?? result.ResultCode ?? 'unknown error'}`,\n 'error', 5000,\n );\n return { Success: false, Message: result.Message };\n }\n let payload: Record<string, unknown> = {};\n try { payload = JSON.parse(result.Message ?? '{}'); } catch { /* best effort */ }\n const mode: InteractiveFormApplyResult['Mode'] = kind === 'create'\n ? 'create'\n : (payload.Mode === 'in-place' ? 'modify-in-place' : 'modify-new-version');\n const note = kind === 'create'\n ? (activated\n ? 'Custom form is now active for your user.'\n : 'Custom form created as a Pending draft — activate it from Form Builder to go live.')\n : (activated\n ? `Updated form is now active${payload.Version ? ` (v${payload.Version})` : ''} for your user.`\n : (mode === 'modify-in-place'\n ? 'Pending version updated. Activate it from Form Builder when ready.'\n : `Pending v${payload.Version ?? '?'} created. Activate it from Form Builder when ready.`));\n this.notifications.CreateSimpleNotification(note, 'success', 4000);\n return {\n Success: true,\n Mode: mode,\n OverrideID: payload.OverrideID as string | undefined,\n ComponentID: payload.ComponentID as string | undefined,\n Version: payload.Version as string | undefined,\n Message: result.Message,\n };\n }\n\n private fail(message: string): InteractiveFormApplyResult {\n this.notifications.CreateSimpleNotification(`Apply failed: ${message}`, 'error', 5000);\n return { Success: false, Message: message };\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-artifacts",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.41.0",
|
|
4
4
|
"description": "MemberJunction: Artifact viewer plugin system for rendering different artifact types (JSON, Code, Markdown, HTML, SVG, Components)",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"/dist"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "
|
|
11
|
+
"test": "vitest run",
|
|
12
12
|
"build": "ngc",
|
|
13
13
|
"test:watch": "vitest"
|
|
14
14
|
},
|
|
@@ -32,23 +32,23 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@angular/cdk": "21.1.3",
|
|
34
34
|
"@angular/forms": "21.1.3",
|
|
35
|
-
"@memberjunction/core": "5.
|
|
36
|
-
"@memberjunction/core-entities": "5.
|
|
37
|
-
"@memberjunction/global": "5.
|
|
38
|
-
"@memberjunction/graphql-dataprovider": "5.
|
|
39
|
-
"@memberjunction/interactive-component-types": "5.
|
|
40
|
-
"@memberjunction/ng-base-forms": "5.
|
|
41
|
-
"@memberjunction/ng-base-types": "5.
|
|
42
|
-
"@memberjunction/ng-code-editor": "5.
|
|
43
|
-
"@memberjunction/ng-export-service": "5.
|
|
44
|
-
"@memberjunction/ng-markdown": "5.
|
|
45
|
-
"@memberjunction/ng-notifications": "5.
|
|
46
|
-
"@memberjunction/ng-pagination": "5.
|
|
47
|
-
"@memberjunction/ng-query-viewer": "5.
|
|
48
|
-
"@memberjunction/ng-react": "5.
|
|
49
|
-
"@memberjunction/ng-shared-generic": "5.
|
|
50
|
-
"@memberjunction/ng-trees": "5.
|
|
51
|
-
"@memberjunction/ng-ui-components": "5.
|
|
35
|
+
"@memberjunction/core": "5.41.0",
|
|
36
|
+
"@memberjunction/core-entities": "5.41.0",
|
|
37
|
+
"@memberjunction/global": "5.41.0",
|
|
38
|
+
"@memberjunction/graphql-dataprovider": "5.41.0",
|
|
39
|
+
"@memberjunction/interactive-component-types": "5.41.0",
|
|
40
|
+
"@memberjunction/ng-base-forms": "5.41.0",
|
|
41
|
+
"@memberjunction/ng-base-types": "5.41.0",
|
|
42
|
+
"@memberjunction/ng-code-editor": "5.41.0",
|
|
43
|
+
"@memberjunction/ng-export-service": "5.41.0",
|
|
44
|
+
"@memberjunction/ng-markdown": "5.41.0",
|
|
45
|
+
"@memberjunction/ng-notifications": "5.41.0",
|
|
46
|
+
"@memberjunction/ng-pagination": "5.41.0",
|
|
47
|
+
"@memberjunction/ng-query-viewer": "5.41.0",
|
|
48
|
+
"@memberjunction/ng-react": "5.41.0",
|
|
49
|
+
"@memberjunction/ng-shared-generic": "5.41.0",
|
|
50
|
+
"@memberjunction/ng-trees": "5.41.0",
|
|
51
|
+
"@memberjunction/ng-ui-components": "5.41.0",
|
|
52
52
|
"mammoth": "^1.8.0",
|
|
53
53
|
"pdfjs-dist": "^4.10.38",
|
|
54
54
|
"rxjs": "^7.8.2",
|