Source: widget/help/catalogues/UACP.js

(function() {
    /**
     * @typedef {Object} Help4.widget.help.catalogues.UACP.CatalogueProject
     * @property {string} alias - alternative project name
     * @property {string} appUrl - screen ID
     * @property {string} [cloneSrc] - clone source for compatibility with SEN backends; internally added
     * @property {Array} [conditions] - possible conditions
     * @property {Help4.widget.help.ContextTypes} contextType - HELP or TOUR
     * @property {string} editable
     * @property {string} environment
     * @property {string} id - project ID
     * @property {string} lastModifiedDate - last modification time
     * @property {string} locale - project language
     * @property {string} loio - project LOIO (LOgical Info Object)
     * @property {string|Object} [otherMetadata] - CMP specific information stored within UACP; JSON format
     * @property {string} product - context information
     * @property {string} shortDescription - context information
     * @property {string} state - DRAFT, ...
     * @property {string} system - context information
     * @property {string} title - title of the project
     * @property {string} version - context information
     * @property {Help4.widget.help.CatalogueTypes} [_catalogueType] - SEN, SEN2, UACP, ...; internally added
     * @property {Help4.widget.help.DataTypes} [_dataType] - SEN, UACP, ...; internally added
     */

    /**
     * @typedef {Object} Help4.widget.help.catalogues.UACP.CatalogueProjects
     * @property {Help4.widget.help.catalogues.UACP.CatalogueProject[]|null} pub - public catalogue projects for end-users
     */

    /**
     * this backend connector is able to handle UACP catalogue content for a RO model configuration
     */
    Help4.widget.help.catalogues.UACP = class {
        /** @returns {Help4.widget.help.DataTypes} */
        static getDataType() {
            return 'UACP';
        }

        /**
         * @param {Help4.typedef.SystemConfiguration} config - the system configuration
         * @returns {Promise<Help4.widget.help.catalogues.UACP.CatalogueProjects|null>}
         */
        static async load(config) {
            const {roModel, serviceUrl} = config.help;
            if (!serviceUrl || roModel !== Help4.SERVICE_LAYER.uacp) return null;

            const url = this._getUrl(config);
            /** @type {?Help4.widget.companionCore.UACP.CatalogueResponse} */
            const data = await Help4.widget.companionCore.UACP.doGetRequest(url);
            /** @type {Help4.widget.help.catalogues.UACP.CatalogueProject[]|null} */
            const pub = this._parse(data);
            return {pub};
        }

        /**
         * @param {?Help4.widget.companionCore.UACP.CatalogueResponse} serverResponse - the server response
         * @param {Help4.widget.help.CatalogueTypes} [catalogueType = 'UACP']
         * @returns {Help4.widget.help.catalogues.UACP.CatalogueProject[]|null}
         * @protected
         */
        static _parse(serverResponse, catalogueType = 'UACP') {
            /**
             * @param {Help4.widget.help.catalogues.UACP.CatalogueProject} project - catalogue project data
             * @returns {Help4.widget.help.catalogues.UACP.CatalogueProject}
             */
            const normalize = project => {
                project._catalogueType = catalogueType;
                project._dataType = 'UACP';

                if (project.otherMetadata) {
                    try {
                        project.otherMetadata = Help4.JSON.parse(project.otherMetadata);
                    } catch(e) {
                        project.otherMetadata = {};
                    }
                } else {
                    project.otherMetadata = {};
                }

                if (project.contextType === 'TOUR' && project.loio) project.cloneSrc = project.loio;  // for compatibility with SEN backends

                return setDefaults(project);
            }

            /**
             * @param {Help4.widget.help.catalogues.UACP.CatalogueProject} project - project data
             * @returns {Help4.widget.help.catalogues.UACP.CatalogueProject}
             */
            const setDefaults = project => {
                for (const [key, config] of Object.entries(Help4.PROJECT_DEFAULTS)) {
                    const id = (config.uacp || key).split('.');

                    let value = project;
                    while (id[0] && value) value = value[id.shift()];

                    project[key] = value || config.f;  // attention: only works for json type!!!
                }

                return project;
            }

            const {status, data} = serverResponse || {};
            return status === 'OK' && Help4.isArray(data) && data.length
                ? data.map(catalogueProject => normalize(catalogueProject))
                : null;
        }

        /**
         * @param {Help4.typedef.SystemConfiguration} config - the system configuration
         * @param {string[]} [appUrl] - enforce a certain appUrl
         * @returns {string}
         * @protected
         */
        static _getUrl(config, appUrl) {
            const {UACP} = Help4.widget.companionCore;
            const {WHATSNEW_SCREEN_ID} = Help4.widget.help.CatalogueBackend;

            const query = {};
            const {core: {screenId, system}, help: {serviceUrl, featureProfileUACP: profile}} = config;
            query.locale = UACP.getLanguages(config);
            query.appUrl = appUrl || [screenId, screenId + WHATSNEW_SCREEN_ID];
            query.system = typeof system === 'string' ? [system, null, ''] : [null, ''];
            if (profile) query.profile = profile;
            ['product', 'version', 'solution'].forEach(key => query[key] = config.core[key]);

            return serviceUrl + '/catalogue?' + encodeURIComponent(Help4.JSON.stringify(query));
        }
    }
})();