Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions addon/utils/resource-descriptors/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,32 @@ export function engineInstalled(owner, engineName = FLEETOPS_ENGINE) {
}
}

/**
* Whether the console is on one of the engine's own routes. Unknown means yes, so a host
* without a router keeps the previous behaviour.
*/
export function isInsideEngine(manager, engineName = FLEETOPS_ENGINE) {
let current;
let mountPoint;

try {
current = manager?.applicationInstance?.lookup?.('service:router')?.currentRouteName;
mountPoint = manager?.getEngineMountPoint?.(engineName);
} catch {
return true;
}

if (typeof current !== 'string' || typeof mountPoint !== 'string' || mountPoint === '') {
return true;
}

return current === mountPoint.replace(/\.$/, '') || current.startsWith(mountPoint);
}

/**
* An opener that loads an engine on demand, then hands the record to one of
* its action services: the context panel when it has one, else its route
* transition. The engine bundle is only fetched when someone actually clicks,
* its action services: the context panel when it has one and the console is inside that
* engine, else its route transition. The engine bundle is only fetched when someone actually clicks,
* never when a page that merely shows the resource renders.
*/
export function engineOpener(owner, serviceName, { engineName = FLEETOPS_ENGINE, mode = 'panel' } = {}) {
Expand All @@ -190,7 +212,10 @@ export function engineOpener(owner, serviceName, { engineName = FLEETOPS_ENGINE,
return false;
}

const view = (mode === 'panel' ? (service.panel?.view ?? service.transition?.view) : null) ?? (mode === 'transition' ? service.transition?.view : null);
// A panel renders the engine's own components, which only resolve inside that engine's
// routes; from anywhere else (Storefront, the console home) open the record's page instead.
const panelView = mode === 'panel' && isInsideEngine(manager, engineName) ? service.panel?.view : null;
const view = panelView ?? (mode === 'panel' || mode === 'transition' ? service.transition?.view : null);

if (typeof view !== 'function') {
return false;
Expand Down
35 changes: 35 additions & 0 deletions tests/unit/utils/resource-descriptors/helpers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
extensionManager,
engineInstalled,
engineOpener,
isInsideEngine,
FLEETOPS_ENGINE,
} from '@fleetbase/fleetops-data/utils/resource-descriptors/helpers';
import { PLACEHOLDER_IMAGES } from '@fleetbase/fleetops-data/utils/placeholder-images';
Expand Down Expand Up @@ -219,5 +220,39 @@ module('Unit | Utility | resource-descriptors/helpers', function (hooks) {
['transition', record],
]);
});

test("engineOpener opens the record's page instead of a panel outside the engine's routes", async function (assert) {
const record = { id: 'r1' };
const seen = [];
const service = { panel: { view: () => seen.push('panel') }, transition: { view: () => seen.push('transition') } };
const at = (routeName) =>
ownerWithEngine(
{ 'vehicle-actions': service, 'panel-only': { panel: { view: () => seen.push('panel-only') } } },
{
applicationInstance: { lookup: (name) => (name === 'service:router' ? { currentRouteName: routeName } : null) },
getEngineMountPoint: () => 'console.fleet-ops.',
}
);

assert.true(await engineOpener(at('console.fleet-ops.management.vehicles.index'), 'vehicle-actions')(record));
assert.true(await engineOpener(at('console.storefront.food-trucks.index'), 'vehicle-actions')(record));
assert.false(await engineOpener(at('console.storefront.food-trucks.index'), 'panel-only')(record), 'nothing to open outside without a transition');
assert.deepEqual(seen, ['panel', 'transition'], 'the panel inside Fleet-Ops, the page from Storefront');
});

test('isInsideEngine reads the console route against the engine mount point and assumes yes when it cannot tell', function (assert) {
const manager = (routeName, mountPoint = 'console.fleet-ops.') => ({
applicationInstance: { lookup: () => ({ currentRouteName: routeName }) },
getEngineMountPoint: () => mountPoint,
});

assert.true(isInsideEngine(manager('console.fleet-ops.operations.orders.index')));
assert.true(isInsideEngine(manager('console.fleet-ops')), 'the engine root');
assert.false(isInsideEngine(manager('console.storefront.index')));
assert.false(isInsideEngine(manager('console.fleet-ops-reports.index')), 'a prefix match is not enough');
assert.true(isInsideEngine(null), 'no manager');
assert.true(isInsideEngine(manager(undefined)), 'no route');
assert.true(isInsideEngine(manager('console.storefront.index', null)), 'no mount point');
});
});
});
Loading