Name
sn_uibtk_api.Page
Description
No description available
Script
const Page = Class.create();
Page.prototype = {
initialize: function(noDomain) {
this.appRouteHander = new AppRoute();
this.addonEventMappingHandler = new UXAddOnEventMapping([], noDomain);
this.clientScriptHandler = new ClientScript();
this.componentDefinitionHandler = new ComponentDefinitions();
this.controllerHandler = new Controller();
this.dataBrokerDefinitionHandler = new DataBrokerDefinitions();
this.experienceHandler = new Experience();
this.macroponentHandler = new Macroponent();
this.presetHandler = new Preset();
this.controllerPresetHandler = new ControllerPreset();
this.screenApplicabilityHandler = new ScreenApplicability([], noDomain);
this.screenCollectionHandler = new ScreenCollection();
this.screenHandler = new Screen([], noDomain);
this.screenTestValueHandler = new ScreenTestValue();
this.uxEventHandler = new UXEvent();
this.uibTemplateHandler = new UIBTemplate();
this.extensionPointHandler = new ExtensionPoint();
this.libComponentHandler = new LibComponent();
},
createPage: function(
experienceId = false,
screen = false,
route = false,
applicabilities = [],
screenTestValues = {},
templateId = false,
mode = false
) {
let errorMessage = BuilderToolkitConstants.ERRORS.NO_EXPERIENCE_FOUND;
if (screen && route) {
const extensionPoint = this.extensionPointHandler.getRecordById(experienceId);
const experience = this.experienceHandler.getRecordById(experienceId);
const {
name: routeName
} = route;
const experienceData = {
appConfig: experience ? experience?.adminPanel : null,
parentMacroponent: extensionPoint?.appShell ?? route?.parentMacroponent ?? experience?.rootMacroponent,
extensionPoint: extensionPoint ? extensionPoint?.sysId : null
};
const screenCollectionId = this.screenCollectionHandler.createRecord({
name: routeName
});
errorMessage = BuilderToolkitConstants.ERRORS.FAILED_TO_CREATE_SCREEN_COLLECTION;
if (screenCollectionId) {
const routeId = this.appRouteHander.createRecord({
...route,
...experienceData,
screenType: screenCollectionId,
});
errorMessage = BuilderToolkitConstants.ERRORS.FAILED_TO_CREATE_APPROUTE;
if (routeId) {
const screenResult = this.screenHandler.create(experienceData, {
...screen,
screenType: screenCollectionId
}, [...(route.fields ?? []), ...(route.optionalParameters ?? [])], applicabilities, screenTestValues, templateId, mode);
if (typeof screenResult !== 'string') {
return {
...screenResult,
route: routeId,
screenCollection: screenCollectionId,
};
} else {
errorMessage = screenResult;
}
this.appRouteHander.deleteRecord({
sysId: routeId
});
}
this.screenCollectionHandler.deleteRecord({
sysId: screenCollectionId
});
}
}
return errorMessage;
},
createSubPage: function(screenGR, newMacroponentId, overrideFieldValues, scope, domain) {
const newScreenCollectionId = this.screenCollectionHandler.createRecord({
name: screenGR.screen_type.name.toString(),
sysScope: scope,
sysDomain: domain
});
const existingAppRoute = this.appRouteHander.getRecordsByQuery('screen_type=' + screenGR.screen_type.toString(), '', true);
if (!existingAppRoute || !existingAppRoute.next()) {
newScreenCollectionId ? this.screenCollectionHandler.deleteRecord({
sysId: newScreenCollectionId
}) : null;
return false;
}
const newRouteId = this.appRouteHander.copyRecord(existingAppRoute, null, {
...overrideFieldValues,
screenType: newScreenCollectionId,
sysScope: scope,
sysDomain: domain
});
const newScreenId = this.screenHandler.copyRecord(screenGR, null, {
...overrideFieldValues,
macroponent: newMacroponentId,
screenType: newScreenCollectionId,
sysScope: scope,
sysDomain: domain
});
if (!newScreenCollectionId || !newRouteId || !newScreenId) {
newScreenCollectionId ? this.screenCollectionHandler.deleteRecord({
sysId: newScreenCollectionId
}) : null;
newRouteId ? this.appRouteHander.deleteRecord({
sysId: newScreenCollectionId
}) : null;
newScreenId ? this.screenHandler.deleteRecord({
sysId: newScreenCollectionId
}) : null;
return false;
}
return newScreenId;
},
/**
* @param screenGR {GlideRecord} the screen record we are pulling from
* @param extensionPointGR {GlideRecord | null} the extension point record our route is are tied to
*/
getContextState: function(screenGR, macroponentGR, extensionPointGR) {
const pageRegistry = new BuilderToolkitAPIBase('sys_ux_page_registry').getRecordsByQuery(`admin_panel=${screenGR.getValue('app_config')}`, '', true);
const {
embeddedExtensionPointControllers,
extensionPointController
} = new Controller().getExtensionPointControllers(extensionPointGR);
const extensionPointValues = extensionPointGR ? this.extensionPointHandler.getValuesFromGlideRecord(extensionPointGR) : {};
if (pageRegistry && pageRegistry.next()) {
const parentMacroponent = !screenGR.parent_macroponent.nil() ? screenGR.parent_macroponent.getRefRecord() : null;
const parent = extensionPointGR ? this.getParentForExtensionPoint(extensionPointGR.getValue('app_shell')) : this.screenHandler.getParent(parentMacroponent, pageRegistry, screenGR);
const ancestor = extensionPointGR ? {} : this.screenHandler.getAncestor(pageRegistry, parentMacroponent?.getUniqueValue() ?? null);
const appPageProperties = [{"name":"appId", "value":pageRegistry.sys_id}].concat(new BuilderToolkitAPIBase('sys_ux_page_property', ['name', 'type', 'route', 'value']).getRecordsByQuery('page=' + pageRegistry.getUniqueValue()));
let theme = '{}';
// Adding try catch to protect us from any scriptable changes which are in global
try {
theme = UIBScriptables.getThemeForUIB(pageRegistry.getValue('admin_panel'), pageRegistry.getValue('parent_app'));
} catch (err) {
// No theme information is set for the page or parent app
}
return {
ancestor,
extensionPoint: extensionPointValues,
embeddedExtensionPointControllers: embeddedExtensionPointControllers ?? [],
extensionPointController,
extendsMacroponent: this.macroponentHandler.getRecordById(macroponentGR.getValue('extends')),
appPageProperties,
parent,
theme
};
}
return {
parent: extensionPointGR ? this.getParentForExtensionPoint(extensionPointGR.getValue('app_shell')) : {},
extensionPoint: extensionPointValues,
embeddedExtensionPointControllers: embeddedExtensionPointControllers ?? [],
extensionPointController,
extendsMacroponent: this.macroponentHandler.getRecordById(macroponentGR.getValue('extends'))
};
},
/**
* This is the full Page getter function when loading a UIB page
*
* @param screenSysId {string} the sys_id of the screen we are getting
*/
getUIBEditorPageObject: function(screenSysId) {
const screenGR = this.screenHandler.getRecordById(screenSysId, true);
if (screenGR) {
if (screenGR.macroponent.nil()) {
return gs.getMessage('No page definition has been found');
}
const macroponentGR = screenGR.macroponent.getRefRecord();
if (!macroponentGR.isValidRecord()) {
return gs.getMessage('No macroponent definition could be found');
}
const macroponentValues = this.macroponentHandler.getValuesFromGlideRecord(macroponentGR);
const {
mcpIds,
presetIds
} = this.macroponentHandler.getCompositionReferenceIds(this.macroponentHandler.parseJSON(macroponentGR.getValue('composition'), {
field: 'composition',
sysId: macroponentGR.getUniqueValue()
}));
const presetDefinitions = this.presetHandler.convertPresetDefinitions(this.presetHandler.getRecordsByQuery('sys_idIN' + presetIds));
const bundleMcpIds = (macroponentValues.bundles ?? []).map(bundle => bundle.definitionId);
const componentDefintions = this.componentDefinitionHandler.getComponentDefinitions([...bundleMcpIds, ...mcpIds, ...this.componentDefinitionHandler.ALWAYS_LOAD_COMPONENT_IDS], true);
const libComponentDefinitions = this.libComponentHandler.getComponentDefinitions(mcpIds);
const allComponentDefinitions = [...componentDefintions, ...libComponentDefinitions];
const allComponentMcpIds = allComponentDefinitions.map(({
macroponent
}) => macroponent.sysId);
const filteredMcpIds = mcpIds.filter((id) => !allComponentMcpIds.includes(id));
const macroponentDefinitions = this.macroponentHandler.getRecordsByQuery(`sys_idIN${filteredMcpIds}`);
const embeddedMacroponentDefinitions = (macroponentDefinitions ?? []).reduce((acc, def) => {
acc[def?.sysId] = def;
return acc;
}, {});
const addOnEventMappings = this.addonEventMappingHandler.getRecordsByQuery('parent_macroponent=' + macroponentGR.getUniqueValue());
// If we have no parent macroponent we're either broken or in extension point mode
let contextState = null;
let extensionPointControllerDefinitionIds = [];
const routeGR = this.appRouteHander.getRecordsByQuery('extension_point!=^screen_type=' + screenGR.getValue('screen_type'), 'name', true);
if (routeGR && routeGR.next()) {
contextState = this.getContextState(screenGR, macroponentGR, routeGR.extension_point.getRefRecord());
extensionPointControllerDefinitionIds = contextState.embeddedExtensionPointControllers.map(({
sysId
}) => sysId);
} else {
contextState = this.getContextState(screenGR, macroponentGR);
}
const dataBrokerDefinitions = this.dataBrokerDefinitionHandler.getMacroponentDataBrokerDefinitions(macroponentGR, contextState);
const allData = [].concat(macroponentValues?.data ?? [], contextState?.parent?.data ?? [], contextState?.ancestor?.data ?? []);
const controllersFromData = this.controllerHandler.getControllersFromData(allData);
const allControllerDefinitions = [...controllersFromData, ...this.controllerHandler.getRecordsByQuery(`sys_idIN${extensionPointControllerDefinitionIds}`)];
const controllerPresetIds = this.controllerHandler.getControllerPresetReferenceIds(allData);
const controllerPresetDefinitions = this.controllerPresetHandler.convertPresetDefinitions(this.controllerPresetHandler.getRecordsByQuery('sys_idIN' + controllerPresetIds));
const screen = this.screenHandler.getValuesFromGlideRecord(screenGR);
const parentHandledEventIds = contextState?.parent?.handledEvents?.reduce((acc, handler) => {
return acc.concat(handler?.handledEvents);
}, []);
const ancestorHandledEventIds = contextState?.ancestor?.handledEvents?.reduce((acc, handler) => {
return acc.concat(handler?.handledEvents);
}, []);
// Get all events for our MCP, dbs, components, controllers, parent mcp, and ancestor mcps, and public ones
const allUxEventIds = `
${this.getAllEventSysIdFromMacroponentValues(macroponentValues)},
${this.getEventsFromSupportingRecords(componentDefintions, allControllerDefinitions, dataBrokerDefinitions)},
${this.getEventsFromSupportingRecords([], [], [...(contextState?.parent?.data ?? []), ...(contextState?.ancestor?.data ?? [])])},
${(parentHandledEventIds ?? '')},
${(ancestorHandledEventIds ?? '')},
${(contextState?.extendsMacroponent?.handledEvents ?? '')},
${BuilderToolkitConstants.PUBLIC_MCP_EVENT_SYS_IDS}
`.replace(/\s/g, '');
// We need to query by the eventIds we got, and our DB definition operation query too and we'll do that long query as a new Query
const dataBrokerDefinitionOperationEventNameQuery = this.dataBrokerDefinitionHandler.getDataBrokerOperationsEventQuery(dataBrokerDefinitions);
const eventDefinitionRecords = new UXEvent().getRecordsByQuery(`sys_idIN${allUxEventIds}${dataBrokerDefinitionOperationEventNameQuery.replace('^OR', '^NQ')}`, 'name');
const eventDefinitions = [...eventDefinitionRecords, ...this.dataBrokerDefinitionHandler.getMutationDataBrokerDispatchedEvents(), ...this.dataBrokerDefinitionHandler.getRegularDataBrokerDispatchedEvents()];
const lastUpgradeGR = new GlideRecord('sys_upgrade_history');
lastUpgradeGR.orderByDesc('upgrade_started');
lastUpgradeGR.setLimit(1);
lastUpgradeGR.query();
const lastUpgradeDT = lastUpgradeGR.next() ? new GlideDateTime(lastUpgradeGR.getValue('upgrade_started')) : null;
const lastUpgrade = lastUpgradeDT ? lastUpgradeDT.getNumericValue() : null;
return {
screen,
macroponent: macroponentValues,
dataBrokerDefinitions,
componentDefinitions: [...allComponentDefinitions, ...this.componentDefinitionHandler.getPseudoComponents()],
screenTestValues: this.screenTestValueHandler.getRecordById(screenGR.getUniqueValue()),
clientScripts: this.clientScriptHandler.getRecordsByQuery('macroponent=' + macroponentGR.getUniqueValue()),
controllerDefinitions: this.controllerHandler.convertControllerDefinitions(allControllerDefinitions),
controllerPresetDefinitions,
presetDefinitions,
macroponentPublicHandledEvents: BuilderToolkitConstants.PUBLIC_MCP_EVENT_SYS_IDS,
contextState,
subroutes: this.screenHandler.getSubroutes(macroponentGR.getUniqueValue()),
addOnEventMappings,
eventDefinitions,
embeddedMacroponentDefinitions,
lastUpgrade
};
}
return false;
},
getEventsFromSupportingRecords: function(componentDefinitions = [], controllerDefinitions = [], dataBrokerDefinitions = {}) {
const componentEvents = componentDefinitions.reduce((acc, compDef) => {
return acc.concat(compDef?.macroponent?.dispatchedEvents?.split(',') ?? [],
compDef?.macroponent?.handledEvents?.split(',') ?? []);
}, []);
const controllerEvents = controllerDefinitions.reduce((acc, contDef) => {
return acc.concat(contDef?.macroponent?.dispatchedEvents?.split(',') ?? [],
contDef?.macroponent?.handledEvents?.split(',') ?? []);
}, []);
const dataBrokerEvents = Object.values(dataBrokerDefinitions).filter((dbDef) => dbDef?.macroponent).reduce((acc, dbDef) => {
return acc.concat(dbDef?.macroponent?.dispatchedEvents?.split(',') ?? [],
dbDef?.macroponent?.handledEvents?.split(',') ?? []);
}, []);
return [...componentEvents, ...controllerEvents, ...dataBrokerEvents].join(',');
},
getAllEventSysIdFromMacroponentValues: function(macroponentValues) {
const events = [...(macroponentValues?.handledEvents?.split(',') ?? []), ...(macroponentValues?.dispatchedEvents?.split(',') ?? [])];
return events.join(',');
},
/**
* @param pageRegistry {GlideRecord} the page registry record for the screen
*/
getParentForExtensionPoint: function(appShellSysId) {
const appShellGR = this.macroponentHandler.getRecordsByQuery(`sys_id=${appShellSysId}`, '');
if (appShellGR) {
return this.screenHandler.getUpstreamAttributes(appShellGR[0]);
}
return {};
},
type: 'Page'
};
Sys ID
b169b3bc9d231110f8772de6b52d4d7a