Skip to content

Commit

Permalink
Merge pull request #2967 from Hyperkid123/inventory-centric-view
Browse files Browse the repository at this point in the history
Add inventory centric POC module.
  • Loading branch information
Hyperkid123 authored Nov 7, 2024
2 parents b5b9825 + f9547e7 commit e793f9e
Show file tree
Hide file tree
Showing 6 changed files with 714 additions and 0 deletions.
1 change: 1 addition & 0 deletions config/webpack.plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const plugins = (dev = false, beta = false, restricted = false) => {
'./LandingNavFavorites': resolve(__dirname, '../src/components/FavoriteServices/LandingNavFavorites.tsx'),
'./DashboardFavorites': resolve(__dirname, '../src/components/FavoriteServices/DashboardFavorites.tsx'),
'./SatelliteToken': resolve(__dirname, '../src/layouts/SatelliteToken.tsx'),
'./ModularInventory': resolve(__dirname, '../src/inventoryPoc/index.ts'),
},
shared: [
{ react: { singleton: true, eager: true, requiredVersion: deps.react } },
Expand Down
13 changes: 13 additions & 0 deletions src/components/Routes/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { moduleRoutesAtom } from '../../state/atoms/chromeModuleAtom';
const INTEGRATION_SOURCES = 'platform.sources.integrations';

const QuickstartCatalogRoute = lazy(() => import('../QuickstartsCatalogRoute'));
const ModularInventoryRoute = lazy(() => import('../../inventoryPoc'));

const redirects = [
{
Expand Down Expand Up @@ -64,6 +65,7 @@ export type RoutesProps = {

const ChromeRoutes = ({ routesProps }: RoutesProps) => {
const enableIntegrations = useFlag(INTEGRATION_SOURCES);
const enableInventoryPOC = useFlag('platform.chrome.poc.inventory');
const featureFlags = useMemo<Record<string, boolean>>(() => ({ INTEGRATION_SOURCES: enableIntegrations }), [enableIntegrations]);
const moduleRoutes = useAtomValue(moduleRoutesAtom);
const showBundleCatalog = localStorage.getItem('chrome:experimental:quickstarts') === 'true';
Expand Down Expand Up @@ -92,6 +94,17 @@ const ChromeRoutes = ({ routesProps }: RoutesProps) => {
{moduleRoutes.map((app) => (
<Route key={app.path} path={app.absolute ? app.path : `${app.path}/*`} element={<ChromeRoute {...routesProps} {...app} />} />
))}
{/* Inventory POC route only available for certain accounts */}
{enableInventoryPOC ? (
<Route
path="/staging/modular-inventory"
element={
<Suspense fallback={LoadingFallback}>
<ModularInventoryRoute />
</Suspense>
}
/>
) : null}
<Route path="*" element={<NotFoundRoute />} />
</Routes>
);
Expand Down
114 changes: 114 additions & 0 deletions src/inventoryPoc/InventoryColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { ReactNode } from 'react';
import { getModule } from '@scalprum/core';

export type RemoteColumnData<T extends Array<unknown> = unknown[]> = {
scope: string;
module: string;
importName?: string;
initArgs?: T;
};
export type BaseColumnData = ReactNode[];
export type ColumnData = BaseColumnData | RemoteColumnData | (() => Promise<BaseColumnData>);
export type LocalColumnData = ReactNode[];

export function isRemoteColumn(columnData: ColumnData): columnData is RemoteColumnData {
return (columnData as RemoteColumnData).module !== undefined || (columnData as RemoteColumnData).scope !== undefined;
}

export function isAsyncColumnData(columnData: ColumnData): columnData is () => Promise<BaseColumnData> {
return typeof columnData === 'function';
}

export class BaseInventoryColumn {
private columnId: string;
private title: ReactNode;
private columnData: BaseColumnData;

constructor(columnId: string, title: ReactNode, { columnData }: { columnData: BaseColumnData }) {
this.columnId = columnId;
this.title = title;
this.columnData = columnData;
}

getColumnId(): string {
return this.columnId;
}

getTitle(): ReactNode {
return this.title;
}

getColumnData(): BaseColumnData {
return this.columnData;
}

setColumnData(columnData: BaseColumnData): void {
this.columnData = columnData;
}

setColumnId(columnId: string): void {
this.columnId = columnId;
}

setColumnTitle(title: ReactNode): void {
this.title = title;
}
}

export class InventoryColumn extends BaseInventoryColumn {
private asyncModule?: boolean = false;
private ready?: boolean = true;
private observeReadyCallbacks: (() => void)[] = [];

constructor(columnId: string, title: ReactNode, { columnData }: { columnData: ColumnData }) {
if (isRemoteColumn(columnData)) {
super(columnId, title, { columnData: [] });
this.asyncModule = true;
this.ready = false;
getModule<(...args: unknown[]) => InventoryColumn>(columnData.scope, columnData.module, columnData.importName).then((remoteColumnInit) => {
const remoteColumn = remoteColumnInit(...(columnData.initArgs || []));
if (remoteColumn?.isAsync?.()) {
const p = new Promise<void>((res) => {
remoteColumn.observeReady(res);
});
p.then(() => {
this.setColumnId(remoteColumn.getColumnId());
this.setColumnTitle(remoteColumn.getTitle());
this.setColumnData(remoteColumn.getColumnData());
this.ready = true;
this.observeReadyCallbacks.forEach((callback) => callback());
});
} else {
this.setColumnId(remoteColumn.getColumnId());
this.setColumnTitle(remoteColumn.getTitle());
this.setColumnData(remoteColumn.getColumnData());
this.ready = true;
this.observeReadyCallbacks.forEach((callback) => callback());
}
});
} else if (isAsyncColumnData(columnData)) {
super(columnId, title, { columnData: [] });
this.asyncModule = true;
this.ready = false;
columnData().then((data) => {
this.setColumnData(data);
this.ready = true;
this.observeReadyCallbacks.forEach((callback) => callback());
});
} else {
super(columnId, title, { columnData: columnData as BaseColumnData });
}
}

isAsync(): boolean {
return !!this.asyncModule;
}

isReady(): boolean {
return !!this.ready;
}

observeReady(callback: () => void): void {
this.observeReadyCallbacks.push(callback);
}
}
Loading

0 comments on commit e793f9e

Please sign in to comment.