From 1c8658b6267ab0624c40cd17d15d4106fa5f8b98 Mon Sep 17 00:00:00 2001 From: Martin Marosi Date: Mon, 4 Aug 2025 13:25:43 +0200 Subject: [PATCH] feat: migrate to new widget backend --- docs/components/custom-widgets.md | 6 ++-- docs/layout-data-format.md | 25 +++++----------- fec.config.js | 7 ++--- src/Components/DnDLayout/GridLayout.tsx | 3 +- src/Routes/Default/Default.tsx | 2 ++ src/api/dashboard-templates.ts | 39 ++++++++----------------- 6 files changed, 28 insertions(+), 54 deletions(-) diff --git a/docs/components/custom-widgets.md b/docs/components/custom-widgets.md index 944977d..8b9ff43 100644 --- a/docs/components/custom-widgets.md +++ b/docs/components/custom-widgets.md @@ -10,7 +10,7 @@ Custom widgets are React components that integrate with the Widget Layout system Widgets are loaded through a multi-step process: -1. **Widget Mapping**: The backend provides widget configuration via `/api/chrome-service/v1/dashboard-templates/widget-mapping` +1. **Widget Mapping**: The backend provides widget configuration via `/api/widget-layout/v1/widget-mapping` 2. **Module Federation**: Widgets are loaded as federated modules using ScalprumComponent (configured via `fec.config.js`) 3. **Grid Integration**: Each widget is wrapped in a GridTile that provides layout and interaction capabilities @@ -129,7 +129,7 @@ npm run build ### Step 3: Configure Widget Mapping -The widget mapping must be provided by the backend API at `/api/chrome-service/v1/dashboard-templates/widget-mapping`. Example configuration: +The widget mapping must be provided by the backend API at `/api/widget-layout/v1/widget-mapping`. Example configuration: ```json { @@ -388,7 +388,7 @@ Ensure your widget is properly registered by checking the widget mapping: ```tsx // Test if widget is available -const widgetMapping = await fetch('/api/chrome-service/v1/dashboard-templates/widget-mapping') +const widgetMapping = await fetch('/api/widget-layout/v1/widget-mapping') .then(res => res.json()); console.log('Available widgets:', Object.keys(widgetMapping.data)); diff --git a/docs/layout-data-format.md b/docs/layout-data-format.md index 1dabad4..7cf2ae2 100644 --- a/docs/layout-data-format.md +++ b/docs/layout-data-format.md @@ -343,30 +343,22 @@ export type WidgetMapping = { ## API Endpoints -### Base Templates +**Note**: The API has been migrated from `/api/chrome-service/v1/dashboard-templates` to `/api/widget-layout/v1/`. The base template fetch functions have been removed, and the delete dashboard template functionality is no longer available. They were not used in this codebase. -```bash -GET /api/chrome-service/v1/dashboard-templates/base-template -# Returns: BaseTemplate[] - -GET /api/chrome-service/v1/dashboard-templates/base-template?dashboard=landingPage -# Returns: BaseTemplate -``` - -### User Templates +### Dashboard Templates ```bash -GET /api/chrome-service/v1/dashboard-templates +GET /api/widget-layout/v1/ # Returns: DashboardTemplate[] -GET /api/chrome-service/v1/dashboard-templates?dashboard=landingPage +GET /api/widget-layout/v1/?dashboardType=landingPage # Returns: DashboardTemplate[] ``` ### Widget Mapping ```bash -GET /api/chrome-service/v1/dashboard-templates/widget-mapping +GET /api/widget-layout/v1/widget-mapping # Returns: WidgetMapping ``` @@ -374,7 +366,7 @@ GET /api/chrome-service/v1/dashboard-templates/widget-mapping ```bash # Update template configuration -PATCH /api/chrome-service/v1/dashboard-templates/{templateId} +PATCH /api/widget-layout/v1/{templateId} Content-Type: application/json { @@ -387,10 +379,7 @@ Content-Type: application/json } # Reset template to base configuration -POST /api/chrome-service/v1/dashboard-templates/{templateId}/reset - -# Delete template -DELETE /api/chrome-service/v1/dashboard-templates/{templateId} +POST /api/widget-layout/v1/{templateId}/reset ``` ## Data Flow and Persistence diff --git a/fec.config.js b/fec.config.js index 5082ef8..9df4736 100644 --- a/fec.config.js +++ b/fec.config.js @@ -19,11 +19,8 @@ module.exports = { _unstableHotReload: process.env.HOT === 'true', routes: { ...(process.env.CONFIG_PORT && { - '/api/chrome-service/v1/static': { - host: `http://localhost:${process.env.CONFIG_PORT}`, - }, - '/api/chrome-service/v1/dashboard-templates': { - host: `http://localhost:${process.env.CONFIG_PORT}`, + '/api/widget-layout': { + target: 'http://localhost:8000', }, }), }, diff --git a/src/Components/DnDLayout/GridLayout.tsx b/src/Components/DnDLayout/GridLayout.tsx index 8f08c93..db75757 100644 --- a/src/Components/DnDLayout/GridLayout.tsx +++ b/src/Components/DnDLayout/GridLayout.tsx @@ -76,7 +76,7 @@ const debouncedPatchDashboardTemplate = DebouncePromise(patchDashboardTemplate, onlyResolvesLast: true, }); -const GridLayout = ({ isLayoutLocked = false, layoutType = 'landingPage' }: { isLayoutLocked?: boolean; layoutType?: LayoutTypes }) => { +const GridLayout = ({ isLayoutLocked = false, layoutType = 'landing-landingPage' }: { isLayoutLocked?: boolean; layoutType?: LayoutTypes }) => { const [isDragging, setIsDragging] = useState(false); const [isInitialRender, setIsInitialRender] = useState(true); const [isLoaded, setIsLoaded] = useState(false); @@ -296,6 +296,7 @@ const GridLayout = ({ isLayoutLocked = false, layoutType = 'landingPage' }: { is // eslint-disable-next-line @typescript-eslint/no-unused-vars .map(({ widgetType, title, ...rest }, index) => { const widget = getWidget(widgetMapping, widgetType); + console.log({ widgetType, widgetMapping, widget }); if (!widget) { return null; } diff --git a/src/Routes/Default/Default.tsx b/src/Routes/Default/Default.tsx index 127dbfd..7187509 100644 --- a/src/Routes/Default/Default.tsx +++ b/src/Routes/Default/Default.tsx @@ -54,6 +54,8 @@ const DefaultRoute = (props: { layoutType?: LayoutTypes }) => { const widgetConfig = value.config; const hasPermissions = widgetConfig && widgetConfig.permissions ? await checkPermissions(widgetConfig.permissions) : true; if (hasPermissions) { + // this key is composed on the backend side to ensure unique widget names when collect from FEO + // '-(-?)' resolvedAcc[key] = value; } return acc; diff --git a/src/api/dashboard-templates.ts b/src/api/dashboard-templates.ts index 2c83c92..9a01493 100644 --- a/src/api/dashboard-templates.ts +++ b/src/api/dashboard-templates.ts @@ -10,7 +10,7 @@ const getRequestHeaders = () => ({ export const widgetIdSeparator = '#'; -export type LayoutTypes = 'landingPage'; +export type LayoutTypes = 'landingPage' | 'landing-landingPage'; export type Variants = 'sm' | 'md' | 'lg' | 'xl'; @@ -118,33 +118,27 @@ export const getWidgetIdentifier = (widgetType: string, uniqueId: string = crypt return `${widgetType}${widgetIdSeparator}${uniqueId}`; }; -export async function getBaseDashboardTemplate(): Promise; -export async function getBaseDashboardTemplate(type: LayoutTypes): Promise; -export async function getBaseDashboardTemplate(type?: LayoutTypes): Promise { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates/base-template${type ? `?dashboard=${type}` : ''}`, { - method: 'GET', - headers: getRequestHeaders(), - }); - handleErrors(resp); - const json = await resp.json(); - return json.data; -} - // Returns multiple templates for a user (user can have multiple template copies) - we will render the one marked default: true by default export async function getDashboardTemplates(): Promise; export async function getDashboardTemplates(type: LayoutTypes): Promise; export async function getDashboardTemplates(type?: LayoutTypes): Promise { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates${type ? `?dashboard=${type}` : ''}`, { + const searchParams = new URLSearchParams(); + if (type) { + searchParams.append('dashboardType', type); + } + const url = new URL(`/api/widget-layout/v1/`, window.location.origin); + url.search = searchParams.toString(); + const resp = await fetch(url.toString(), { method: 'GET', headers: getRequestHeaders(), }); - handleErrors(resp); const json = await resp.json(); + console.log({ json }); return json.data; } export async function getWidgetMapping(): Promise { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates/widget-mapping`, { + const resp = await fetch(`/api/widget-layout/v1/widget-mapping`, { method: 'GET', headers: getRequestHeaders(), }); @@ -154,7 +148,7 @@ export async function getWidgetMapping(): Promise { } export const resetDashboardTemplate = async (templateId: number): Promise => { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates/${templateId}/reset`, { + const resp = await fetch(`/api/widget-layout/v1/${templateId}/reset`, { method: 'POST', headers: getRequestHeaders(), }); @@ -167,7 +161,7 @@ export const patchDashboardTemplate = async ( templateId: DashboardTemplate['id'], data: { templateConfig: PartialTemplateConfig } ): Promise => { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates/${templateId}`, { + const resp = await fetch(`/api/widget-layout/v1/${templateId}`, { method: 'PATCH', headers: getRequestHeaders(), body: JSON.stringify(data), @@ -177,15 +171,6 @@ export const patchDashboardTemplate = async ( return json.data; }; -export const deleteDashboardTemplate = async (templateId: DashboardTemplate['id']): Promise => { - const resp = await fetch(`/api/chrome-service/v1/dashboard-templates/${templateId}`, { - method: 'DELETE', - headers: getRequestHeaders(), - }); - handleErrors(resp); - return resp.status === 204; -}; - export const getDefaultTemplate = (templates: DashboardTemplate[]): DashboardTemplate | undefined => { return templates.find((itm) => itm.default === true); };