diff --git a/packages/omniscript/src/omniScriptAccess.ts b/packages/omniscript/src/omniScriptAccess.ts index 20bcc4db..792642cd 100644 --- a/packages/omniscript/src/omniScriptAccess.ts +++ b/packages/omniscript/src/omniScriptAccess.ts @@ -64,6 +64,9 @@ interface OmniScriptFindOptions { */ export class OmniScriptAccess { + private isOmniProcessSObjectExists?: boolean = undefined; + private isOmniScriptSObjectExists?: boolean = undefined; + constructor( private readonly salesforceService: SalesforceService, private readonly lookupService: SalesforceLookupService, @@ -71,6 +74,20 @@ export class OmniScriptAccess { ) { } + private async hasOmniProcessSObject() { + if (this.isOmniProcessSObjectExists === undefined) { + this.isOmniProcessSObjectExists = await this.schema.isSObjectDefined(OmniProcessRecord.SObjectType); + } + return this.isOmniProcessSObjectExists; + } + + private async hasOmniScriptSObject() { + if (this.isOmniScriptSObjectExists === undefined) { + this.isOmniScriptSObjectExists = await this.schema.isSObjectDefined(OmniScriptRecord.SObjectType); + } + return this.isOmniScriptSObjectExists; + } + /** * Filter OmniScripts based on specified criteria. This method searches across both * OmniProcess and OmniScript SObjects and returns matching records. @@ -106,11 +123,15 @@ export class OmniScriptAccess { public async filter(filter?: OmniScriptIdentifier, options?: OmniScriptFilterOptions): Promise; public async filter(filter?: OmniScriptIdentifier, options?: OmniScriptFilterOptions): Promise { const scripts: OmniScriptRecord[] = []; - for (const record of await this.queryOmniProcessRecords(filter)) { - scripts.push(OmniScriptRecord.fromProcess(record)); + if (await this.hasOmniProcessSObject()) { + for (const record of await this.queryOmniProcessRecords(filter)) { + scripts.push(OmniScriptRecord.fromProcess(record)); + } } - for (const record of await this.queryOmniScriptRecords(filter)) { - scripts.push(OmniScriptRecord.fromScript(record)); + if (await this.hasOmniScriptSObject()) { + for (const record of await this.queryOmniScriptRecords(filter)) { + scripts.push(OmniScriptRecord.fromScript(record)); + } } return options?.withElements ? this.attachElements(scripts) : scripts; } @@ -158,12 +179,12 @@ export class OmniScriptAccess { criteria.id = undefined; } - const processRecords = await this.queryOmniProcessRecords(id, { limit: 1 }); + const processRecords = await this.hasOmniProcessSObject() ? await this.queryOmniProcessRecords(id, { limit: 1 }) : []; if (processRecords.length) { scriptRecord = OmniScriptRecord.fromProcess(processRecords[0]); } - const scriptRecords = await this.queryOmniScriptRecords(id, { limit: 1 }); + const scriptRecords = await this.hasOmniScriptSObject() ? await this.queryOmniScriptRecords(id, { limit: 1 }) : []; if (scriptRecords.length) { scriptRecord = OmniScriptRecord.fromScript(scriptRecords[0]); } diff --git a/packages/salesforce/src/deploy/packageBuilder.ts b/packages/salesforce/src/deploy/packageBuilder.ts index 86a2e087..2e150004 100644 --- a/packages/salesforce/src/deploy/packageBuilder.ts +++ b/packages/salesforce/src/deploy/packageBuilder.ts @@ -943,4 +943,4 @@ export class SalesforcePackageBuilder { } }, 4); } -} +} \ No newline at end of file diff --git a/packages/vlocity-deploy/src/deploymentSpecs/vlocityCard.ts b/packages/vlocity-deploy/src/deploymentSpecs/vlocityCard.ts index 93f69aad..2f5e8a72 100644 --- a/packages/vlocity-deploy/src/deploymentSpecs/vlocityCard.ts +++ b/packages/vlocity-deploy/src/deploymentSpecs/vlocityCard.ts @@ -6,6 +6,7 @@ import { DatapackDeploymentRecord, DeploymentStatus } from '../datapackDeploymen import { forEachAsyncParallel, getErrorMessage, Iterable, Timer } from '@vlocode/util'; import { SalesforceDeployService, SalesforcePackage } from '@vlocode/salesforce'; import { FlexCardActivator } from '../flexCard/flexCardActivator'; +import { RecordActivator } from './recordActivator'; import { Container, Logger } from '@vlocode/core'; @deploymentSpec({ recordFilter: /^VlocityCard__c$/i }) @@ -13,6 +14,7 @@ export class VlocityUILayoutAndCards implements DatapackDeploymentSpec { public constructor( private readonly activator: FlexCardActivator, + private readonly recordActivator: RecordActivator, private readonly logger: Logger, private readonly container: Container, ) { } @@ -71,7 +73,13 @@ export class VlocityUILayoutAndCards implements DatapackDeploymentSpec { public async afterDeploy(event: DatapackDeploymentEvent) { const packages = new Array(); - + await this.recordActivator.activateRecords( + Iterable.filter( + event.getDeployedRecords('VlocityCard__c'), + record => record.value('CardType__c') !== 'flex' + ), + () => ({ Active__c: true }) + ); await forEachAsyncParallel( Iterable.filter( event.getDeployedRecords('VlocityCard__c'), diff --git a/packages/vlocity-deploy/src/flexCard/flexCardDefinition.ts b/packages/vlocity-deploy/src/flexCard/flexCardDefinition.ts index 55884e93..6ef48ec0 100644 --- a/packages/vlocity-deploy/src/flexCard/flexCardDefinition.ts +++ b/packages/vlocity-deploy/src/flexCard/flexCardDefinition.ts @@ -1,5 +1,5 @@ import { injectable } from "@vlocode/core"; -import { QueryBuilder, RecordFactory, SalesforceService } from "@vlocode/salesforce"; +import { QueryBuilder, RecordFactory, SalesforceSchemaService, SalesforceService } from "@vlocode/salesforce"; import { asString } from "@vlocode/util"; import { VlocityDatapack } from "@vlocode/vlocity"; @@ -21,27 +21,27 @@ export interface FlexCardDefinition { } interface OmniUiCardRecord { - Name: string; - Id: string; - AuthorName: string; - VersionNumber: number; - IsActive: boolean; - OmniUiCardType?: 'parent' | 'child'; - UniqueName?: string; - PropertySetConfig: string | object; - StylingConfiguration?: string; + name: string; + id: string; + authorName: string; + versionNumber: number; + isActive: boolean; + omniUiCardType?: 'parent' | 'child'; + uniqueName?: string; + propertySetConfig: string | object; + stylingConfiguration?: string; } interface VlocityCardRecord { - Name: string; - Id: string; - Author: string; - Active: boolean; - Version: number; - IsChildCard: boolean; - CardType: 'flex' | 'classic'; - Definition: string | object; - Styles?: string; + name: string; + id: string; + author: string; + active: boolean; + version: number; + isChildCard: boolean; + cardType: 'flex' | 'classic'; + definition: string | object; + styles?: string; } export namespace FlexCardDefinition { @@ -102,16 +102,16 @@ export namespace FlexCardDefinition { return { SObjectType: 'OmniUiCard', ActivationField: 'IsActive', - Name: record.Name, - Id: record.Id, - VersionNumber: record.VersionNumber, - AuthorName: record.AuthorName, - IsActive: record.IsActive === undefined ? true : record.IsActive, - IsChildCard: record.OmniUiCardType === 'child', + Name: record.name, + Id: record.id, + VersionNumber: record.versionNumber, + AuthorName: record.authorName, + IsActive: record.isActive === undefined ? true : record.isActive, + IsChildCard: record.omniUiCardType === 'child', Type: 'flex', - UniqueName: record.UniqueName, - PropertySetConfig: asString(record.PropertySetConfig), - StylingConfiguration: parseAsJsonString(record.StylingConfiguration), + UniqueName: record.uniqueName, + PropertySetConfig: asString(record.propertySetConfig), + StylingConfiguration: parseAsJsonString(record.stylingConfiguration), }; } @@ -119,15 +119,15 @@ export namespace FlexCardDefinition { return { SObjectType: '%vlocity_namespace%__VlocityCard__c', ActivationField: '%vlocity_namespace%__Active__c', - Name: record.Name, - Id: record.Id, - VersionNumber: record.Version, - AuthorName: record.Author, - IsActive: record.Active === undefined ? true : record.Active, - IsChildCard: record.IsChildCard, - Type: record.CardType, - PropertySetConfig: asString(record.Definition), - StylingConfiguration: parseAsJsonString(record.Styles) + Name: record.name, + Id: record.id, + VersionNumber: record.version, + AuthorName: record.author, + IsActive: record.active === undefined ? true : record.active, + IsChildCard: record.isChildCard, + Type: record.cardType, + PropertySetConfig: asString(record.definition), + StylingConfiguration: parseAsJsonString(record.styles) }; } @@ -156,7 +156,24 @@ export type FlexCardIdentifier = string | { name: string, isChildCard?: boolean, @injectable.singleton() export class FlexCardDefinitionAccess { - constructor(private readonly salesforceService: SalesforceService) { + private isOmniUiCardSObjectExists?: boolean = undefined; + private isVlocityCardSObjectExists?: boolean = undefined; + + constructor(private readonly salesforceService: SalesforceService, private readonly salesforceSchemaService: SalesforceSchemaService) { + } + + private async hasOmniUiCardSObject() { + if (this.isOmniUiCardSObjectExists === undefined) { + this.isOmniUiCardSObjectExists = await this.salesforceSchemaService.isSObjectDefined('OmniUiCard'); + } + return this.isOmniUiCardSObjectExists; + } + + private async hasVlocityCardSObject() { + if (this.isVlocityCardSObjectExists === undefined) { + this.isVlocityCardSObjectExists = await this.salesforceSchemaService.isSObjectDefined('%vlocity_namespace%__VlocityCard__c'); + } + return this.isVlocityCardSObjectExists; } /** @@ -174,11 +191,15 @@ export class FlexCardDefinitionAccess { */ public async getFlexCardDefinitions(criteria?: FlexCardIdentifier): Promise> { const cards: FlexCardDefinition[] = []; - for (const record of await this.queryOmniCardRecords(criteria)) { - cards.push(FlexCardDefinition.fromOmniCard(record)); + if (await this.hasOmniUiCardSObject()) { + for (const record of await this.queryOmniCardRecords(criteria)) { + cards.push(FlexCardDefinition.fromOmniCard(record)); + } } - for (const record of await this.queryVlocityCardRecords(criteria)) { - cards.push(FlexCardDefinition.fromVlocityCard(record)); + if (await this.hasVlocityCardSObject()) { + for (const record of await this.queryVlocityCardRecords(criteria)) { + cards.push(FlexCardDefinition.fromVlocityCard(record)); + } } const cardsByName = new Map(); for (const card of cards) { @@ -200,11 +221,15 @@ export class FlexCardDefinitionAccess { */ public async filterCardDefinitions(filter?: FlexCardIdentifier): Promise { const cards: FlexCardDefinition[] = []; - for (const record of await this.queryOmniCardRecords(filter)) { - cards.push(FlexCardDefinition.fromOmniCard(record)); + if (await this.hasOmniUiCardSObject()) { + for (const record of await this.queryOmniCardRecords(filter)) { + cards.push(FlexCardDefinition.fromOmniCard(record)); + } } - for (const record of await this.queryVlocityCardRecords(filter)) { - cards.push(FlexCardDefinition.fromVlocityCard(record)); + if (await this.hasVlocityCardSObject()) { + for (const record of await this.queryVlocityCardRecords(filter)) { + cards.push(FlexCardDefinition.fromVlocityCard(record)); + } } return cards; } @@ -218,16 +243,19 @@ export class FlexCardDefinitionAccess { * @throws Error when no FlexCard record is found for the provided identifier */ public async findCardDefinition(id: FlexCardIdentifier): Promise { - const omniCardRecords = await this.queryOmniCardRecords(id); - if (omniCardRecords.length) { - return FlexCardDefinition.fromOmniCard(omniCardRecords[0]); + if (await this.hasOmniUiCardSObject()) { + const omniCardRecords = await this.queryOmniCardRecords(id); + if (omniCardRecords.length) { + return FlexCardDefinition.fromOmniCard(omniCardRecords[0]); + } } - const vlocityCardRecords = await this.queryVlocityCardRecords(id); - if (vlocityCardRecords.length) { - return FlexCardDefinition.fromVlocityCard(vlocityCardRecords[0]); + if (await this.hasVlocityCardSObject()) { + const vlocityCardRecords = await this.queryVlocityCardRecords(id); + if (vlocityCardRecords.length) { + return FlexCardDefinition.fromVlocityCard(vlocityCardRecords[0]); + } } - throw new Error(`No FlexCard record found for ID: ${JSON.stringify(id)}`); } diff --git a/packages/vlocity-deploy/src/flexCard/flexCardLwcCompiler.ts b/packages/vlocity-deploy/src/flexCard/flexCardLwcCompiler.ts index 602d26bd..36dd9e0b 100644 --- a/packages/vlocity-deploy/src/flexCard/flexCardLwcCompiler.ts +++ b/packages/vlocity-deploy/src/flexCard/flexCardLwcCompiler.ts @@ -1,6 +1,6 @@ -import { SalesforceService, SalesforcePackage, LightningComponentBundle } from '@vlocode/salesforce'; -import { injectable, Logger } from '@vlocode/core'; +import { SalesforceService, SalesforcePackage, LightningComponentBundle, SalesforceLabels } from '@vlocode/salesforce'; +import { container, injectable, Logger } from '@vlocode/core'; import { VlocityNamespaceService } from '@vlocode/vlocity'; import { cache, Timer, XML } from '@vlocode/util'; import { FlexCardDesigner, FlexCardDesignerOptions } from './flexCardDesignerUtil'; @@ -71,8 +71,9 @@ export class FlexCardLwcCompiler { isStdRuntime: !!options?.useStandardRuntime, apiVersion: Number(options?.apiVersion ?? this.salesforceService.getApiVersion()), }); + await this.setCustomLabelsFromCardDefinition(card); const name = options?.lwcName ?? this.getLwcName(card); - const metaObject = this.getCardMeta(card); + const metaObject = this.getCardMeta(card); const files: Array<{ filepath: string, source: string @@ -132,6 +133,19 @@ export class FlexCardLwcCompiler { }; } + private async setCustomLabelsFromCardDefinition(cardDef) { + if (cardDef.Label) { + return; + } + + const labelRegex = /\{(Label\.[^}]+)\}/g; + const matches = [...JSON.stringify(cardDef).matchAll(labelRegex)].map(m => m[1].substring(6)); // Extract "Label.namespace.labelName" or "Label.labelName" + const labelKeys = Array.from(new Set(matches)); + const salesforceLabelsService = container.get(SalesforceLabels); + cardDef.Label = Object.fromEntries( + Object.entries(await salesforceLabelsService.getCustomLabels(labelKeys)).map(([key, label]) =>[key, label.value] + )); + } /** * Compile an OmniScript into a deployable Salesforce Tooling record * @param card Definition of the FlexCard to compile diff --git a/packages/vscode-extension/src/commands/datapacks/omniScriptGenerateLwc.ts b/packages/vscode-extension/src/commands/datapacks/omniScriptGenerateLwc.ts index 6113bb8c..ac021b31 100644 --- a/packages/vscode-extension/src/commands/datapacks/omniScriptGenerateLwc.ts +++ b/packages/vscode-extension/src/commands/datapacks/omniScriptGenerateLwc.ts @@ -22,9 +22,13 @@ export default class GenerateLwcCommand extends DatapackCommand { private async executeWithSelection(selectedFiles: vscode.Uri[]) : Promise { const datapacks = (await this.loadDatapacks(selectedFiles)) - .filter(datapack => datapack.datapackType === 'OmniScript' || datapack.datapackType === 'FlexCard'); + .filter( + datapack => datapack.datapackType === 'OmniScript' || + datapack.datapackType === 'FlexCard' || + (datapack.datapackType === 'VlocityCard' && datapack.data['%vlocity_namespace%__CardType__c'] === 'flex') + ); if (datapacks.length === 0) { - throw new Error('Selected file is not a Vlocity OmniScript DataPack'); + throw new Error('Selected file is not a Vlocity OmniScript or FlexCard DataPack'); } const outputFolder = await this.promptOutputPathSelection(); @@ -41,7 +45,7 @@ export default class GenerateLwcCommand extends DatapackCommand { const definition = await container.new(OmniScriptDefinitionGenerator).getScriptDefinitionFromDatapack(datapack); return container.new(OmniScriptLwcCompiler).compile(definition, options); } - if (datapack.datapackType === 'FlexCard') { + if (datapack.datapackType === 'FlexCard' || datapack.datapackType === 'VlocityCard') { const definition = FlexCardDefinition.fromDatapack(datapack); return container.new(FlexCardLwcCompiler).compile(definition, options); }