From 7c47c324b5eb728344e84620d9a1ca4fa0914ca8 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 20 Oct 2023 17:12:52 +0800 Subject: [PATCH 1/2] improved the `LoaderService` --- addon/.DS_Store | Bin 8196 -> 0 bytes addon/services/loader.js | 72 +++++++++++++++++++++++++++++---------- package.json | 2 +- 3 files changed, 55 insertions(+), 19 deletions(-) delete mode 100644 addon/.DS_Store diff --git a/addon/.DS_Store b/addon/.DS_Store deleted file mode 100644 index 245688bcaaf79b70b6dae8be8ea880e6a3254b82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMU2GIp6u#fIrFVt`)6$m0X6Zt~U@6c)sr@HAi z`b11DkwhiNpGP&Q;lV_sMib(LPiP`RL`i(n7~_kYnE2v@=g!@2XrV8XC<$|ux#ym9 z&$)NcneWV1U_P02|LiGu7I^O9L_JZZbhJ9I-q z7=bVXVFbbmgb@fMaDPOA&TP^6Jm9-ui&9=E|$M6E%ZaKkK zt`6%fCMFuTY-y^CHMKNP*2N|o8aFr8#acEuPEM-4qGr>!L&GQSF~^;jZXow4V2kFs zb$+%_wwGy_-y{ku^FH0o`=n|MBYpka;D9yaI^EV;b68*EkyCq#?Mj&$a;AU8wbNsc zH>{VABNSjQ{#7YOoeam&c zJ~QPJt%=vmAFf_5sfezAXnp-7TX%LmzW?C$MT?i{TA5bfpRqhEX`8)S%kW1B6W)mF z7?yKlh@$5B)>D?5QcIN!YLAl`Gq3BF%c_>Ih(zXU=T{j>C#_Ry%Ri&na4z?#j;vDk z5BL#-e&l}F5GxwNOr$!pmh;0x-kvh4mtt*Qq*m1vyvHM#`_GhH$Qn+1vjF+NL9T;)P#>gK}id!S?T))DPiM=}$o_}E6 zbZC3w-LC3LWKhUk4Z}3ZiK@zFdSqXulk3;`kT;r0nFq22xxBoK^Wb)pT&%RquzYuB zvPVqnmXomv&2&2?sCiAiR^F8$sA~BfY>9JfIa|$|*>={&2ARRKY?{5yF0wb-W%eQa zlzqXzX4lv^>;}8Veqz6}KiS_XLNPd0lwm0

