mirror of
https://github.com/fleetbase/fleetbase.git
synced 2025-12-19 14:18:57 +00:00
refactor of universe and lazy loading fix contd.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="px-4 py-2.5">
|
||||
{{#if this.isLoading}}
|
||||
{{#if this.loadBlogPosts.isRunning}}
|
||||
<Spinner />
|
||||
{{else}}
|
||||
<ul class="space-y-2">
|
||||
|
||||
@@ -1,28 +1,42 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { isArray } from '@ember/array';
|
||||
import { storageFor } from 'ember-local-storage';
|
||||
import { add, isPast } from 'date-fns';
|
||||
import { task } from 'ember-concurrency';
|
||||
|
||||
export default class FleetbaseBlogComponent extends Component {
|
||||
@storageFor('local-cache') localCache;
|
||||
@service fetch;
|
||||
@tracked posts = [];
|
||||
@tracked isLoading = false;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.loadBlogPosts();
|
||||
this.loadBlogPosts.perform();
|
||||
}
|
||||
|
||||
@action loadBlogPosts() {
|
||||
this.isLoading = true;
|
||||
@task *loadBlogPosts() {
|
||||
// Check if cached data and expiration are available
|
||||
const cachedData = this.localCache.get('fleetbase-blog-data');
|
||||
const expiration = this.localCache.get('fleetbase-blog-data-expiration');
|
||||
|
||||
return this.fetch
|
||||
.get('lookup/fleetbase-blog')
|
||||
.then((response) => {
|
||||
this.posts = response;
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
// Check if the cached data is still valid
|
||||
if (cachedData && isArray(cachedData) && expiration && !isPast(new Date(expiration))) {
|
||||
// Use cached data
|
||||
this.posts = cachedData;
|
||||
} else {
|
||||
// Fetch new data
|
||||
try {
|
||||
const data = yield this.fetch.get('lookup/fleetbase-blog');
|
||||
this.posts = isArray(data) ? data : [];
|
||||
if (data) {
|
||||
this.localCache.set('fleetbase-blog-data', data);
|
||||
this.localCache.set('fleetbase-blog-data-expiration', add(new Date(), { hours: 6 }));
|
||||
}
|
||||
} catch (err) {
|
||||
debug('Failed to load blog: ' + err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export default class GithubCardComponent extends Component {
|
||||
this.data = cachedData;
|
||||
} else {
|
||||
// Fetch new data
|
||||
const response = yield fetch('https://api.github.com/repos/fleetbase/fleetbase');
|
||||
const response = yield fetch('https://api.github.com/repos/fleetbase/fleetbase', { cache: 'default' });
|
||||
if (response.ok) {
|
||||
this.data = yield response.json();
|
||||
this.localCache.set('fleetbase-github-data', this.data);
|
||||
@@ -72,7 +72,7 @@ export default class GithubCardComponent extends Component {
|
||||
this.tags = cachedTags;
|
||||
} else {
|
||||
// Fetch new tags
|
||||
const response = yield fetch('https://api.github.com/repos/fleetbase/fleetbase/tags');
|
||||
const response = yield fetch('https://api.github.com/repos/fleetbase/fleetbase/tags', { cache: 'default' });
|
||||
if (response.ok) {
|
||||
this.tags = yield response.json();
|
||||
this.localCache.set('fleetbase-github-tags', this.tags);
|
||||
|
||||
7
console/app/controllers/virtual.js
Normal file
7
console/app/controllers/virtual.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class VirtualController extends Controller {
|
||||
@tracked view;
|
||||
queryParams = ['view'];
|
||||
}
|
||||
@@ -40,5 +40,5 @@ export function initialize(application) {
|
||||
|
||||
export default {
|
||||
name: 'load-intl-polyfills',
|
||||
initialize
|
||||
initialize,
|
||||
};
|
||||
|
||||
@@ -14,17 +14,18 @@ import { debug } from '@ember/debug';
|
||||
*/
|
||||
export function initialize(application) {
|
||||
const startTime = performance.now();
|
||||
debug('[Initializer:load-runtime-config] Loading runtime configuration...');
|
||||
debug('[Runtime Config] Loading runtime configuration...');
|
||||
|
||||
// Defer readiness until config is loaded
|
||||
application.deferReadiness();
|
||||
(async () => {
|
||||
try {
|
||||
await loadRuntimeConfig();
|
||||
debug(`[Initializer:load-runtime-config] Runtime config loaded in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
const endTime = performance.now();
|
||||
debug(`[Runtime Config] Runtime config loaded in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
application.advanceReadiness();
|
||||
} catch (error) {
|
||||
console.error('[Initializer:load-runtime-config] Failed to load runtime config:', error);
|
||||
console.error('[Runtime Config] Failed to load runtime config:', error);
|
||||
// Still advance readiness to prevent hanging
|
||||
application.advanceReadiness();
|
||||
}
|
||||
|
||||
@@ -3,31 +3,31 @@ import { debug } from '@ember/debug';
|
||||
|
||||
/**
|
||||
* Apply Router Fix Instance Initializer
|
||||
*
|
||||
*
|
||||
* Applies the Fleetbase router refresh bug fix patch.
|
||||
* This patches the Ember router to handle dynamic segments correctly
|
||||
* when refreshing routes with query parameters.
|
||||
*
|
||||
*
|
||||
* Runs as an instance-initializer because it needs access to the
|
||||
* application instance and router service.
|
||||
*
|
||||
*
|
||||
* Bug: https://github.com/emberjs/ember.js/issues/19260
|
||||
*
|
||||
*
|
||||
* @export
|
||||
* @param {ApplicationInstance} appInstance
|
||||
*/
|
||||
export function initialize(appInstance) {
|
||||
const startTime = performance.now();
|
||||
debug('[InstanceInitializer:apply-router-fix] Applying router refresh bug fix...');
|
||||
|
||||
debug('[Initializing Router Patch] Applying router refresh bug fix...');
|
||||
|
||||
try {
|
||||
const application = appInstance.application;
|
||||
applyRouterFix(application);
|
||||
|
||||
|
||||
const endTime = performance.now();
|
||||
debug(`[InstanceInitializer:apply-router-fix] Router fix applied in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
debug(`[Initializing Router Patch] Router fix applied in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
} catch (error) {
|
||||
console.error('[InstanceInitializer:apply-router-fix] Failed to apply router fix:', error);
|
||||
console.error('[Initializing Router Patch] Failed to apply router fix:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +35,5 @@ export default {
|
||||
name: 'apply-router-fix',
|
||||
initialize,
|
||||
// Run before extension loading to ensure router is patched early
|
||||
before: 'load-extensions'
|
||||
before: 'load-extensions',
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { debug } from '@ember/debug';
|
||||
|
||||
/**
|
||||
* Create console-specific registries
|
||||
* Runs after extensions are loaded
|
||||
@@ -5,8 +7,8 @@
|
||||
export function initialize(appInstance) {
|
||||
const registryService = appInstance.lookup('service:universe/registry-service');
|
||||
|
||||
console.log('[initialize-registries] Creating console registries...');
|
||||
|
||||
debug('[Initializing Registries] Creating console registries...');
|
||||
|
||||
// Create console-specific registries
|
||||
registryService.createRegistries(['@fleetbase/console', 'auth:login']);
|
||||
}
|
||||
@@ -14,5 +16,5 @@ export function initialize(appInstance) {
|
||||
export default {
|
||||
name: 'initialize-registries',
|
||||
after: 'load-extensions',
|
||||
initialize
|
||||
initialize,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Widget } from '@fleetbase/ember-core/contracts';
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons';
|
||||
import { debug } from '@ember/debug';
|
||||
|
||||
/**
|
||||
* Register dashboard and widgets for FleetbaseConsole
|
||||
@@ -8,7 +9,7 @@ import { faGithub } from '@fortawesome/free-brands-svg-icons';
|
||||
export function initialize(appInstance) {
|
||||
const widgetService = appInstance.lookup('service:universe/widget-service');
|
||||
|
||||
console.log('[initialize-widgets] Registering console dashboard and widgets...');
|
||||
debug('[Initializing Widgets] Registering console dashboard and widgets...');
|
||||
|
||||
// Register the console dashboard
|
||||
widgetService.registerDashboard('dashboard');
|
||||
|
||||
@@ -17,6 +17,5 @@ export async function initialize(appInstance) {
|
||||
|
||||
export default {
|
||||
name: 'load-extensions',
|
||||
initialize
|
||||
initialize,
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,5 @@ export async function initialize(appInstance) {
|
||||
export default {
|
||||
name: 'setup-extensions',
|
||||
after: ['load-extensions', 'initialize-registries', 'initialize-widgets'],
|
||||
initialize
|
||||
initialize,
|
||||
};
|
||||
|
||||
|
||||
@@ -96,10 +96,7 @@ export default class ApplicationRoute extends Route {
|
||||
* @memberof ApplicationRoute
|
||||
*/
|
||||
afterModel() {
|
||||
if (!this.session.isAuthenticated) {
|
||||
console.log('boot loader removed');
|
||||
removeBootLoader();
|
||||
}
|
||||
if (!this.session.isAuthenticated) removeBootLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,6 @@ export default class ConsoleRoute extends Route {
|
||||
async afterModel(model, transition) {
|
||||
this.hookService.execute('console:after-model', this.session, this.router, model, transition);
|
||||
removeBootLoader();
|
||||
console.log('boot loader removed');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ConsoleAccountVirtualRoute extends Route {
|
||||
@service('universe/menu-service') menuService;
|
||||
@service universe;
|
||||
|
||||
queryParams = {
|
||||
@@ -12,6 +13,6 @@ export default class ConsoleAccountVirtualRoute extends Route {
|
||||
|
||||
model({ slug }, transition) {
|
||||
const view = this.universe.getViewFromTransition(transition);
|
||||
return this.universe.lookupMenuItemFromRegistry('console:account', slug, view);
|
||||
return this.menuService.lookupMenuItem('console:account', slug, view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ConsoleAdminVirtualRoute extends Route {
|
||||
@service('universe/menu-service') menuService;
|
||||
@service universe;
|
||||
|
||||
queryParams = {
|
||||
@@ -12,6 +13,6 @@ export default class ConsoleAdminVirtualRoute extends Route {
|
||||
|
||||
model({ slug }, transition) {
|
||||
const view = this.universe.getViewFromTransition(transition);
|
||||
return this.universe.lookupMenuItemFromRegistry('console:admin', slug, view);
|
||||
return this.menuService.lookupMenuItem('console:admin', slug, view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ConsoleSettingsVirtualRoute extends Route {
|
||||
@service('universe/menu-service') menuService;
|
||||
@service universe;
|
||||
|
||||
queryParams = {
|
||||
@@ -12,6 +13,6 @@ export default class ConsoleSettingsVirtualRoute extends Route {
|
||||
|
||||
model({ slug }, transition) {
|
||||
const view = this.universe.getViewFromTransition(transition);
|
||||
return this.universe.lookupMenuItemFromRegistry('console:settings', slug, view);
|
||||
return this.menuService.lookupMenuItem('console:settings', slug, view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ConsoleVirtualRoute extends Route {
|
||||
@service('universe/menu-service') menuService;
|
||||
@service universe;
|
||||
|
||||
queryParams = {
|
||||
@@ -12,6 +13,6 @@ export default class ConsoleVirtualRoute extends Route {
|
||||
|
||||
model({ slug }, transition) {
|
||||
const view = this.universe.getViewFromTransition(transition);
|
||||
return this.universe.lookupMenuItemFromRegistry('console', slug, view);
|
||||
return this.menuService.lookupMenuItem('console', slug, view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class VirtualRoute extends Route {
|
||||
@service('universe/menu-service') menuService;
|
||||
@service universe;
|
||||
|
||||
queryParams = {
|
||||
@@ -12,6 +13,6 @@ export default class VirtualRoute extends Route {
|
||||
|
||||
model({ slug }, transition) {
|
||||
const view = this.universe.getViewFromTransition(transition);
|
||||
return this.universe.lookupMenuItemFromRegistry('auth:login', slug, view);
|
||||
return this.menuService.lookupMenuItem('auth:login', slug, view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
<div class="container mx-auto h-screen">
|
||||
<div class="max-w-3xl my-10 mx-auto space-y-">
|
||||
{{component @model.component params=@model.componentParams}}
|
||||
<LazyEngineComponent @component={{@model.component}} @params={{@model.componentParams}} />
|
||||
</div>
|
||||
</div>
|
||||
<Spacer @height="300px" />
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<Layout::Sidebar::Item @route="console.admin.branding" @icon="palette">{{t "console.admin.menu.branding"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.two-fa-settings" @icon="shield-halved">{{t "console.admin.menu.2fa-config"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.schedule-monitor" @icon="calendar-check">{{t "console.admin.schedule-monitor.schedule-monitor"}}</Layout::Sidebar::Item>
|
||||
|
||||
{{#each this.universe.adminMenuItems as |menuItem|}}
|
||||
<Layout::Sidebar::Item
|
||||
@onClick={{fn this.universe.transitionMenuItem "console.admin.virtual" menuItem}}
|
||||
@@ -13,6 +14,7 @@
|
||||
@icon={{menuItem.icon}}
|
||||
>{{menuItem.title}}</Layout::Sidebar::Item>
|
||||
{{/each}}
|
||||
|
||||
{{#each this.universe.adminMenuPanels as |menuPanel|}}
|
||||
<Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}}>
|
||||
{{#each menuPanel.items as |menuItem|}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
<div class="container mx-auto h-screen">
|
||||
<div class="max-w-3xl my-10 mx-auto space-y-">
|
||||
{{component @model.component params=@model.componentParams}}
|
||||
<LazyEngineComponent @component={{@model.component}} @params={{@model.componentParams}} />
|
||||
</div>
|
||||
</div>
|
||||
<Spacer @height="300px" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
<div class="container mx-auto h-screen">
|
||||
<div class="max-w-3xl my-10 mx-auto space-y-">
|
||||
{{component @model.component params=@model.componentParams}}
|
||||
<LazyEngineComponent @component={{@model.component}} @params={{@model.componentParams}} />
|
||||
</div>
|
||||
</div>
|
||||
<Spacer @height="300px" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{page-title @model.title}}
|
||||
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
{{component @model.component params=@model.componentParams}}
|
||||
<LazyEngineComponent @component={{@model.component}} @params={{@model.componentParams}} />
|
||||
<Spacer @height="300px" />
|
||||
</Layout::Section::Body>
|
||||
@@ -1,2 +1,2 @@
|
||||
{{page-title @model.title}}
|
||||
{{component @model.component params=@model.componentParams}}
|
||||
<LazyEngineComponent @component={{@model.component}} @params={{@model.componentParams}} />
|
||||
@@ -60,21 +60,21 @@ export function applyRuntimeConfig(rawConfig = {}) {
|
||||
const coercedValue = coerceValue(key, value);
|
||||
set(config, configPath, coercedValue);
|
||||
} else {
|
||||
debug(`[runtime-config] Ignored unknown key: ${key}`);
|
||||
debug(`[Runtime Config] Ignored unknown key: ${key}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached config from localStorage
|
||||
*
|
||||
*
|
||||
* @returns {Object|null} Cached config or null
|
||||
*/
|
||||
function getCachedConfig() {
|
||||
try {
|
||||
const cached = localStorage.getItem(CACHE_KEY);
|
||||
const cachedVersion = localStorage.getItem(CACHE_VERSION_KEY);
|
||||
|
||||
|
||||
if (!cached || !cachedVersion) {
|
||||
return null;
|
||||
}
|
||||
@@ -84,55 +84,55 @@ function getCachedConfig() {
|
||||
|
||||
// Check if cache is still valid (within TTL)
|
||||
if (cacheAge > CACHE_TTL) {
|
||||
debug('[runtime-config] Cache expired');
|
||||
debug('[Runtime Config] Cache expired');
|
||||
return null;
|
||||
}
|
||||
|
||||
debug(`[runtime-config] Using cached config (age: ${Math.round(cacheAge / 1000)}s)`);
|
||||
debug(`[Runtime Config] Using cached config (age: ${Math.round(cacheAge / 1000)}s)`);
|
||||
return cacheData.config;
|
||||
} catch (e) {
|
||||
debug(`[runtime-config] Failed to read cache: ${e.message}`);
|
||||
debug(`[Runtime Config] Failed to read cache: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save config to localStorage cache
|
||||
*
|
||||
*
|
||||
* @param {Object} config Config object
|
||||
*/
|
||||
function setCachedConfig(config) {
|
||||
try {
|
||||
const cacheData = {
|
||||
config,
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData));
|
||||
localStorage.setItem(CACHE_VERSION_KEY, '1');
|
||||
debug('[runtime-config] Config cached to localStorage');
|
||||
debug('[Runtime Config] Config cached to localStorage');
|
||||
} catch (e) {
|
||||
debug(`[runtime-config] Failed to cache config: ${e.message}`);
|
||||
debug(`[Runtime Config] Failed to cache config: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached config
|
||||
*
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export function clearRuntimeConfigCache() {
|
||||
try {
|
||||
localStorage.removeItem(CACHE_KEY);
|
||||
localStorage.removeItem(CACHE_VERSION_KEY);
|
||||
debug('[runtime-config] Cache cleared');
|
||||
debug('[Runtime Config] Cache cleared');
|
||||
} catch (e) {
|
||||
debug(`[runtime-config] Failed to clear cache: ${e.message}`);
|
||||
debug(`[Runtime Config] Failed to clear cache: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and apply runtime config with localStorage caching.
|
||||
*
|
||||
*
|
||||
* Strategy:
|
||||
* 1. Check localStorage cache first (instant, no HTTP request)
|
||||
* 2. If cache hit and valid, use it immediately
|
||||
@@ -147,34 +147,34 @@ export default async function loadRuntimeConfig() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try cache first
|
||||
const cachedConfig = getCachedConfig();
|
||||
if (cachedConfig) {
|
||||
applyRuntimeConfig(cachedConfig);
|
||||
return;
|
||||
}
|
||||
// // Try cache first
|
||||
// const cachedConfig = getCachedConfig();
|
||||
// if (cachedConfig) {
|
||||
// applyRuntimeConfig(cachedConfig);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Cache miss - fetch from server
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
const response = await fetch(`/fleetbase.config.json`, {
|
||||
cache: 'default' // Use browser cache if available
|
||||
const response = await fetch('/fleetbase.config.json', {
|
||||
cache: 'default', // Use browser cache if available
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
debug('[runtime-config] No fleetbase.config.json found, using built-in config defaults');
|
||||
debug('[Runtime Config] No fleetbase.config.json found, using built-in config defaults');
|
||||
return;
|
||||
}
|
||||
|
||||
const runtimeConfig = await response.json();
|
||||
const endTime = performance.now();
|
||||
|
||||
debug(`[runtime-config] Fetched from server in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
|
||||
|
||||
debug(`[Runtime Config] Fetched from server in ${(endTime - startTime).toFixed(2)}ms`);
|
||||
|
||||
// Apply and cache
|
||||
applyRuntimeConfig(runtimeConfig);
|
||||
setCachedConfig(runtimeConfig);
|
||||
} catch (e) {
|
||||
debug(`[runtime-config] Failed to load runtime config: ${e.message}`);
|
||||
debug(`[Runtime Config] Failed to load runtime config: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,7 @@ module.exports = function (defaults) {
|
||||
storeConfigInMeta: false,
|
||||
|
||||
fingerprint: {
|
||||
exclude: [
|
||||
'leaflet/',
|
||||
'leaflet-images/',
|
||||
'socketcluster-client.min.js',
|
||||
'fleetbase.config.json',
|
||||
'extensions.json'
|
||||
],
|
||||
exclude: ['leaflet/', 'leaflet-images/', 'socketcluster-client.min.js', 'fleetbase.config.json', 'extensions.json'],
|
||||
},
|
||||
|
||||
liveReload: {
|
||||
@@ -71,7 +65,7 @@ module.exports = function (defaults) {
|
||||
plugins: [require.resolve('ember-auto-import/babel-plugin')],
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
let runtimeConfigTree;
|
||||
if (toBoolean(process.env.DISABLE_RUNTIME_CONFIG)) {
|
||||
runtimeConfigTree = writeFile('fleetbase.config.json', '{}');
|
||||
|
||||
@@ -13,7 +13,7 @@ module.exports = {
|
||||
name: require('./package').name,
|
||||
|
||||
getGeneratedFileHeader() {
|
||||
const year = (new Date()).getFullYear();
|
||||
const year = new Date().getFullYear();
|
||||
return `/**
|
||||
* ███████╗██╗ ███████╗███████╗████████╗██████╗ █████╗ ███████╗███████╗
|
||||
* ██╔════╝██║ ██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██╔════╝██╔════╝
|
||||
@@ -37,41 +37,41 @@ module.exports = {
|
||||
|
||||
included(app) {
|
||||
this._super.included.apply(this, arguments);
|
||||
|
||||
|
||||
console.log('\n' + '/'.repeat(70));
|
||||
console.log('[Fleetbase] Extension Build System');
|
||||
console.log('/'.repeat(70));
|
||||
|
||||
|
||||
// Generate files on startup
|
||||
this.generateExtensionFiles();
|
||||
|
||||
|
||||
// Watch for changes in development
|
||||
this.watchExtensionFiles();
|
||||
},
|
||||
|
||||
async generateExtensionFiles() {
|
||||
const extensions = await this.getExtensions();
|
||||
|
||||
|
||||
if (extensions.length === 0) {
|
||||
console.log('[Fleetbase] No extensions found');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
console.log(`[Fleetbase] Discovered ${extensions.length} extension(s)`);
|
||||
extensions.forEach(ext => {
|
||||
extensions.forEach((ext) => {
|
||||
console.log(`[Fleetbase] - ${ext.name} (v${ext.version})`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
|
||||
// Generate extension shims
|
||||
this.generateExtensionShims(extensions);
|
||||
|
||||
|
||||
// Generate extension loaders
|
||||
this.generateExtensionLoaders(extensions);
|
||||
|
||||
|
||||
// Generate router
|
||||
this.generateRouter(extensions);
|
||||
|
||||
|
||||
// Generate manifest
|
||||
this.generateExtensionsManifest(extensions);
|
||||
},
|
||||
@@ -184,12 +184,14 @@ module.exports = {
|
||||
|
||||
const mountPath = extension.fleetbase?.route || this.getExtensionMountPath(extension.name);
|
||||
const camelCaseName = mountPath.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
|
||||
|
||||
imports.push(`import ${camelCaseName} from './${mountPath}';`);
|
||||
loaders[extension.name] = `() => ${camelCaseName}`;
|
||||
});
|
||||
|
||||
const loadersContent = this.getGeneratedFileHeader() + `${imports.join('\n')}
|
||||
const loadersContent =
|
||||
this.getGeneratedFileHeader() +
|
||||
`${imports.join('\n')}
|
||||
|
||||
export const EXTENSION_LOADERS = {
|
||||
${Object.entries(loaders)
|
||||
@@ -227,7 +229,7 @@ export default getExtensionLoader;
|
||||
functionExpression = arg;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (functionExpression) {
|
||||
// Check and add the new engine mounts
|
||||
consoleExtensions.forEach((extension) => {
|
||||
@@ -337,7 +339,7 @@ export default getExtensionLoader;
|
||||
}
|
||||
|
||||
const self = this;
|
||||
|
||||
|
||||
this.getExtensions().then((extensions) => {
|
||||
const extensionFiles = [];
|
||||
|
||||
|
||||
12
console/tests/unit/controllers/virtual-test.js
Normal file
12
console/tests/unit/controllers/virtual-test.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from '@fleetbase/console/tests/helpers';
|
||||
|
||||
module('Unit | Controller | virtual', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup('controller:virtual');
|
||||
assert.ok(controller);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user