diff --git a/.github/workflows/gubbins-test.yml b/.github/workflows/gubbins-test.yml
index cb15ad76..aaaa8382 100644
--- a/.github/workflows/gubbins-test.yml
+++ b/.github/workflows/gubbins-test.yml
@@ -330,3 +330,10 @@ jobs:
browser: chrome
config: baseUrl=${{ env.DIRACX_URL }}
project: /tmp/gubbins-web
+
+ - name: Upload Cypress screenshots
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: cypress-screenshots
+ path: /tmp/gubbins-web/cypress/screenshots
\ No newline at end of file
diff --git a/docs/developer/create_application.md b/docs/developer/create_application.md
index 8964e4b1..52b552b6 100644
--- a/docs/developer/create_application.md
+++ b/docs/developer/create_application.md
@@ -6,7 +6,7 @@ The applicatins created here will be available for DiracX-Web and for all the ex
### Declare the application
-In the file `packages/diracx-web-components/src/components/ApplicationList.ts` you can extend the `applicationList` with your new app.
+In the file `packages/diracx-web-components/src/components/applicationList.ts` you can extend the `applicationList` with your new app.
You must provide:
- A clear and explicit name
diff --git a/packages/diracx-web-components/src/components/ApplicationList.ts b/packages/diracx-web-components/src/components/applicationList.ts
similarity index 100%
rename from packages/diracx-web-components/src/components/ApplicationList.ts
rename to packages/diracx-web-components/src/components/applicationList.ts
diff --git a/packages/diracx-web-components/src/components/defaultDashboard.ts b/packages/diracx-web-components/src/components/defaultDashboard.ts
new file mode 100644
index 00000000..b04b6f10
--- /dev/null
+++ b/packages/diracx-web-components/src/components/defaultDashboard.ts
@@ -0,0 +1,15 @@
+import { DashboardGroup } from "../types/DashboardGroup";
+
+export const defaultDashboard: DashboardGroup[] = [
+ {
+ title: "My dashboard",
+ extended: true,
+ items: [
+ {
+ title: "My Jobs",
+ type: "Job Monitor",
+ id: "JobMonitor0",
+ },
+ ],
+ },
+];
diff --git a/packages/diracx-web-components/src/components/index.ts b/packages/diracx-web-components/src/components/index.ts
index a093c1e5..f5da5865 100644
--- a/packages/diracx-web-components/src/components/index.ts
+++ b/packages/diracx-web-components/src/components/index.ts
@@ -1,5 +1,5 @@
// Application list
-export { applicationList } from "./ApplicationList";
+export { applicationList } from "./applicationList";
// Dashboard Layout
export * from "./DashboardLayout";
diff --git a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx
index af97ee87..c0996263 100644
--- a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx
+++ b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx
@@ -1,7 +1,8 @@
"use client";
import React, { createContext, useEffect, useState } from "react";
-import { applicationList } from "../components/ApplicationList";
+import { applicationList } from "../components/applicationList";
+import { defaultDashboard } from "../components/defaultDashboard";
import { DashboardGroup } from "../types/DashboardGroup";
import ApplicationMetadata from "../types/ApplicationMetadata";
@@ -33,7 +34,7 @@ interface ApplicationsProviderProps {
export const ApplicationsProvider = ({
children,
appList = applicationList,
- defaultUserDashboard,
+ defaultUserDashboard = defaultDashboard,
}: ApplicationsProviderProps) => {
const loadedDashboard = sessionStorage.getItem("savedDashboard");
const parsedDashboard: DashboardGroup[] = loadedDashboard
@@ -51,21 +52,7 @@ export const ApplicationsProvider = ({
useEffect(() => {
if (userDashboard.length !== 0) return;
- setUserDashboard(
- defaultUserDashboard || [
- {
- title: "My dashboard",
- extended: true,
- items: [
- {
- title: "My Jobs",
- type: "Job Monitor",
- id: "JobMonitor0",
- },
- ],
- },
- ],
- );
+ setUserDashboard(defaultUserDashboard);
}, [appList, defaultUserDashboard]);
// Save the dashboard in session storage
diff --git a/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx b/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx
index 323b3502..856a7e2c 100644
--- a/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx
+++ b/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx
@@ -1,5 +1,8 @@
"use client";
+import type { ApplicationMetadata, DashboardGroup } from "../types";
+
+import { OIDCSecure } from "../components";
import {
OIDCConfigurationProvider,
ThemeProvider,
@@ -12,6 +15,8 @@ interface DiracXWebProvidersProps {
getPath: () => string;
setPath: (path: string) => void;
getSearchParams: () => URLSearchParams;
+ appList?: ApplicationMetadata[];
+ defaultUserDashboard?: DashboardGroup[];
}
export function DiracXWebProviders({
@@ -19,6 +24,8 @@ export function DiracXWebProviders({
getPath,
setPath,
getSearchParams,
+ appList,
+ defaultUserDashboard,
}: DiracXWebProvidersProps) {
return (
@@ -27,8 +34,13 @@ export function DiracXWebProviders({
setPath={setPath}
getSearchParams={getSearchParams}
>
-
- {children}
+
+
+ {children}
+
diff --git a/packages/diracx-web-components/stories/Dashboard.stories.tsx b/packages/diracx-web-components/stories/Dashboard.stories.tsx
index be3d3e3f..1a05227c 100644
--- a/packages/diracx-web-components/stories/Dashboard.stories.tsx
+++ b/packages/diracx-web-components/stories/Dashboard.stories.tsx
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react";
import { Box } from "@mui/material";
import { ApplicationsContext } from "../src/contexts/ApplicationsProvider";
import { NavigationProvider } from "../src/contexts/NavigationProvider";
-import { applicationList } from "../src/components/ApplicationList";
+import { applicationList } from "../src/components/applicationList";
import { DashboardGroup } from "../src/types/DashboardGroup";
import Dashboard from "../src/components/DashboardLayout/Dashboard";
import { ThemeProvider } from "../src/contexts/ThemeProvider";
diff --git a/packages/diracx-web/src/app/(dashboard)/layout.tsx b/packages/diracx-web/src/app/(dashboard)/layout.tsx
index 3e2f29e2..0222f171 100644
--- a/packages/diracx-web/src/app/(dashboard)/layout.tsx
+++ b/packages/diracx-web/src/app/(dashboard)/layout.tsx
@@ -2,10 +2,7 @@
import React from "react";
import { Box } from "@mui/material";
import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts";
-import {
- OIDCSecure,
- Dashboard,
-} from "@dirac-grid/diracx-web-components/components";
+import { Dashboard } from "@dirac-grid/diracx-web-components/components";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
export default function DashboardLayout({
@@ -25,22 +22,20 @@ export default function DashboardLayout({
}}
getSearchParams={() => searchParams}
>
-
-
-
- {children}
-
-
-
+
+
+ {children}
+
+
);
diff --git a/packages/extensions/src/app/(dashboard)/layout.tsx b/packages/extensions/src/app/(dashboard)/layout.tsx
index b15d764d..1f464574 100644
--- a/packages/extensions/src/app/(dashboard)/layout.tsx
+++ b/packages/extensions/src/app/(dashboard)/layout.tsx
@@ -1,16 +1,10 @@
"use client";
import React from "react";
import { Box } from "@mui/material";
-import {
- OIDCSecure,
- Dashboard,
-} from "@dirac-grid/diracx-web-components/components";
-import {
- ApplicationsProvider,
- DiracXWebProviders,
-} from "@dirac-grid/diracx-web-components/contexts";
+import { Dashboard } from "@dirac-grid/diracx-web-components/components";
+import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
-import { applicationList } from "@/gubbins/ApplicationList";
+import { applicationList } from "@/gubbins/applicationList";
import { defaultSections } from "@/gubbins/DefaultUserDashboard";
// Layout for the dashboard: setup the providers and the dashboard for the applications
@@ -32,32 +26,25 @@ export default function DashboardLayout({
getPath={() => pathname}
setPath={router.push}
getSearchParams={() => searchParams}
+ // You can optionally pass a list of applications and a default user dashboard
+ appList={applicationList}
+ defaultUserDashboard={defaultSections}
>
- {/* ApplicationsProvider is the provider for the applications, you can give it customized application list or default user dashboard to override them.
- No need to use it if you don't want to customize the applications */}
-
- {/* OIDCSecure is used to make sure the user is authenticated before accessing the dashboard */}
-
- {/* Dashboard is the main layout for the applications, you can optionally give it a custom logo URL and a drawer width */}
-
-
- {children}
-
-
-
-
+ {/* Dashboard is the main layout for the applications, you can optionally give it a custom logo URL and a drawer width */}
+
+
+ {children}
+
+
);
}
diff --git a/packages/extensions/src/app/auth/layout.tsx b/packages/extensions/src/app/auth/layout.tsx
index 7e563ffc..1a573ab0 100644
--- a/packages/extensions/src/app/auth/layout.tsx
+++ b/packages/extensions/src/app/auth/layout.tsx
@@ -2,6 +2,8 @@
import React from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts";
+import { applicationList } from "@/gubbins/applicationList";
+import { defaultSections } from "@/gubbins/DefaultUserDashboard";
// Layout for the authentication page: setup the navigation provider
export default function AuthLayout({
@@ -19,6 +21,9 @@ export default function AuthLayout({
getPath={() => pathname}
setPath={router.push}
getSearchParams={() => searchParams}
+ // You can optionally pass a list of applications and a default user dashboard
+ appList={applicationList}
+ defaultUserDashboard={defaultSections}
>
{children}
diff --git a/packages/extensions/src/gubbins/ApplicationList.ts b/packages/extensions/src/gubbins/applicationList.ts
similarity index 100%
rename from packages/extensions/src/gubbins/ApplicationList.ts
rename to packages/extensions/src/gubbins/applicationList.ts
diff --git a/packages/extensions/src/gubbins/components/OwnerMonitor/OwnerMonitor.tsx b/packages/extensions/src/gubbins/components/OwnerMonitor/OwnerMonitor.tsx
index 6dc9c552..ef49e8e0 100644
--- a/packages/extensions/src/gubbins/components/OwnerMonitor/OwnerMonitor.tsx
+++ b/packages/extensions/src/gubbins/components/OwnerMonitor/OwnerMonitor.tsx
@@ -1,5 +1,5 @@
"use client";
-import React, { useMemo, useState } from "react";
+import React, { useMemo, useState, useEffect, useCallback } from "react";
import { useOidcAccessToken } from "@axa-fr/react-oidc";
import {
fetcher,
@@ -34,7 +34,7 @@ export default function OwnerMonitor() {
});
// Fetch the list of owners
- const fetchOwners = async () => {
+ const fetchOwners = useCallback(async () => {
try {
setIsLoading(true);
const response = await fetcher([
@@ -53,7 +53,7 @@ export default function OwnerMonitor() {
} finally {
setIsLoading(false);
}
- };
+ }, [accessToken]);
// Handle adding a new owner
const handleAddOwner = async () => {
@@ -91,6 +91,10 @@ export default function OwnerMonitor() {
onPaginationChange: setPagination,
});
+ useEffect(() => {
+ fetchOwners();
+ }, [fetchOwners]);
+
return (
{
// so we must tell it to visit our website with the `cy.visit()` command.
// Since we want to visit the same URL at the start of all our tests,
// we include it in our beforeEach function so that it runs before each test
- cy.visit("/");
+ cy.visit("/auth");
});
it("login", () => {
@@ -43,7 +43,9 @@ describe("Login and Logout", () => {
// From now on the user is logged in
// The login buttton should not be present anymore
cy.get('[data-testid="button-login"]').should("not.exist");
- cy.contains("Hello admin").should("exist");
+
+ cy.visit("/");
+ cy.contains("Owners").should("exist");
// Click on the user avatar
cy.get(".MuiAvatar-root").click();
diff --git a/packages/extensions/test/e2e/ownerMonitor.cy.ts b/packages/extensions/test/e2e/ownerMonitor.cy.ts
index ff81c400..cad7dd61 100644
--- a/packages/extensions/test/e2e/ownerMonitor.cy.ts
+++ b/packages/extensions/test/e2e/ownerMonitor.cy.ts
@@ -1,9 +1,9 @@
///
-describe("Job Monitor", () => {
+describe("Owner Monitor", () => {
beforeEach(() => {
cy.session("login", () => {
- cy.visit("/");
+ cy.visit("/auth");
//login
cy.get('[data-testid="button-login"]').click();
cy.get("#login").type("admin@example.com");
@@ -17,9 +17,14 @@ describe("Job Monitor", () => {
});
// Visit the page where the Job Monitor is rendered
- cy.visit(
- "/?appId=OwnerMonitor1&dashboard=%5B3Gubbins+Apps%27~extended%21true~items%21%5B-020.04~data%21%5B%5D%29%2C3Job2Job.Job4%29%5D%29%5D*Monitor-%28%27title%21%27.*1%27~type%21%270Owner2s%27~id%21%273-My+4+*%27%014320.-*_",
- );
+ cy.window().then((win) => {
+ win.sessionStorage.setItem(
+ "savedDashboard",
+ '[{"title":"Group 2","extended":true,"items":[{"title":"Owner Monitor","id":"JOwner Monitor0","type":"Owner Monitor"},{"title":"Owner Monitor 2","id":"Owner Monitor 21","type":"Owner Monitor"}]}]',
+ );
+ });
+
+ cy.visit("/");
});
it("should render the drawer", () => {
@@ -47,7 +52,6 @@ describe("Job Monitor", () => {
});
/** Column interactions */
-
it("should hide/show columns", () => {
// Click on the visibility icon
cy.get('[data-testid="VisibilityIcon"] > path').click();