diff --git a/src/core/js/new_module.js b/src/core/js/new_module.js index 0784b2e8129bc5ca35180ba4faa60d164d07b32e..40d47f0ae1a46a17347e2e81d8884ecc6387309d 100644 --- a/src/core/js/new_module.js +++ b/src/core/js/new_module.js @@ -25,7 +25,8 @@ /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ + * Add a special section to each entity one the current page where a thumbnail, + * a video preview or any other kind of preview for the entity is shown. * * @module new_module * @version 0.1 @@ -58,11 +59,23 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat return false; } + /** + * Create a preview for videos. + * + * @param {HTMLElement} entity + * @return {HTMLElement} a VIDEO element. + */ const _create_video_preview = function (entity) { var path = connection.getFileSystemPath() + getEntityPath(entity); return $(`<video control="controls"><source src="${path}"/></video>`)[0]; } + /** + * Create a preview for pictures. + * + * @param {HTMLElement} entity + * @return {HTMLElement} an IMG element. + */ const _create_picture_preview = function (entity) { var path = connection.getFileSystemPath() + getEntityPath(entity); return $(`<img class="entity-image-preview" style="max-width: 200px; max-height=140px;" src="${path}"/>`)[0]; @@ -71,7 +84,9 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat var fallback_preview = undefined; /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ + * Default creators. + * + * @member {Creator[]} */ const _default_creators = [ { // pictures @@ -94,18 +109,18 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat ]; + const previewShownEvent = new Event("new_module.preview.shown"); const previewReadyEvent = new Event("new_module.preview.ready"); - /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ - */ const _css_class_preview_container = "caosdb-f-new_module-container"; const _css_class_preview_container_resolvable = "caosdb-f-new_module-container-resolvable"; const _css_class_preview_container_button = "caosdb-f-new_module-container-button"; /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ + * Store the list of creators. + * + * @member {Creator[]} */ var _creators = []; @@ -280,7 +295,7 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat if (container.hasClass(_css_class_preview_container_resolvable)) { container.removeClass(_css_class_preview_container_resolvable); const preview = root_preview_creator(entity); - set_preview(entity, preview); + await set_preview(entity, preview); } } @@ -331,7 +346,32 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat }; /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ + * @type {Config} + * + * @property {string} version + * @property {string} fallback + * @property {Creator[]} creators + */ + + /** + * @type {Creator} + * + * @property {string} id + * @property {string|function} is_applicable - a function with one + * parameter (entity) which returns true iff this creator is applicable + * for the given entity. Note: This property can as well be a + * javascript string which evaluates to a function. + * + * @property {string|function} create - a function with one parameter + * (entity) which creates a preview for the given entity after + * is_applicable returned true. Note: This property can as well be a + * javascript string which evaluates to a function. + */ + + /** + * Configure the creators. + * + * @param {Config} config */ var configure = async function (config) { logger.debug("configure", config); @@ -339,10 +379,11 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat throw new Error("Wrong version in config."); } + fallback_preview = config.fallback || fallback_preview; + // append/load creators _creators.splice(0, _creators.length); for (let c of config.creators) { - // TODO check deps _creators.push({ id: c.id, is_applicable: typeof c.is_applicable === "function" ? c.is_applicable : eval(c.is_applicable), @@ -358,7 +399,13 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat /** - * TODO Please adhere to JSDoc standards: https://jsdoc.app/ + * Initialize this module. + * + * I.e. configure the list of creators and setup the scroll listener which + * triggers the root_preview_handler. + * + * @property {Config} [config] - an optional config. Per default, the + * configuration is fetched from the server. */ var init = async function (config) { logger.info("new_module initialized"); @@ -385,6 +432,7 @@ var new_module = function ($, logger, is_in_view_port, load_config, getEntityPat init_watcher: init_watcher, configure: configure, add_preview_container: add_preview_container, + root_preview_handler: root_preview_handler, _creators: _creators, _css_class_preview_container, _css_class_preview_container_button, diff --git a/test/core/js/modules/new_module.js.js b/test/core/js/modules/new_module.js.js index abef05720b1c0b1a409b0bf22f84f8f2db2ef0e0..774c355c1bcec115a4b9ff5642e0d03d40771de7 100644 --- a/test/core/js/modules/new_module.js.js +++ b/test/core/js/modules/new_module.js.js @@ -24,8 +24,12 @@ var new_module_test_suite = function ($, new_module, QUnit) { + const sleep = (ms) => { + return new Promise(res => setTimeout(res, ms)) + } + var test_config = { "version": 0.1, - "deps": ["getParents", "getEntityName"], + "fallback": "blablabla", "creators": [ { "id": "test.success", "is_applicable": "(entity) => getParents(entity).map(par => par.name).includes('TestPreviewRecordType') && getEntityName(entity) === 'TestPreviewRecord-success'", @@ -78,8 +82,41 @@ var new_module_test_suite = function ($, new_module, QUnit) { let name = "TestPreviewRecord-" + name_suffix; let entity_xml = `<Response><Record name="${name}"><Parent name='TestPreviewRecordType'/></Record></Response>`; let entity = (await transformation.transformEntities(str2xml(entity_xml)))[0]; - assert.equal(getEntityName(entity), name); - new_module.root_preview_handler(entity[0]); + assert.equal(getEntityName(entity), name, "correct name"); + var container = $(new_module.add_preview_container(entity)); + + assert.ok(container.hasClass(new_module._css_class_preview_container), `before has class ${new_module._css_class_preview_container}`); + assert.ok(container.hasClass(new_module._css_class_preview_container_resolvable), `before has class ${new_module._css_class_preview_container_resolvable}`); + + if (name_suffix === "load-forever"){ + new_module.root_preview_handler(entity); + await sleep(1000); + } else { + await new_module.root_preview_handler(entity); + } + + // ..._resolvable class removed + assert.ok(container.hasClass(new_module._css_class_preview_container), `after has class ${new_module._css_class_preview_container}`); + assert.notOk(container.hasClass(new_module._css_class_preview_container_resolvable), `after missing class ${new_module._css_class_preview_container_resolvable}`); + + + switch(name_suffix) { + case "fall-back": + assert.equal(container.text(), "blablabla"); + break; + case "error": + assert.equal(container.text(), "An error occured while loading this preview"); + break; + case "load-forever": + assert.equal(container.text(), "Please wait..."); + break; + case "success": + assert.equal(container.text(), "SUCCESS"); + break; + default: + assert.ok(false); + } + } });