Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inventory centric POC module. #2967

Merged
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
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
Loading