diff --git a/.env.development b/.env.development
deleted file mode 100644
index a75c3062..00000000
--- a/.env.development
+++ /dev/null
@@ -1,4 +0,0 @@
-DIRACX_CLIENT_ID=myDIRACClientID
-REDIRECT_URI=http://localhost:3000/dashboard/#authentication-callback
-DEFAULT_SCOPE="vo:diracAdmin"
-NEXT_PUBLIC_DIRACX_URL=http://localhost:8000
diff --git a/.env.production b/.env.production
deleted file mode 100644
index 440a14f9..00000000
--- a/.env.production
+++ /dev/null
@@ -1,4 +0,0 @@
-DIRACX_CLIENT_ID=interactive.public.short
-REDIRECT_URI=http://localhost:3000/dashboard/#authentication-callback
-DEFAULT_SCOPE="openid profile email api offline_access"
-NEXT_PUBLIC_DIRACX_URL=https://demo.duendesoftware.com
diff --git a/.github/workflows/containerised.yml b/.github/workflows/containerised.yml
index 1b15fd3e..24328c1f 100644
--- a/.github/workflows/containerised.yml
+++ b/.github/workflows/containerised.yml
@@ -27,5 +27,5 @@ jobs:
with:
context: .
push: ${{ github.event_name == 'push' && github.repository == 'DIRACGrid/diracx-web' && github.ref_name == 'main' }}
- tags: ghcr.io/diracgrid/diracx-web/client:latest
+ tags: ghcr.io/diracgrid/diracx-web/static:latest
platforms: linux/amd64,linux/arm64
diff --git a/Dockerfile b/Dockerfile
index 3f3e4cd2..4fcf6992 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,23 +1,16 @@
-FROM node:16-alpine
-EXPOSE 3000
-
-# Set the working directory in the container
+# Minimize the size and complexity of the final Docker image by separating the
+# build stage and the runtime stage into two different steps
+FROM node:16-alpine AS build
WORKDIR /app
-
-# Copy package.json and package-lock.json to the working directory
+# Install the project dependencies
COPY package*.json ./
-
-# Install project dependencies
-RUN npm install
-
+RUN npm ci
# Copy the rest of the application to the working directory
COPY . .
+# Build the static export with telemetry disabled (https://nextjs.org/telemetry)
+RUN NEXT_TELEMETRY_DISABLED=1 npm run build
-# Disable telemetry. Further details: https://nextjs.org/telemetry
-ENV NEXT_TELEMETRY_DISABLED 1
-
-# Build the Next.js app for production
-RUN npm run build
-
-# Define the command to run the app
-CMD [ "npm", "start" ]
+# Copy the website from the previous container to a Nginx container
+FROM nginxinc/nginx-unprivileged:alpine
+EXPOSE 8080
+COPY --from=build /app/out /usr/share/nginx/html
diff --git a/next.config.js b/next.config.js
index 658404ac..8d7f01b5 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,4 +1,9 @@
/** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {
+ output: "export",
+ images: {
+ unoptimized: true,
+ },
+};
module.exports = nextConfig;
diff --git a/src/app/dashboard/jobmonitor/[id]/page.tsx b/src/app/dashboard/jobmonitor/[id]/page.tsx
deleted file mode 100644
index 01b7137e..00000000
--- a/src/app/dashboard/jobmonitor/[id]/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function Page({ params }: { params: { id: string } }) {
- return
Hello, Job Monitoring {params.id} Page!
;
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index aba44b2d..e4b1ce0a 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,21 +1,17 @@
import "./globals.css";
import { Inter } from "next/font/google";
import { OIDCProvider } from "@/components/auth/OIDCUtils";
-import { OidcConfiguration } from "@axa-fr/react-oidc";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
- title: "diracX",
+ title: "DiracX",
description: "Distributed Infrastructure with Remote Agent Controller",
};
-const configuration: OidcConfiguration = {
- client_id: process.env.DIRACX_CLIENT_ID || "",
- redirect_uri: process.env.REDIRECT_URI || "",
- scope: process.env.DEFAULT_SCOPE || "",
- authority: process.env.NEXT_PUBLIC_DIRACX_URL || "",
-};
+// Force an error if any components use dynamic functions or uncached data
+// as these won't work in the static export.
+export const dynamic = "error";
export default function RootLayout({
children,
@@ -25,7 +21,7 @@ export default function RootLayout({
return (
- {children}
+ {children}
);
diff --git a/src/components/auth/OIDCUtils.tsx b/src/components/auth/OIDCUtils.tsx
index 062a4b3e..1cf977fe 100644
--- a/src/components/auth/OIDCUtils.tsx
+++ b/src/components/auth/OIDCUtils.tsx
@@ -4,10 +4,10 @@ import {
OidcProvider,
OidcSecure,
} from "@axa-fr/react-oidc";
-import React from "react";
+import React, { useState, useEffect } from "react";
+import { useDiracxUrl } from "@/hooks/utils";
interface OIDCProviderProps {
- configuration: OidcConfiguration;
children: React.ReactNode;
}
@@ -30,11 +30,32 @@ export function OIDCProvider(props: OIDCProviderProps) {
},
};
};
+ const diracxUrl = useDiracxUrl();
+ const [configuration, setConfiguration] = useState(
+ null,
+ );
+
+ useEffect(() => {
+ if (diracxUrl !== null) {
+ setConfiguration((prevConfig) => ({
+ authority: diracxUrl,
+ // TODO: Figure out how to get this. Hardcode? Get from a /.well-known/diracx-configuration endpoint?
+ client_id: "myDIRACClientID",
+ // TODO: Get this from the /.well-known/openid-configuration endpoint
+ scope: "vo:diracAdmin",
+ redirect_uri: `${diracxUrl}/#authentication-callback`,
+ }));
+ }
+ }, [diracxUrl]);
+
+ if (configuration === null) {
+ return <>>;
+ }
return (
<>
{props.children}
diff --git a/src/hooks/jobs.tsx b/src/hooks/jobs.tsx
index dfc2b474..d511273a 100644
--- a/src/hooks/jobs.tsx
+++ b/src/hooks/jobs.tsx
@@ -1,5 +1,6 @@
import { useOidcAccessToken } from "@axa-fr/react-oidc";
import useSWR from "swr";
+import { useDiracxUrl } from "./utils";
const fetcher = (args: any[]) => {
const [url, accessToken] = args;
@@ -14,10 +15,15 @@ const fetcher = (args: any[]) => {
};
export function useJobs() {
+ const diracxUrl = useDiracxUrl();
const { accessToken } = useOidcAccessToken();
- const url = `${process.env.NEXT_PUBLIC_DIRACX_URL}/api/jobs/search?page=0&per_page=100`;
+ const url = `${diracxUrl}/api/jobs/search?page=0&per_page=100`;
const { data, error } = useSWR([url, accessToken], fetcher);
+ if (diracxUrl === null) {
+ return { data: null, error: "diracxUrl is null", isLoading: false };
+ }
+
return {
data,
error,
diff --git a/src/hooks/utils.tsx b/src/hooks/utils.tsx
new file mode 100644
index 00000000..12683886
--- /dev/null
+++ b/src/hooks/utils.tsx
@@ -0,0 +1,16 @@
+import { useEffect, useState } from "react";
+
+export function useDiracxUrl() {
+ const [diracxUrl, setDiracxUrl] = useState(null);
+
+ useEffect(() => {
+ // Ensure this runs on client side
+ if (typeof window !== "undefined") {
+ setDiracxUrl(
+ (prevConfig) => `${window.location.protocol}//${window.location.host}`,
+ );
+ }
+ }, []);
+
+ return diracxUrl;
+}