e.stopPropagation()}>
-
+ setDateValue(val)}
views={["year", "month", "day", "hours", "minutes", "seconds"]}
diff --git a/packages/diracx-web-components/src/components/shared/SearchBar/SearchField.tsx b/packages/diracx-web-components/src/components/shared/SearchBar/SearchField.tsx
index 110be77f..0bc322af 100644
--- a/packages/diracx-web-components/src/components/shared/SearchBar/SearchField.tsx
+++ b/packages/diracx-web-components/src/components/shared/SearchBar/SearchField.tsx
@@ -1,6 +1,6 @@
import { useState, useRef, useEffect } from "react";
-import { Autocomplete, TextField } from "@mui/material";
+import { Autocomplete, InputBase } from "@mui/material";
import {
SearchBarTokenEquation,
@@ -30,7 +30,7 @@ interface SearchFieldProps {
setInputValue: React.Dispatch>;
/** Reference to the input element */
- inputRef: React.RefObject;
+ inputRef: React.RefObject;
/** The current token equations */
tokenEquations: SearchBarTokenEquation[];
@@ -262,6 +262,9 @@ export default function SearchField({
}, 0);
}
+ // Calculate the width of the input field based on the input value length
+ const width = Math.min(Math.max(inputValue.length * 8 + 50, 150), 800);
+
const handleDateAccepted = (newValue: string | null) => {
if (newValue) {
handleTokenCreation(
@@ -300,64 +303,73 @@ export default function SearchField({
minWidth: "180px",
flexGrow: 1,
}}
+ loading={suggestionsLoading}
disableClearable={true}
options={suggestions.items}
value={inputValue}
onHighlightChange={(_e, option) => {
optionSelectedRef.current = option !== null;
}}
- loading={suggestionsLoading}
- renderInput={(params) => (
- ) => {
- if (e.key === "Enter" && inputValue && inputValue.trim()) {
- if (optionSelectedRef.current) {
- optionSelectedRef.current = false;
- return;
- }
- const { nature, type } = getTokenMetadata(
- inputValue.trim(),
- suggestions,
- previousToken,
- );
- // Always create token on Enter press, regardless of operator type
- handleTokenCreation(inputValue.trim(), nature, type);
- }
- if (e.key === "Backspace") {
- handleBackspaceKeyDown();
- }
+ onKeyDown={(e: React.KeyboardEvent) => {
+ if (e.key === "Enter" && inputValue && inputValue.trim()) {
+ if (optionSelectedRef.current) {
+ optionSelectedRef.current = false;
+ return;
+ }
+ const { nature, type } = getTokenMetadata(
+ inputValue.trim(),
+ suggestions,
+ previousToken,
+ );
+ // Always create token on Enter press, regardless of operator type
+ handleTokenCreation(inputValue.trim(), nature, type);
+ }
+ if (e.key === "Backspace") {
+ handleBackspaceKeyDown();
+ }
- if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
- handleArrowKeyDown(e);
- }
+ if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
+ handleArrowKeyDown(e);
+ }
- if (e.key === "Tab") {
- e.preventDefault();
- setInputValue((prev) => {
- const options = suggestions.items.filter((val) => {
- return val.toLowerCase().startsWith(prev.toLowerCase());
- });
- return options[0] || prev;
- });
- }
- if (e.key === "Escape") {
- setFocusedTokenIndex(null);
- setInputValue("");
- }
- }}
- />
- )}
+ if (e.key === "Tab") {
+ e.preventDefault();
+ setInputValue((prev) => {
+ const options = suggestions.items.filter((val) => {
+ return val.toLowerCase().startsWith(prev.toLowerCase());
+ });
+ return options[0] || prev;
+ });
+ }
+ if (e.key === "Escape") {
+ setFocusedTokenIndex(null);
+ setInputValue("");
+ }
+ }}
+ renderInput={(params) => {
+ const { InputProps: autoInputProps, inputProps } = params;
+
+ return (
+ {
+ const r = autoInputProps.ref;
+ if (typeof r === "function") r(node);
+ else if (r) r.current = node;
+ if (inputRef) inputRef.current = node;
+ }}
+ inputProps={{
+ ...inputProps,
+ style: { width: `${width}px` },
+ }}
+ />
+ );
+ }}
onChange={(_e, value: string | null) => {
if (value && value !== "") {
optionSelectedRef.current = true;
diff --git a/packages/diracx-web-components/src/components/shared/Sunburst/Sunburst.tsx b/packages/diracx-web-components/src/components/shared/Sunburst/Sunburst.tsx
index 38f1398d..5c34fa4b 100644
--- a/packages/diracx-web-components/src/components/shared/Sunburst/Sunburst.tsx
+++ b/packages/diracx-web-components/src/components/shared/Sunburst/Sunburst.tsx
@@ -73,8 +73,8 @@ export function Sunburst({
const finalColorScales = colorScales || defaultColorScale;
const svgRef = useRef(null);
- const tooltipRef: React.RefObject =
- useRef(null);
+ const tooltipRef: React.RefObject =
+ useRef(null);
const theme = useTheme();
diff --git a/packages/diracx-web-components/stories/SearchBar.stories.tsx b/packages/diracx-web-components/stories/SearchBar.stories.tsx
index 3f9f282a..a0fdf29c 100644
--- a/packages/diracx-web-components/stories/SearchBar.stories.tsx
+++ b/packages/diracx-web-components/stories/SearchBar.stories.tsx
@@ -1,7 +1,6 @@
import { Meta, StoryObj } from "@storybook/react";
import React, { useState } from "react";
import { Paper } from "@mui/material";
-import { action } from "@storybook/addon-actions";
import {
SearchBar,
SearchBarProps,
@@ -161,8 +160,8 @@ export const Default: Story = {
export const WithPrefilledTokens: Story = {
args: {
filters: sampleFilters,
- setFilters: action("setFilters"),
- searchFunction: action("searchTriggered"),
+ setFilters: () => {},
+ searchFunction: () => {},
allowKeyWordSearch: true,
},
render: (args) => {
diff --git a/packages/diracx-web-components/stories/mocks/contexts.mock.tsx b/packages/diracx-web-components/stories/mocks/contexts.mock.tsx
index 7febcab7..04bf9bab 100644
--- a/packages/diracx-web-components/stories/mocks/contexts.mock.tsx
+++ b/packages/diracx-web-components/stories/mocks/contexts.mock.tsx
@@ -33,7 +33,7 @@ export const JobMockProvider: React.FC = ({
jobHistory,
error = null,
isLoading = false,
-}): JSX.Element => {
+}) => {
return (
{children}
diff --git a/packages/diracx-web-components/stories/mocks/style.mock.ts b/packages/diracx-web-components/stories/mocks/style.mock.ts
new file mode 100644
index 00000000..f053ebf7
--- /dev/null
+++ b/packages/diracx-web-components/stories/mocks/style.mock.ts
@@ -0,0 +1 @@
+module.exports = {};
diff --git a/packages/diracx-web-components/test/SearchBar.test.tsx b/packages/diracx-web-components/test/SearchBar.test.tsx
index fc0d61a5..a6ed2396 100644
--- a/packages/diracx-web-components/test/SearchBar.test.tsx
+++ b/packages/diracx-web-components/test/SearchBar.test.tsx
@@ -72,13 +72,23 @@ describe("SearchBar", () => {
const searchInput = screen.getByPlaceholderText("Enter a category");
- // Create a category token
+ // Create a category token (Status)
await user.type(searchInput, "Status");
await user.keyboard("{Enter}");
- // Check if operator suggestions appear
+ // Focus operator input
const operatorInput = screen.getByPlaceholderText("Enter an operator");
- await user.type(operatorInput, "{downArrow}");
+ await user.click(operatorInput);
+
+ // Open the autocomplete popup
+ await user.keyboard("{ArrowDown}");
+
+ // Wait for the listbox to appear (ensures popup is open)
+ await waitFor(() => {
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
+ });
+
+ // Now expect "=" operator to be one of the suggestions
await waitFor(() => {
expect(screen.getByText("=")).toBeInTheDocument();
});
diff --git a/packages/diracx-web-components/tsconfig.json b/packages/diracx-web-components/tsconfig.json
index c6e0f02e..4cd818c2 100644
--- a/packages/diracx-web-components/tsconfig.json
+++ b/packages/diracx-web-components/tsconfig.json
@@ -26,13 +26,13 @@
"@testing-library/jest-dom"
]
},
- "include": ["src/global.d.ts", "**/*.ts", "**/*.tsx"],
+ "include": ["src/global.d.ts", "**/*.ts", "**/*.tsx",],
"exclude": [
"app",
"node_modules",
"dist",
"stories",
"tsup.config.ts",
- "jest.setup.ts"
+ "jest.setup.ts",
]
}
diff --git a/packages/diracx-web/eslint.config.js b/packages/diracx-web/eslint.config.js
index 6be6693d..4333fa97 100644
--- a/packages/diracx-web/eslint.config.js
+++ b/packages/diracx-web/eslint.config.js
@@ -46,7 +46,10 @@ export default [
"import/no-unused-modules": ["error"],
"import/no-namespace": ["error"],
"unused-imports/no-unused-imports": ["error"],
-
+ "import/no-unresolved": [
+ "error",
+ { ignore: ["@dirac-grid/diracx-web-components"] }, // We ignore this module because it is special
+ ],
"import/no-useless-path-segments": ["error"],
"react/destructuring-assignment": ["error", "always"],
diff --git a/packages/diracx-web/package.json b/packages/diracx-web/package.json
index d2463421..e4a08ef0 100644
--- a/packages/diracx-web/package.json
+++ b/packages/diracx-web/package.json
@@ -5,10 +5,10 @@
"type": "module",
"scripts": {
"dev": "next dev",
- "build": "next build",
+ "build": "next build --turbopack",
"test": "cypress open --config baseUrl=$DIRACX_URL",
"start": "next start",
- "lint": "next lint",
+ "lint": "eslint ./src",
"lint-staged": "lint-staged",
"ts-lint": "tsc -noEmit -incremental",
"postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public"
@@ -18,16 +18,17 @@
"@dirac-grid/diracx-web-components": "^0.1.0-a10",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
- "@mui/icons-material": "^6.4.2",
- "@mui/material": "^6.1.6",
+ "@mui/icons-material": "^7.3.1",
+ "@mui/material": "^7.3.1",
+ "@mui/utils": "^7.3.1",
"@types/node": "20.17.6",
- "@types/react": "18.3.12",
- "@types/react-dom": "18.3.1",
+ "@types/react": "^19.1.10",
+ "@types/react-dom": "^19.1.7",
"autoprefixer": "10.4.20",
- "next": "15.3.1",
+ "next": "^15.5.0",
"postcss": "8.5.1",
- "react": "^18.3.1",
- "react-dom": "^18.3.1",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
"server-only": "^0.0.1",
"sharp": "^0.33.3",
"swr": "^2.2.5"
@@ -38,7 +39,7 @@
"@eslint/js": "^9.14.0",
"@typescript-eslint/eslint-plugin": "^8.31.0",
"@typescript-eslint/parser": "^8.31.0",
- "cypress": "^14.2.1",
+ "cypress": "^15.0.0",
"eslint": "^9.14.0",
"eslint-config-next": "^15.0.2",
"eslint-config-prettier": "^10.0.1",
diff --git a/packages/diracx-web/test/e2e/loginOut.cy.ts b/packages/diracx-web/test/e2e/00_loginOut.cy.ts
similarity index 95%
rename from packages/diracx-web/test/e2e/loginOut.cy.ts
rename to packages/diracx-web/test/e2e/00_loginOut.cy.ts
index db192f25..7287f955 100644
--- a/packages/diracx-web/test/e2e/loginOut.cy.ts
+++ b/packages/diracx-web/test/e2e/00_loginOut.cy.ts
@@ -1,5 +1,7 @@
///
+// This file is named 00_loginOut.cy.ts because we want to run it first
+
// Make sure the user can login and logout
describe("Login and Logout", () => {
beforeEach(() => {
@@ -37,8 +39,7 @@ describe("Login and Logout", () => {
cy.get(":nth-child(1) > form > .dex-btn").click();
});
- // The user is redirected back to the /auth page
- cy.url().should("include", "/auth");
+ cy.wait(1000); // Wait for the page to load
// From now on the user is logged in
// The login buttton should not be present anymore
diff --git a/packages/diracx-web/tsconfig.json b/packages/diracx-web/tsconfig.json
index 6f57de34..b255aaef 100644
--- a/packages/diracx-web/tsconfig.json
+++ b/packages/diracx-web/tsconfig.json
@@ -20,7 +20,7 @@
}
],
"paths": {
- "@/*": ["./src/*"]
+ "@/*": ["./src/*"],
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
diff --git a/packages/extensions/package.json b/packages/extensions/package.json
index 1e7c4903..c184424d 100644
--- a/packages/extensions/package.json
+++ b/packages/extensions/package.json
@@ -9,7 +9,7 @@
"build": "next build",
"test": "cypress open --config baseUrl=$DIRACX_URL",
"start": "next start",
- "lint": "next lint",
+ "lint": "eslint ./src",
"lint-staged": "lint-staged",
"ts-lint": "tsc -noEmit -incremental",
"postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public"
@@ -17,24 +17,23 @@
"dependencies": {
"@axa-fr/react-oidc": "^7.24.0",
"@dirac-grid/diracx-web-components": "0.1.0-a10",
- "@mui/icons-material": "^6.4.2",
- "@mui/material": "^6.1.6",
- "@mui/utils": "^6.1.6",
- "@mui/x-date-pickers": "^7.28.3",
+ "@mui/icons-material": "^7.3.1",
+ "@mui/material": "^7.3.1",
+ "@mui/utils": "^7.3.1",
"@tanstack/react-table": "^8.20.5",
"autoprefixer": "10.4.20",
- "next": "15.3.1",
+ "next": "^15.5.0",
"postcss": "8.5.1",
- "react": "^18",
- "react-dom": "^18"
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1"
},
"devDependencies": {
"@eslint/compat": "^1.2.2",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.14.0",
"@types/node": "^20",
- "@types/react": "^18",
- "@types/react-dom": "^18",
+ "@types/react": "^19.1.10",
+ "@types/react-dom": "^19.1.7",
"cypress": "^14.2.1",
"eslint": "^9",
"eslint-config-next": "15.0.2",