(function() {
/**
* Data handler for whatsnew widget.
* @augments Help4.widget.help.Data
* @property {Function} _onDataRetrieved
* @property {boolean} _initialized
*/
Help4.widget.whatsnew.Data = class extends Help4.widget.help.Data {
static SCREEN_ID_EXTENSION = Help4.widget.help.CatalogueBackend.WHATSNEW_SCREEN_ID;
/**
* @override
* @param {Help4.widget.help.Data.Params} params
*/
constructor(params) {
/** @returns {Promise<void>} */
const onDataRetrieved = async () => this.isDestroyed() || await this._onHelpRetrieveReady();
super(params, {
statics: {
_onDataRetrieved: {init: onDataRetrieved, destroy: false},
_initialized: {init: false, destroy: false}
},
retrieve: {
/**
* override function from Help4.widget.help.Data as we do not want to load data twice
* instead we will listen and react to changes from help data; see below
* @returns {null}
*/
catalogues: () => {
// reset loaded information
this._cataloguesLoaded = null;
this._helpLoaded = null;
return null;
}
}
});
const {_onDataRetrieved} = this;
const helpWidget = Help4.widget.getInstance('help');
const {widget: {help: {data}}} = helpWidget.getContext();
data.addListener('dataRetrieved', _onDataRetrieved);
// get all data that exists already before we added our listener
// call only after constructor is done
setTimeout(async () => {
await _onDataRetrieved();
this._initialized = true;
}, 1);
}
/** @override */
destroy() {
const {_onDataRetrieved} = this;
const helpWidget = Help4.widget.getInstance('help');
const {widget: {help: {data} = {}} = {}} = helpWidget?.getContext() || {};
data && _onDataRetrieved && data.removeListener('dataRetrieved', _onDataRetrieved);
super.destroy();
}
/**
* @override
* @returns {Promise<void>}
*/
initialize() {
return new Help4.Promise(resolve => {
const check = () => {
this._initialized
? resolve()
: setTimeout(check, 100);
}
check();
});
}
/**
* @override
* @returns {Promise<void>}
*/
async update() {
this._cataloguesLoaded = null;
this._helpLoaded = null;
const {configuration: {core: {screenId}}} = this.__widget.getContext();
await this.waitCataloguesLoaded(screenId);
await this.waitHelpLoaded();
// fire this.help event again; to allow proper view update (timing issues)
this._fireEvent({type: 'dataChange', name: 'help', value: this.help});
}
/**
* @private
* @returns {Promise<void>}
*/
async _onHelpRetrieveReady() {
const helpWidget = Help4.widget.getInstance('help');
const {
widget: {help: {data}},
configuration: {core: {screenId}}
} = helpWidget.getContext();
await data.waitCataloguesLoaded(screenId);
if (this.isDestroyed()) return;
// copy data from help widget
this.catalogues = Help4.cloneValue(data.catalogues);
// mark catalogues for this screen as loaded
this._cataloguesLoaded = screenId;
// update help information
await this._retrieveHelp();
if (this.isDestroyed()) return;
// mark help for this screen as loaded
this._helpLoaded = screenId;
await this.updateCatalogue(); // handle WN tours
}
/**
* updates tour list based on catalogue from help widget
* see {@link Help4.widget.tourlist.Data#updateCatalogue}
* @returns {Promise<void>}
*/
async updateCatalogue() {
const {
tourlist: {Data},
help: {project: {WNTours}},
companionCore: {data: {Tour}}
} = Help4.widget;
const {__widget, catalogues} = this;
/**
* will get all tours from help catalogue in case they<br>
* - are not extended (EXT for tour completely overrides; therefore ignore extended tours)<br>
* - not filtered out by extension<br>
* - only whatsnew
* @param {Help4.widget.help.CatalogueProject} project
* @returns {boolean}
*/
const getTours = ({contextType: ct, _ext, _ignore, _whatsnew})=>
ct === 'TOUR' && _ext === undefined && !_ignore && !!_whatsnew;
const {
pub: {projects: pubProjects},
head: {projects: headProjects}
} = catalogues;
const {
pub: pubTours,
head: headTours
} = Data.getTours(__widget, getTours);
const pub = /** @type {Help4.widget.help.CatalogueProject[]} */ pubTours.map(projectId => pubProjects.find(({id}) => id === projectId));
const head = /** @type {Help4.widget.help.CatalogueProject[]} */ headTours.map(projectId => headProjects.find(({id}) => id === projectId));
// evaluate tour conditions
const promisePub = Tour.getFilteredTourProjects({whatsnew: true, catalogueKey: 'pub', projects: pub});
const promiseHead = Tour.getFilteredTourProjects({whatsnew: true, catalogueKey: 'head', projects: head});
Help4.Promise.all([promisePub, promiseHead]);
if (this.isDestroyed()) return;
const filteredPub = await promisePub;
const filteredHead = await promiseHead;
await WNTours.setData({pub: filteredPub, head: filteredHead});
}
/**
* disables unsupported features in whatsnew mode
* @override
* @returns {Promise<Help4.widget.help.ProjectTile[]>}
*/
async getHelpTiles() {
const tiles = /** @type {Help4.widget.help.ProjectTile[]} */ await super.getHelpTiles();
tiles.forEach(tile => {
if (tile.type === 'help') {
tile.instantHelp = false;
tile.callout = false;
}
});
return tiles;
}
}
})();