CAUVFNZ|E85Y4-PnUp^r8;~7{oE0 zz$l)^Nu0u2Okfhv;v8PU1-yut@CM$(+qi^x@G(BeReXuB@GWlQd)&g$_zl0~52ZjU zQ5GqSl~u}WWxZ0b(04x3lzhGnNj~2zZ8W;=89@1x`-Z2Sx?8?Pckj{m{;&D+U5Ut$ z(z2!H6)S7jZD`!QEj|Mx3A;SfZbxtc+F4K!KpWiWxoDHAq(yrP)#mB>GDP3Wm$*x&T>;l5PWFM}LMs#;an z;C_z)3Ol+x#7n?@&sb4w$LKmvmuNz7O47iDx}Y2<8kFNiXZ|pxag0=jO*}`ZBqa&8 X|NKJ$y*}n&b;I*NJpTg_K7idnn79}D diff --git a/addon/services/loader.js b/addon/services/loader.js index b133265..557aa69 100644 --- a/addon/services/loader.js +++ b/addon/services/loader.js @@ -2,31 +2,55 @@ import Service from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { later } from '@ember/runloop'; +/** + * Service for managing loading overlays. + * + * @class LoaderService + * @extends Service + */ export default class LoaderService extends Service { + /** + * Tracks the routes that have been loaded. + * + * @type {Array} + * @tracked + */ @tracked routesLoaded = []; + /** + * Shows the loader based on a condition. + * + * @param {String|HTMLElement} target - The loader target. + * @param {Object} options - Options for controlling the loader. + * @param {Function|null} condition - The condition to evaluate. + */ showOnCondition(target, options = {}, condition = null) { - const { loadingMessage, opacity } = options; - if (typeof condition === 'function') { condition = condition(); } if (condition) { - this.showLoader(target, loadingMessage, opacity); + this.showLoader(target, options); } } - showOnInitialTransition(transition, target, loadingMessage = 'Loading...', opacity = 0.1) { + /** + * Shows loader during the initial route transition. + * + * @param {Object} transition - The Ember.js transition object. + * @param {String|HTMLElement} target - The loader target. + * @param {Object} options - Options for controlling the loader. + */ + showOnInitialTransition(transition, target, options = { loadingMessage: 'Loading...', opacity: 0.1 }) { const route = transition.to.name; const isSameRoute = transition.from ? transition.to.name === transition.from.name : false; if (!this.routesLoaded.includes(route) || !isSameRoute) { - if (document.querySelectorAll(`.overloader`).length > 0) { + if (document.querySelectorAll('.overloader').length > 0) { return; } - this.showLoader(target, loadingMessage, opacity); + this.showLoader(target, options); transition.finally(() => { this.removeLoader(target); @@ -39,20 +63,25 @@ export default class LoaderService extends Service { /** * Creates an HTML element node for a loading overlay with a message. * - * @param {String|HTMLElement} targetSelector - * @param {String} loadingMessage - * @return {HTMLElement} loader + * @param {String|HTMLElement} targetSelector - The loader target. + * @param {Object} options - Options for controlling the loader. + * @returns {HTMLElement} - The loader element. */ - showLoader(targetSelector, loadingMessage = 'Loading...', opacity = 0.1) { + showLoader(targetSelector, options = {}) { let target = typeof targetSelector === 'string' ? document.querySelector(targetSelector) : targetSelector; if (!target) { target = document.body; } + const loadingMessage = typeof options.loadingMessage === 'string' ? options.loadingMessage : 'Loading...'; + const opacity = typeof options.opacity === 'number' ? options.opacity : 0.1; const isDarkMode = document.body.dataset.theme ? document.body.dataset.theme === 'dark' : true; + const preserveTargetPosition = options.preserveTargetPosition === true; - target.style.position = 'relative'; + if (!preserveTargetPosition) { + target.style.position = 'relative'; + } let loader = document.createElement('div'); loader.classList.add('overloader'); @@ -71,15 +100,21 @@ export default class LoaderService extends Service { return loader; } - show(loadingMessage = 'Loading...', opacity = 0.1) { - return this.showLoader(document.body, loadingMessage, opacity); + /** + * Shows a loader on the document body. + * + * @param {Object} options - Options for controlling the loader. + * @returns {HTMLElement} - The loader element. + */ + show(options = { loadingMessage: 'Loading...', opacity: 0.1 }) { + return this.showLoader(document.body, options); } /** - * Creates an HTML element node for a loading overlay with a message. + * Removes a loader from a target. * - * @param {String|HTMLElement} targetSelector - * @return {Service} this + * @param {String|HTMLElement} targetSelector - The loader target. + * @returns {Service} - The current service instance. */ removeLoader(targetSelector) { let target = typeof targetSelector === 'string' ? document.querySelector(targetSelector) : targetSelector; @@ -114,9 +149,10 @@ export default class LoaderService extends Service { } /** - * Removes the all loader instances. + * Removes all loader instances after a delay. * - * @return {Service} this + * @param {Number} delay - The delay in milliseconds. + * @returns {Service} - The current service instance. */ remove(delay = 0) { const loaders = document.querySelectorAll(`.overloader`); diff --git a/package.json b/package.json index d17ff88..b55250b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/ember-core", - "version": "0.1.5", + "version": "0.1.6", "description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.", "keywords": [ "fleetbase-core", From 650f986d32b2e6a65177506aadf535473ec63261 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 27 Oct 2023 04:00:29 +0800 Subject: [PATCH 2/2] Added engine service share injection utility, as well as minor updates to the universe service --- addon/services/universe.js | 8 ++++++++ addon/utils/inject-engine-service.js | 15 +++++++++++++++ app/utils/inject-engine-service.js | 1 + tests/unit/utils/inject-engine-service-test.js | 10 ++++++++++ 4 files changed, 34 insertions(+) create mode 100644 addon/utils/inject-engine-service.js create mode 100644 app/utils/inject-engine-service.js create mode 100644 tests/unit/utils/inject-engine-service-test.js diff --git a/addon/services/universe.js b/addon/services/universe.js index ae2551a..fecaca8 100644 --- a/addon/services/universe.js +++ b/addon/services/universe.js @@ -447,6 +447,14 @@ export default class UniverseService extends Service.extend(Evented) { // create menu item const menuItem = this._createMenuItem(title, route, options); + // register menu item + if (!this[internalRegistryName]) { + this[internalRegistryName] = { + menuItems: [], + menuPanels: [], + }; + } + // register menu item this[internalRegistryName].menuItems.pushObject(menuItem); diff --git a/addon/utils/inject-engine-service.js b/addon/utils/inject-engine-service.js new file mode 100644 index 0000000..3d4a21f --- /dev/null +++ b/addon/utils/inject-engine-service.js @@ -0,0 +1,15 @@ +import { getOwner } from '@ember/application'; + +export default function injectEngineService(target, engineName, serviceName, key = null) { + const owner = getOwner(target); + const universe = owner.lookup('service:universe'); + const service = universe.getServiceFromEngine(engineName, serviceName); + const effectiveServiceName = key || serviceName; + + Object.defineProperty(target, effectiveServiceName, { + value: service, + writable: false, + configurable: true, + enumerable: true, + }); +} diff --git a/app/utils/inject-engine-service.js b/app/utils/inject-engine-service.js new file mode 100644 index 0000000..8a3fead --- /dev/null +++ b/app/utils/inject-engine-service.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/ember-core/utils/inject-engine-service'; diff --git a/tests/unit/utils/inject-engine-service-test.js b/tests/unit/utils/inject-engine-service-test.js new file mode 100644 index 0000000..5c2b9b5 --- /dev/null +++ b/tests/unit/utils/inject-engine-service-test.js @@ -0,0 +1,10 @@ +import injectEngineService from 'dummy/utils/inject-engine-service'; +import { module, test } from 'qunit'; + +module('Unit | Utility | inject-engine-service', function () { + // TODO: Replace this with your real tests. + test('it works', function (assert) { + let result = injectEngineService(); + assert.ok(result); + }); +});