diff --git a/drama-queen/.env b/drama-queen/.env
index 21693dee..20bd6111 100644
--- a/drama-queen/.env
+++ b/drama-queen/.env
@@ -1,7 +1,6 @@
VITE_QUEEN_URL=http://localhost:5001
VITE_QUEEN_V2_URL=http://localhost:5002
VITE_QUEEN_API_URL=
-VITE_AUTH_TYPE=
-VITE_KEYCLOAK_URL=
-VITE_KEYCLOAK_CLIENT_ID=
-VITE_KEYCLOAK_REALM=
+# If no environment variables for OIDC are provided, the application will use a mock OIDC.
+VITE_OIDC_ISSUER=
+VITE_OIDC_CLIENT_ID=
diff --git a/drama-queen/package.json b/drama-queen/package.json
index 741489da..43f3e875 100644
--- a/drama-queen/package.json
+++ b/drama-queen/package.json
@@ -24,6 +24,7 @@
"jwt-decode": "^3.1.2",
"keycloak-js": "^21.1.2",
"memoizee": "^0.4.15",
+ "oidc-spa": "^2.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1",
@@ -33,7 +34,7 @@
"zod": "^3.21.4"
},
"devDependencies": {
- "@inseefr/lunatic": "^2.4.10",
+ "@inseefr/lunatic": "^2.7.4",
"@types/node": "^20.3.3",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
diff --git a/drama-queen/src/App.tsx b/drama-queen/src/App.tsx
new file mode 100644
index 00000000..e35bf5cf
--- /dev/null
+++ b/drama-queen/src/App.tsx
@@ -0,0 +1,33 @@
+import { createCoreProvider } from "core";
+import { RequiresAuthentication } from "ui/auth";
+import { LoadingData } from "ui/pages/LoadingData";
+
+
+const { CoreProvider } = createCoreProvider({
+ "apiUrl": import.meta.env.VITE_API_URL,
+ "publicUrl": import.meta.env.BASE_URL,
+ "oidcParams": {
+ "issuerUri": import.meta.env.VITE_OIDC_ISSUER,
+ "clientId": import.meta.env.VITE_OIDC_CLIENT_ID,
+ },
+});
+
+export default function App() {
+ console.log("public", import.meta.env.BASE_URL)
+ return (
+ /*
+
+
+
+
+
+
+
+
+ */
+ Loading} >
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/drama-queen/src/bootstrap.tsx b/drama-queen/src/bootstrap.tsx
index 888a7c4d..59d1016f 100644
--- a/drama-queen/src/bootstrap.tsx
+++ b/drama-queen/src/bootstrap.tsx
@@ -1,39 +1,8 @@
-import { useState, useEffect } from "react";
-import { createCoreProvider } from "core";
import { createRoot } from "react-dom/client";
-import { RouterProvider } from "react-router-dom";
import { type RoutingStrategy, createRouter } from "ui/routing/createRouter";
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { injectLegacyEntryQueens } from "core/injectLegacyQueens";
-import { createAuthProvider } from "ui/auth";
-import { createQueenApiProvider } from "ui/queenApi";
-import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
-import { LoadingData } from "ui/pages/LoadingData";
+import App from "App";
-const queryClient = new QueryClient({});
-
-const { AuthProvider } = createAuthProvider({
- isMock: import.meta.env.VITE_AUTH_TYPE !== "OIDC",
- keycloakUrl: import.meta.env.VITE_KEYCLOAK_URL,
- clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID,
- realm: import.meta.env.VITE_KEYCLOAK_REALM,
- origin: window.location.origin + import.meta.env.BASE_URL
-});
-
-const { QueenApiProvider } = createQueenApiProvider({
- apiUrl: import.meta.env.VITE_QUEEN_API_URL
-});
-
-const { CoreProvider } = createCoreProvider({
- "apiUrl": import.meta.env.VITE_API_URL,
- "keycloakParams": {
- "url": import.meta.env.VITE_KEYCLOAK_URL,
- "clientId": import.meta.env.VITE_KEYCLOAK_CLIENT_ID,
- "realm": import.meta.env.VITE_KEYCLOAK_REALM,
- "origin": window.location.origin + import.meta.env.BASE_URL
- },
- "redirectUrl": import.meta.env.VITE_REDIRECT_URL,
-});
const mount = ({
mountPoint,
@@ -51,19 +20,7 @@ const mount = ({
const router = createRouter({ strategy: routingStrategy, initialPathname });
const root = createRoot(mountPoint);
root.render(
- /*
-
-
-
-
-
-
-
-
- */
- Loading} >
-
-
+
);
return () => queueMicrotask(() => root.unmount());
diff --git a/drama-queen/src/core/adapters/oidc/default.ts b/drama-queen/src/core/adapters/oidc/default.ts
new file mode 100644
index 00000000..4d6b7d0c
--- /dev/null
+++ b/drama-queen/src/core/adapters/oidc/default.ts
@@ -0,0 +1,16 @@
+import { Oidc } from "core/ports/Oidc";
+import { createOidc as createOidcSpa } from "oidc-spa";
+
+export async function createOidc(params: {
+ issuerUri: string;
+ clientId: string;
+ publicUrl: string;
+}): Promise {
+ const { issuerUri, clientId, publicUrl } = params;
+
+ return createOidcSpa({
+ issuerUri,
+ clientId,
+ publicUrl,
+ });
+}
diff --git a/drama-queen/src/core/adapters/oidc/mock.ts b/drama-queen/src/core/adapters/oidc/mock.ts
new file mode 100644
index 00000000..14429da7
--- /dev/null
+++ b/drama-queen/src/core/adapters/oidc/mock.ts
@@ -0,0 +1,33 @@
+import { Oidc } from "core/ports/Oidc";
+import { id } from "tsafe/id";
+
+export function createOidc(params: { isUserLoggedIn: boolean }): Oidc {
+ const common: Oidc.Common = {
+ params: {
+ issuerUri: "",
+ clientId: "",
+ },
+ };
+
+ if (!params.isUserLoggedIn) {
+ return id({
+ ...common,
+ isUserLoggedIn: false,
+ login: async (params: { doesCurrentHrefRequiresAuth: boolean }) => {
+ return new Promise(() => {});
+ },
+ });
+ }
+
+ return id({
+ ...common,
+ isUserLoggedIn: true,
+ getTokens: () => ({
+ accessToken: "",
+ idToken: "",
+ refreshToken: "",
+ refreshTokenExpirationTime: Infinity,
+ }),
+ renewTokens: () => Promise.reject("Not implemented"),
+ });
+}
diff --git a/drama-queen/src/core/queenApi/createApiClient.ts b/drama-queen/src/core/adapters/queenApi/default.ts
similarity index 87%
rename from drama-queen/src/core/queenApi/createApiClient.ts
rename to drama-queen/src/core/adapters/queenApi/default.ts
index 34c3e93e..54206427 100644
--- a/drama-queen/src/core/queenApi/createApiClient.ts
+++ b/drama-queen/src/core/adapters/queenApi/default.ts
@@ -3,25 +3,25 @@ import {
IdAndQuestionnaireIdSchema,
SurveyUnitSchema,
type SurveyUnitWithId,
-} from "core/model/surveyUnit";
+} from "core/ports/QueenApi/SurveyUnit";
import axios from "axios";
import memoize from "memoizee";
-import type { SurveyUnitData } from "core/model/surveyUnitData";
-import type { QueenApi } from "./QueenApi";
-import { type Campaign, CampaignSchema } from "core/model/campaing";
-import { type APIReturnedListOfSurvey } from "core/model/survey";
+import type { SurveyUnitData } from "core/ports/QueenApi/SurveyUnitData";
+import type { QueenApi } from "core/ports/QueenApi/QueenApi";
+import { type Campaign, CampaignSchema } from "core/ports/QueenApi/Campaing";
+import { type APIReturnedListOfSurvey } from "core/ports/QueenApi/Questionnaire";
import {
type Nomenclature,
NomenclatureSchema,
type RequiredNomenclatures,
RequiredNomenclaturesSchema,
-} from "core/model/nomenclature";
-import type { Paradata } from "core/model/paradata";
+} from "core/ports/QueenApi/Nomenclature";
+import type { Paradata } from "core/ports/QueenApi/Paradata";
export function createApiClient(params: {
apiUrl: string;
- getAccessToken: () => string | null;
-}) {
+ getAccessToken: () => string | undefined;
+}): QueenApi {
const { apiUrl, getAccessToken } = params;
const { axiosInstance } = (() => {
@@ -121,5 +121,5 @@ export function createApiClient(params: {
),
postParadata: (paradata) =>
axiosInstance.post(`/api/paradata`, paradata),
- } satisfies QueenApi;
+ };
}
diff --git a/drama-queen/src/core/queenApi/createMockApiClient.ts b/drama-queen/src/core/adapters/queenApi/mock.ts
similarity index 93%
rename from drama-queen/src/core/queenApi/createMockApiClient.ts
rename to drama-queen/src/core/adapters/queenApi/mock.ts
index 7925faff..70f82bc4 100644
--- a/drama-queen/src/core/queenApi/createMockApiClient.ts
+++ b/drama-queen/src/core/adapters/queenApi/mock.ts
@@ -1,7 +1,7 @@
-import type { QueenApi } from "./QueenApi";
+import type { QueenApi } from "core/ports/QueenApi/QueenApi";
import { surveySample } from "./mockData/surveySample";
-export function createMockApiClient() {
+export function createApiClient(): QueenApi {
return {
getSurveyUnitsIdsAndQuestionnaireIdsByCampaign: (_idCampaign) =>
Promise.resolve([{ id: "id", questionnaireId: "questionnaireId" }]),
@@ -25,7 +25,7 @@ export function createMockApiClient() {
getNomenclature: (idNomenclature) =>
Promise.resolve([{ id: `${idNomenclature}`, label: "label" }]),
postParadata: (paradata) => console.log("postParadata", paradata),
- } satisfies QueenApi;
+ };
}
function createSUMocked(props: { idSu?: string; idCampaign?: string }) {
diff --git a/drama-queen/src/core/queenApi/mockData/surveySample.ts b/drama-queen/src/core/adapters/queenApi/mockData/surveySample.ts
similarity index 97%
rename from drama-queen/src/core/queenApi/mockData/surveySample.ts
rename to drama-queen/src/core/adapters/queenApi/mockData/surveySample.ts
index 32d3dc64..0daf7651 100644
--- a/drama-queen/src/core/queenApi/mockData/surveySample.ts
+++ b/drama-queen/src/core/adapters/queenApi/mockData/surveySample.ts
@@ -1,4 +1,4 @@
-import type { Questionnaire } from "core/model/survey";
+import type { Questionnaire } from "core/ports/QueenApi/Questionnaire";
export const surveySample = {
id: "lk9s32o5",
diff --git a/drama-queen/src/core/checkLunaticVersion/isQueenV2Survey.ts b/drama-queen/src/core/checkLunaticVersion/isQueenV2Survey.ts
index aff3507e..b6e23483 100644
--- a/drama-queen/src/core/checkLunaticVersion/isQueenV2Survey.ts
+++ b/drama-queen/src/core/checkLunaticVersion/isQueenV2Survey.ts
@@ -1,5 +1,5 @@
import axios from "axios";
-import { Questionnaire } from "core/model/survey";
+import { Questionnaire } from "core/ports/QueenApi/Questionnaire";
const lunaticModelVersionBreaking = "2.2.10";
diff --git a/drama-queen/src/core/indexedDb/tables/paradata.ts b/drama-queen/src/core/indexedDb/tables/paradata.ts
index 6649d397..e2550fe3 100644
--- a/drama-queen/src/core/indexedDb/tables/paradata.ts
+++ b/drama-queen/src/core/indexedDb/tables/paradata.ts
@@ -1,4 +1,4 @@
-import type { Paradata } from "core/model/paradata";
+import type { Paradata } from "core/ports/QueenApi/Paradata";
import type { Table } from "dexie";
export type ParadataTable = {
diff --git a/drama-queen/src/core/indexedDb/tables/surveyUnit.ts b/drama-queen/src/core/indexedDb/tables/surveyUnit.ts
index 8603132b..fd3e79ed 100644
--- a/drama-queen/src/core/indexedDb/tables/surveyUnit.ts
+++ b/drama-queen/src/core/indexedDb/tables/surveyUnit.ts
@@ -1,4 +1,4 @@
-import type { SurveyUnitWithId } from "core/model/surveyUnit";
+import type { SurveyUnitWithId } from "core/ports/QueenApi/SurveyUnit";
import type { Table } from "dexie";
export type SurveyUnitTable = {
diff --git a/drama-queen/src/core/keycloakClient/Oidc.ts b/drama-queen/src/core/keycloakClient/Oidc.ts
deleted file mode 100644
index a7e9dc11..00000000
--- a/drama-queen/src/core/keycloakClient/Oidc.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-export declare type Oidc = Oidc.LoggedIn | Oidc.NotLoggedIn;
-
-export declare namespace Oidc {
- export type NotLoggedIn = {
- isUserLoggedIn: false;
- login: () => Promise;
- };
-
- export type LoggedIn = {
- isUserLoggedIn: true;
- renewToken(): Promise;
- getAccessToken: () => string;
- };
-}
-
-export type KeycloakParams = {
- url: string;
- realm: string;
- origin?: string;
- clientId: string;
- log?: typeof console.log;
-};
diff --git a/drama-queen/src/core/keycloakClient/createKeycloakClient.ts b/drama-queen/src/core/keycloakClient/createKeycloakClient.ts
deleted file mode 100644
index 13313eca..00000000
--- a/drama-queen/src/core/keycloakClient/createKeycloakClient.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import type { KeycloakParams, Oidc } from "./Oidc";
-import Keycloak from "keycloak-js";
-import { assert } from "tsafe/assert";
-import { decodeJwt } from "core/tools/jwt";
-import { listenActivity } from "core/tools/listenActivity";
-
-export async function createKeycloakClient(params: KeycloakParams) {
- const {
- url,
- realm,
- clientId,
- origin,
- log,
- } = params;
-
- const keycloakInstance = new Keycloak({ url, realm, clientId });
-
- const isAuthenticated = await keycloakInstance.init({
- onLoad: "check-sso",
- silentCheckSsoRedirectUri: `${origin}/silent-sso.html`,
- checkLoginIframe: false,
- });
-
- const login = async () => {
- await keycloakInstance.login({ redirectUri: window.location.href });
- return new Promise(() => {});
- };
-
- if (!isAuthenticated) {
- return {
- isUserLoggedIn: false,
- login,
- } satisfies Oidc;
- }
-
- assert(keycloakInstance.token !== undefined);
-
- let currentAccessToken = keycloakInstance.token;
-
- const oidc = {
- isUserLoggedIn: true,
- getAccessToken: () => currentAccessToken,
- renewToken: async () => {
- await keycloakInstance.updateToken(-1);
-
- assert(keycloakInstance.token !== undefined);
-
- currentAccessToken = keycloakInstance.token;
- },
- } satisfies Oidc;
-
- (function callee() {
- const msBeforeExpiration =
- getAccessTokenExpirationTime(currentAccessToken) - Date.now();
-
- setTimeout(async () => {
- log?.(
- `OIDC access token will expire in ${minValiditySecond} seconds, waiting for user activity before renewing`
- );
-
- await listenActivity();
-
- log?.("User activity detected. Refreshing access token now");
-
- const error = await keycloakInstance.updateToken(-1).then(
- () => undefined,
- (error: Error) => error
- );
-
- if (error) {
- log?.("Can't refresh OIDC access token, getting a new one");
- //NOTE: Never resolves
- await login();
- }
-
- assert(keycloakInstance.token !== undefined);
-
- currentAccessToken = keycloakInstance.token;
-
- callee();
- }, msBeforeExpiration - minValiditySecond * 1000);
- })();
-
- return oidc;
-}
-
-const minValiditySecond = 25;
-
-function getAccessTokenExpirationTime(accessToken: string): number {
- return decodeJwt<{ exp: number }>(accessToken)["exp"] * 1000;
-}
diff --git a/drama-queen/src/core/keycloakClient/dummyOidcClient.ts b/drama-queen/src/core/keycloakClient/dummyOidcClient.ts
deleted file mode 100644
index d313aa48..00000000
--- a/drama-queen/src/core/keycloakClient/dummyOidcClient.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Oidc } from "./Oidc";
-
-export const dummyOidcClient: Oidc.LoggedIn = {
- isUserLoggedIn: true,
- getAccessToken: () =>
- "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
- renewToken: () => Promise.reject("Not implemented"),
-};
diff --git a/drama-queen/src/core/model/type-source.ts b/drama-queen/src/core/model/type-source.ts
deleted file mode 100644
index 7ae51ec8..00000000
--- a/drama-queen/src/core/model/type-source.ts
+++ /dev/null
@@ -1,347 +0,0 @@
-//TODO DELETE This file and use type from @inseefr/lunatic
-export type LabelType = { value: string; type: "VTL" | "VTL|MD" };
-
-export type ComponentTypeEnum =
- | "Sequence"
- | "Subsequence"
- | "RosterForLoop"
- | "Loop"
- | "Table"
- | "Input"
- | "InputNumber"
- | "Datepicker"
- | "CheckboxGroup"
- | "CheckboxOne"
- | "CheckboxBoolean"
- | "Radio"
- | "Dropdown"
- | "Textarea"
- | "FilterDescription"
- | "PairwiseLinks"
- | "Suggester"
- | "ComponentSet";
-
-export type ValuesType = {
- PREVIOUS: T | null;
- COLLECTED: T | null;
- FORCED: T | null;
- EDITED: T | null;
- INPUTED: T | null;
-};
-
-export type ValuesTypeArray = {
- PREVIOUS: T[] | [null];
- COLLECTED: T[] | [null];
- FORCED: T[] | [null];
- EDITED: T[] | [null];
- INPUTED: T[] | [null];
-};
-
-export type DeclarationType = {
- id: string;
- declarationType:
- | "INSTRUCTION"
- | "COMMENT"
- | "HELP"
- | "CODECARD"
- | "WARNING"
- | "STATEMENT";
- position:
- | "AFTER_QUESTION_TEXT"
- | "AFTER_RESPONSE"
- | "BEFORE_QUESTION_TEXT"
- | "DETACHABLE";
- label: LabelType;
-};
-
-export type ConditionFilterType = LabelType & {
- bindingDependencies?: string[];
-};
-
-export enum Criticality {
- INFO = "INFO",
- WARN = "WARN",
- ERROR = "ERROR",
-}
-
-export enum TypeOfControl {
- FORMAT = "FORMAT",
- CONSISTENCY = "CONSISTENCY",
-}
-
-export enum ControlTypeEnum {
- roundabout = "roundabout",
- simple = "simple",
-}
-
-export type ControlType = {
- id: string;
- criticality: Criticality;
- typeOfControl: TypeOfControl;
- control: LabelType;
- errorMessage: LabelType;
- bindingDependencies: string[];
- type: ControlTypeEnum;
- iterations?: number;
-};
-
-export type ResponseType = { name: string };
-
-export type SequenceDescription = {
- label: LabelType;
- id: string;
- page: string;
-};
-
-export type Hierarchy = {
- sequence: SequenceDescription;
- subSequence?: SequenceDescription;
-};
-
-export type ComponentTypeBase = {
- label: LabelType;
- declarations?: DeclarationType[];
- conditionFilter: ConditionFilterType;
- controls?: ControlType[];
- id: string;
- bindingDependencies?: string[];
- hierarchy: Hierarchy;
- mandatory?: boolean;
- page: string;
-};
-export type ComponentType =
- | (ComponentTypeBase & ComponentSequenceType)
- | (ComponentTypeBase & ComponentSubSequenceType)
- | (ComponentTypeBase & ComponentRosterForLoopType)
- | (ComponentTypeBase & ComponentLoopType)
- | (ComponentTypeBase & ComponentTableType)
- | (ComponentTypeBase & ComponentNumberType)
- | (ComponentTypeBase & ComponentDatePickerType)
- | (ComponentTypeBase & ComponentCheckboxGroupType)
- | (ComponentTypeBase & ComponentCheckboxBooleanType)
- | (ComponentTypeBase & ComponentRadioType)
- | (ComponentTypeBase & ComponentFilterDescriptionType)
- | (ComponentTypeBase & ComponentDropdownType)
- | (ComponentTypeBase & ComponentPairWiseLinksType)
- | (ComponentTypeBase & ComponentRoundaboutType)
- | (ComponentTypeBase & ComponentSuggesterType)
- | (ComponentTypeBase & ComponentInputOrTextareaType)
- | (ComponentTypeBase & {
- componentType: "CheckboxOne";
- })
- | (ComponentTypeBase & ComponentComponentSetType);
-
-export type ComponentInputOrTextareaType = {
- componentType: "Input" | "Textarea";
- maxLength: number;
- missingResponse?: ResponseType;
- response: ResponseType;
-};
-export type ComponentSequenceType = {
- componentType: "Sequence";
-};
-
-export type ComponentSubSequenceType = {
- componentType: "Subsequence";
- gotoPage: string;
-};
-
-export type ComponentRoundaboutType = {
- componentType: "Roundabout";
- components: ComponentType[];
- iterations: LabelType;
- locked: boolean;
- expressions: Record;
-};
-
-export type ComponentRosterForLoopType = {
- componentType: "RosterForLoop";
- components: ComponentType[];
- lines: { min: LabelType; max: LabelType };
- header: {
- value: string;
- label: LabelType | string;
- options: { value: string; label: LabelType }[];
- colspan?: number;
- rowspan?: number;
- }[];
- body: {
- label?: LabelType;
- value?: string;
- format?: string;
- dateFormat?: string;
- unit?: string;
- options: { value: string; label: LabelType }[];
- response: ResponseType;
- bindingDependencies: string[];
- componentType?: ComponentTypeEnum;
- maxLength?: number;
- min?: number;
- max?: number;
- decimals?: number;
- colspan?: number;
- rowspan?: number;
- id?: string;
- }[];
- positioning: "HORIZONTAL";
-};
-
-export type ComponentLoopType = {
- componentType: "Loop";
- loopDependencies: string[];
- lines: { min: LabelType; max: LabelType };
- components: ComponentType[];
- iterations: LabelType;
- maxPage: string;
- depth: number;
- paginatedLoop: boolean;
-};
-
-export type ComponentTableType = {
- componentType: "Table";
- lines: ComponentRosterForLoopType["lines"];
- header: ComponentRosterForLoopType["header"];
- body: ComponentRosterForLoopType["body"];
- positioning: ComponentRosterForLoopType["positioning"];
-};
-
-export type ComponentNumberType = {
- componentType: "InputNumber";
- unit: string;
- response: ResponseType;
- min?: number;
- max?: number;
- decimals?: number;
-};
-
-export type ComponentDatePickerType = {
- componentType: "Datepicker";
- dateFormat: string;
- response: ResponseType;
- min?: string;
- max?: string;
-};
-
-export type ComponentCheckboxGroupType = {
- componentType: "CheckboxGroup";
- responses: Array<{
- label: LabelType;
- response: ResponseType;
- id: string;
- }>;
-};
-
-export type ComponentCheckboxBooleanType = {
- componentType: "CheckboxBoolean";
- response: ResponseType;
- missingResponse?: ResponseType;
-};
-
-export type ComponentRadioType = {
- componentType: "Radio";
- options: { value: string; label: LabelType }[];
- response: ResponseType;
- missingResponse?: ResponseType;
-};
-
-export type ComponentDropdownType = {
- componentType: "Dropdown";
- options: { value: string; label: LabelType }[];
- response: ResponseType;
- missingResponse?: ResponseType;
-};
-
-export type ComponentFilterDescriptionType = {
- componentType: "FilterDescription";
- filterDescription: boolean;
-};
-
-export type ComponentPairWiseLinksType = {
- componentType: "PairwiseLinks";
- xAxisIterations: LabelType;
- yAxisIterations: LabelType;
- symLinks: {
- [variableName: string]: Record;
- };
-};
-
-export type ComponentComponentSetType = {
- componentType: "ComponentSet";
- components: ComponentType[];
-};
-
-export type ComponentSuggesterType = {
- componentType: "Suggester";
- storeName: string;
-};
-
-export type SuggesterType = {
- name: string;
- fields: {
- name: string;
- min?: number;
- rules?: string[];
- language?: string;
- stemmer?: boolean;
- synonyms: { source: string; target: string[] }[];
- }[];
- max: number;
- stopWords?: string;
- order?: { field: string; type: string };
- queryParser: {
- type: string;
- params: { language: string; pattern: string; min?: number };
- };
- url?: string;
- version: number;
- meloto?: boolean;
-};
-
-export type Variable =
- | {
- variableType: "EXTERNAL";
- name: string;
- value: unknown;
- }
- | {
- variableType: "COLLECTED";
- name: string;
- values: ValuesType | ValuesTypeArray;
- }
- | {
- variableType: "CALCULATED";
- name: string;
- expression: LabelType;
- bindingDependencies: string[];
- inFilter: string;
- shapeFrom?: string;
- };
-
-export type LunaticSource = {
- id: string;
- modele?: string;
- enoCoreVersion?: string;
- lunaticModelVersion?: string;
- generatingDate?: string;
- missing?: boolean;
- pagination?: "question" | "sequence" | "subsequence";
- maxPage: string;
- label: LabelType;
- components: ComponentType[];
- variables: Variable[];
- suggesters?: SuggesterType[];
- cleaning: {
- [variableName: string]: {
- [variableName: string]: string;
- };
- };
- missingBlock: {
- [variableName: string]: string[];
- };
- resizing: {
- [variableName: string]: {
- size: string; // VTL Expression
- variables: string[];
- };
- };
-};
diff --git a/drama-queen/src/core/ports/Oidc.ts b/drama-queen/src/core/ports/Oidc.ts
new file mode 100644
index 00000000..c6cbe4b8
--- /dev/null
+++ b/drama-queen/src/core/ports/Oidc.ts
@@ -0,0 +1,28 @@
+export declare type Oidc = Oidc.LoggedIn | Oidc.NotLoggedIn;
+
+export declare namespace Oidc {
+ export type Common = {
+ params: {
+ issuerUri: string;
+ clientId: string;
+ };
+ };
+
+ export type NotLoggedIn = Common & {
+ isUserLoggedIn: false;
+ login: (params: { doesCurrentHrefRequiresAuth: boolean }) => Promise;
+ };
+
+ export type LoggedIn = Common & {
+ isUserLoggedIn: true;
+ renewTokens(): Promise;
+ getTokens: () => Tokens;
+ };
+
+ export type Tokens = {
+ accessToken: string;
+ idToken: string;
+ refreshToken: string;
+ refreshTokenExpirationTime: number;
+ };
+}
diff --git a/drama-queen/src/core/model/campaing.ts b/drama-queen/src/core/ports/QueenApi/Campaing.ts
similarity index 100%
rename from drama-queen/src/core/model/campaing.ts
rename to drama-queen/src/core/ports/QueenApi/Campaing.ts
diff --git a/drama-queen/src/core/model/nomenclature.ts b/drama-queen/src/core/ports/QueenApi/Nomenclature.ts
similarity index 100%
rename from drama-queen/src/core/model/nomenclature.ts
rename to drama-queen/src/core/ports/QueenApi/Nomenclature.ts
diff --git a/drama-queen/src/core/model/paradata.ts b/drama-queen/src/core/ports/QueenApi/Paradata.ts
similarity index 100%
rename from drama-queen/src/core/model/paradata.ts
rename to drama-queen/src/core/ports/QueenApi/Paradata.ts
diff --git a/drama-queen/src/core/queenApi/QueenApi.ts b/drama-queen/src/core/ports/QueenApi/QueenApi.ts
similarity index 79%
rename from drama-queen/src/core/queenApi/QueenApi.ts
rename to drama-queen/src/core/ports/QueenApi/QueenApi.ts
index c2937b26..8ddcbe77 100644
--- a/drama-queen/src/core/queenApi/QueenApi.ts
+++ b/drama-queen/src/core/ports/QueenApi/QueenApi.ts
@@ -1,14 +1,14 @@
-import type { Campaign } from "core/model/campaing";
+import type { Campaign } from "core/ports/QueenApi/Campaing";
import type {
Nomenclature,
RequiredNomenclatures,
-} from "core/model/nomenclature";
-import type { Paradata } from "core/model/paradata";
-import type { Questionnaire } from "core/model/survey";
+} from "core/ports/QueenApi/Nomenclature";
+import type { Paradata } from "core/ports/QueenApi/Paradata";
+import type { Questionnaire } from "core/ports/QueenApi/Questionnaire";
import type {
IdAndQuestionnaireId,
SurveyUnitWithId,
-} from "core/model/surveyUnit";
+} from "core/ports/QueenApi/SurveyUnit";
export type QueenApi = {
getSurveyUnitsIdsAndQuestionnaireIdsByCampaign: (
diff --git a/drama-queen/src/core/model/survey.ts b/drama-queen/src/core/ports/QueenApi/Questionnaire.ts
similarity index 65%
rename from drama-queen/src/core/model/survey.ts
rename to drama-queen/src/core/ports/QueenApi/Questionnaire.ts
index 08d1dbe9..2d73f04d 100644
--- a/drama-queen/src/core/model/survey.ts
+++ b/drama-queen/src/core/ports/QueenApi/Questionnaire.ts
@@ -1,6 +1,6 @@
-//import type { LunaticSource } from "@inseefr/lunatic/lib/src/use-lunatic/type-source";
-import { LunaticSource } from "./type-source";
+import { LunaticSource } from "@inseefr/lunatic";
+
/**
* We dont provide zod schema for this type because Survey are very large
@@ -10,6 +10,6 @@ export type Questionnaire = LunaticSource;
/**
* Utility type because API does not return Survey directly
- * Cause by /api/campaign/
+ * Caused by /api/campaign/
*/
export type APIReturnedListOfSurvey = { value: LunaticSource };
diff --git a/drama-queen/src/core/model/surveyUnit.ts b/drama-queen/src/core/ports/QueenApi/SurveyUnit.ts
similarity index 93%
rename from drama-queen/src/core/model/surveyUnit.ts
rename to drama-queen/src/core/ports/QueenApi/SurveyUnit.ts
index 1dff7592..0e41c60f 100644
--- a/drama-queen/src/core/model/surveyUnit.ts
+++ b/drama-queen/src/core/ports/QueenApi/SurveyUnit.ts
@@ -1,5 +1,5 @@
import { z } from "zod";
-import { SurveyUnitDataSchema } from "./surveyUnitData";
+import { SurveyUnitDataSchema } from "./SurveyUnitData";
export const IdAndQuestionnaireIdSchema = z.object({
id: z.string(),
diff --git a/drama-queen/src/core/model/surveyUnitData.ts b/drama-queen/src/core/ports/QueenApi/SurveyUnitData.ts
similarity index 100%
rename from drama-queen/src/core/model/surveyUnitData.ts
rename to drama-queen/src/core/ports/QueenApi/SurveyUnitData.ts
diff --git a/drama-queen/src/core/setup.ts b/drama-queen/src/core/setup.ts
index 8b61bbbf..55d79a3c 100644
--- a/drama-queen/src/core/setup.ts
+++ b/drama-queen/src/core/setup.ts
@@ -1,44 +1,68 @@
-
import { createCoreFromUsecases } from "redux-clean-architecture";
import type { GenericCreateEvt, GenericThunks } from "redux-clean-architecture";
-import { createApiClient } from "./queenApi/createApiClient";
-import { createKeycloakClient } from "./keycloakClient/createKeycloakClient";
import { usecases } from "./usecases";
type CoreParams = {
- apiUrl: string;
- keycloakParams: {
- url: string;
+ apiUrl: string;
+ publicUrl: string;
+ oidcParams:
+ | {
+ issuerUri: string;
clientId: string;
- realm: string;
- origin?: string;
- };
- redirectUrl: string;
+ }
+ | undefined;
};
export async function createCore(params: CoreParams) {
+ const { apiUrl, publicUrl, oidcParams } = params;
- const { apiUrl, keycloakParams } = params;
+ const oidc = await (async () => {
+ if (oidcParams === undefined) {
+ const { createOidc } = await import("core/adapters/oidc/mock");
+ return createOidc({ isUserLoggedIn: false });
+ }
+ const { createOidc } = await import("core/adapters/oidc/default");
+ return createOidc({
+ issuerUri: oidcParams.issuerUri,
+ clientId: oidcParams.clientId,
+ publicUrl: publicUrl,
+ });
+ })();
- const oidc = await createKeycloakClient(keycloakParams);
+ const queenApi = await (async () => {
+ if (apiUrl === "") {
+ // When no apiUrl is provided, we use the mock
+ const { createApiClient } = await import("core/adapters/queenApi/mock");
+ return createApiClient();
+ }
- const queenApi = createApiClient({
- apiUrl,
- "getAccessToken": !oidc.isUserLoggedIn ?
- (() => null) :
- (() => oidc.getAccessToken())
- });
+ const { createApiClient } = await import("core/adapters/queenApi/default");
- const core = createCoreFromUsecases({
- "thunksExtraArgument": {
- "coreParams": params,
- oidc,
- queenApi
- },
- usecases
+ return createApiClient({
+ apiUrl,
+ getAccessToken: () => {
+ if (oidc === undefined) {
+ return undefined;
+ }
+
+ if (!oidc.isUserLoggedIn) {
+ return undefined;
+ }
+ return oidc.getTokens().accessToken;
+ },
});
+ })();
+
+ const core = createCoreFromUsecases({
+ thunksExtraArgument: {
+ coreParams: params,
+ oidc,
+ queenApi,
+ },
+ usecases,
+ });
- return core;
+ return core;
}
type Core = Awaited>;
@@ -47,4 +71,4 @@ export type State = ReturnType;
export type Thunks = GenericThunks;
-export type CreateEvt = GenericCreateEvt;
\ No newline at end of file
+export type CreateEvt = GenericCreateEvt;
diff --git a/drama-queen/src/core/usecases/index.ts b/drama-queen/src/core/usecases/index.ts
index 11f1ed30..c92478a9 100644
--- a/drama-queen/src/core/usecases/index.ts
+++ b/drama-queen/src/core/usecases/index.ts
@@ -1,4 +1,3 @@
-
import * as loadingData from "./loadingData";
-
-export const usecases = { loadingData };
\ No newline at end of file
+import * as userAuthentication from "./userAuthentication";
+export const usecases = { loadingData, userAuthentication };
diff --git a/drama-queen/src/core/usecases/loadingData.ts b/drama-queen/src/core/usecases/loadingData.ts
index 9ca8ff0a..9d9622a0 100644
--- a/drama-queen/src/core/usecases/loadingData.ts
+++ b/drama-queen/src/core/usecases/loadingData.ts
@@ -4,175 +4,154 @@ import type { PayloadAction } from "@reduxjs/toolkit";
import type { State as RootState } from "../setup";
import { id } from "tsafe/id";
import { createSelector } from "@reduxjs/toolkit";
-import { Evt } from "evt";
+import { Evt } from "evt";
export type State = State.NotRunning | State.Running;
export namespace State {
- export type NotRunning = {
- stateDescription: "not running";
- };
- export type Running = {
- stateDescription: "running";
- surveyUnitProgress: number;
- nomenclatureProgress: number;
- surveyProgress: number;
- };
-
+ export type NotRunning = {
+ stateDescription: "not running";
+ };
+ export type Running = {
+ stateDescription: "running";
+ surveyUnitProgress: number;
+ nomenclatureProgress: number;
+ surveyProgress: number;
+ };
}
export const name = "loadingData";
export const { reducer, actions } = createSlice({
- name,
- "initialState": id({
- "stateDescription": "not running"
- }),
- "reducers": {
- "progressUpdated": (state, { payload }: PayloadAction<{
- surveyUnitProgress: number;
- nomenclatureProgress: number;
- surveyProgress: number;
- }>) => {
- const {
- nomenclatureProgress,
- surveyProgress,
- surveyUnitProgress
- } = payload;
-
- return {
- "stateDescription": "running",
- nomenclatureProgress,
- surveyProgress,
- surveyUnitProgress
- };
- },
- "completed": (state, { payload }: PayloadAction<{
- redirectUrl: string;
- }>) => {
- return { "stateDescription": "not running" }
- },
- }
+ name,
+ initialState: id({
+ stateDescription: "not running",
+ }),
+ reducers: {
+ progressUpdated: (
+ state,
+ {
+ payload,
+ }: PayloadAction<{
+ surveyUnitProgress: number;
+ nomenclatureProgress: number;
+ surveyProgress: number;
+ }>
+ ) => {
+ const { nomenclatureProgress, surveyProgress, surveyUnitProgress } =
+ payload;
+
+ return {
+ stateDescription: "running",
+ nomenclatureProgress,
+ surveyProgress,
+ surveyUnitProgress,
+ };
+ },
+ completed: (state) => {
+ return { stateDescription: "not running" };
+ },
+ },
});
export const thunks = {
- "start":
- () =>
- async (...args) => {
- const [dispatch, getState, { coreParams }] = args;
-
- {
- const state = getState()[name];
-
- if (state.stateDescription === "running") {
- return;
- }
-
- }
-
- dispatch(
- actions.progressUpdated({
- "nomenclatureProgress": 0,
- "surveyProgress": 0,
- "surveyUnitProgress": 0
- })
- );
-
- for (const progress of [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) {
- await new Promise((resolve) => setTimeout(resolve, 1000));
-
- dispatch(
- actions.progressUpdated({
- "nomenclatureProgress": progress,
- "surveyProgress": progress,
- "surveyUnitProgress": progress
- })
- );
-
- }
-
- dispatch(
- actions.completed({
- "redirectUrl": coreParams.redirectUrl
- })
- );
-
- }
-} satisfies Thunks;
+ start:
+ () =>
+ async (...args) => {
+ const [dispatch, getState] = args;
-export const selectors = (() => {
- const runningState = (rootState: RootState) => {
- const state = rootState[name];
+ {
+ const state = getState()[name];
- if (state.stateDescription === "not running") {
- return undefined;
- }
- return state;
-
- };
-
- const isRunning = createSelector(
- runningState,
- state => state !== undefined
- );
-
- const surveyUnitProgress = createSelector(
- runningState,
- state => {
- if (state === undefined) {
- return undefined;
- }
- return state.surveyUnitProgress;
+ if (state.stateDescription === "running") {
+ return;
}
- );
-
- const nomenclatureProgress = createSelector(
- runningState,
- state => {
- if (state === undefined) {
- return undefined;
- }
- return state.nomenclatureProgress;
- }
- );
-
- const surveyProgress = createSelector(
- runningState,
- state => {
- if (state === undefined) {
- return undefined;
- }
- return state.surveyProgress;
- }
- );
-
- return {
- isRunning,
- surveyUnitProgress,
- nomenclatureProgress,
- surveyProgress
- };
-
-})();
+ }
+
+ dispatch(
+ actions.progressUpdated({
+ nomenclatureProgress: 0,
+ surveyProgress: 0,
+ surveyUnitProgress: 0,
+ })
+ );
+
+ for (const progress of [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) {
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+
+ dispatch(
+ actions.progressUpdated({
+ nomenclatureProgress: progress,
+ surveyProgress: progress,
+ surveyUnitProgress: progress,
+ })
+ );
+ }
+
+ dispatch(actions.completed());
+ },
+} satisfies Thunks;
+export const selectors = (() => {
+ const runningState = (rootState: RootState) => {
+ const state = rootState[name];
-export const createEvt = (({ evtAction }) =>{
+ if (state.stateDescription === "not running") {
+ return undefined;
+ }
+ return state;
+ };
- const evt = Evt.create<{
- action: "redirect";
- url: string;
- }>();
+ const isRunning = createSelector(
+ runningState,
+ (state) => state !== undefined
+ );
- evtAction
- .pipe(data => data.sliceName === name && data.actionName === "completed" ? [data.payload.redirectUrl] : null)
- .attach((redirectUrl) => {
+ const surveyUnitProgress = createSelector(runningState, (state) => {
+ if (state === undefined) {
+ return undefined;
+ }
+ return state.surveyUnitProgress;
+ });
- evt.post({
- "action": "redirect",
- "url": redirectUrl
- });
- });
+ const nomenclatureProgress = createSelector(runningState, (state) => {
+ if (state === undefined) {
+ return undefined;
+ }
+ return state.nomenclatureProgress;
+ });
- return evt;
+ const surveyProgress = createSelector(runningState, (state) => {
+ if (state === undefined) {
+ return undefined;
+ }
+ return state.surveyProgress;
+ });
+
+ return {
+ isRunning,
+ surveyUnitProgress,
+ nomenclatureProgress,
+ surveyProgress,
+ };
+})();
-}) satisfies CreateEvt;
\ No newline at end of file
+export const createEvt = (({ evtAction }) => {
+ const evt = Evt.create<{
+ action: "redirect";
+ }>();
+
+ evtAction
+ .pipe((action) =>
+ action.sliceName === name && action.actionName === "completed"
+ ? [action]
+ : null
+ )
+ .attach(() => {
+ evt.post({
+ action: "redirect",
+ });
+ });
+
+ return evt;
+}) satisfies CreateEvt;
diff --git a/drama-queen/src/core/usecases/userAuthentication.ts b/drama-queen/src/core/usecases/userAuthentication.ts
new file mode 100644
index 00000000..76461aa9
--- /dev/null
+++ b/drama-queen/src/core/usecases/userAuthentication.ts
@@ -0,0 +1,24 @@
+import { assert } from "tsafe/assert";
+import { Thunks } from "core/setup";
+
+export const name = "userAuthentication";
+
+export const reducer = null;
+
+export const thunks = {
+ getIsUserLoggedIn:
+ () =>
+ (...args): boolean => {
+ const [, , { oidc }] = args;
+ return oidc.isUserLoggedIn;
+ },
+ login:
+ () =>
+ (...args): Promise => {
+ const [, , { oidc }] = args;
+
+ assert(!oidc.isUserLoggedIn);
+
+ return oidc.login({ doesCurrentHrefRequiresAuth: true });
+ },
+} satisfies Thunks;
diff --git a/drama-queen/src/ui/auth.tsx b/drama-queen/src/ui/auth.tsx
index e2826e9a..cdac10a1 100644
--- a/drama-queen/src/ui/auth.tsx
+++ b/drama-queen/src/ui/auth.tsx
@@ -1,72 +1,17 @@
-import { ReactNode, createContext, useContext, useEffect, useState } from "react";
-import { Oidc } from "core/keycloakClient/Oidc";
-import { createKeycloakClient } from "core/keycloakClient/createKeycloakClient";
-import { dummyOidcClient } from "core/keycloakClient/dummyOidcClient";
-import { useQuery } from "@tanstack/react-query"
+import { ReactNode } from "react";
+import { useCoreFunctions, useCoreState } from "core";
-const context = createContext(undefined);
-
-export function useOidc() {
- const value = useContext(context);
- if (value === undefined) throw new Error("You must wrap your component inside AuthProvider");
- return value;
-}
-
-export function useLoggedInOidc(): Oidc.LoggedIn {
- const oidc = useOidc();
- if (!oidc.isUserLoggedIn) throw new Error("You wrap your component inside RequiresAuthentication to use this hook")
- return oidc;
-
-}
export function RequiresAuthentication(props:
{ children: ReactNode }) {
const { children } = props
- const oidc = useOidc();
+ const { userAuthentication } = useCoreFunctions();
- if (!oidc.isUserLoggedIn) {
- oidc.login();
+ if (!userAuthentication.getIsUserLoggedIn()) {
+ userAuthentication.login();
return null;
}
return <>{children}>
-}
-
-
-export function createAuthProvider(params: {
- isMock: true;
-} | {
- isMock: false;
- keycloakUrl: string;
- clientId: string;
- realm: string;
- origin: string;
-}
-) {
-
- const prOidc = params.isMock ?
- Promise.resolve(dummyOidcClient) :
- createKeycloakClient({
- url: params.keycloakUrl,
- clientId: params.clientId,
- realm: params.realm,
- origin: params.origin
- });
-
- function AuthProvider(props: { fallback?: ReactNode; children: ReactNode; }) {
- const { fallback = null, children } = props;
-
- const { data: oidc, isLoading } = useQuery({
- queryKey: ["keycloak-client"],
- queryFn: () => prOidc
- });
-
- if (isLoading) return fallback;
- return {children}
-
- }
-
- return { AuthProvider };
-
}
\ No newline at end of file
diff --git a/drama-queen/src/ui/pages/LoadingData.tsx b/drama-queen/src/ui/pages/LoadingData.tsx
index 93e2a0fc..22c51137 100644
--- a/drama-queen/src/ui/pages/LoadingData.tsx
+++ b/drama-queen/src/ui/pages/LoadingData.tsx
@@ -1,21 +1,11 @@
-import { useEffect, useReducer } from "react";
-import * as loadingData from "core/usecases/loadingData";
+import { useEffect } from "react";
import CircularProgress from "@mui/material/CircularProgress"
import LinearProgress from '@mui/material/LinearProgress';
-import { selectors, useCoreState, useCoreFunctions, useCoreEvts } from "core";
-import { assert } from "tsafe/assert"
+import { useCoreState, useCoreFunctions, useCoreEvts } from "core";
import { useEvt } from "evt/hooks"
export function LoadingData() {
-
- /*
- const { isRunning } = useCoreState(selectors.loadingData.isRunning);
- const { nomenclatureProgress } = useCoreState(selectors.loadingData.nomenclatureProgress);
- const { surveyProgress } = useCoreState(selectors.loadingData.surveyProgress);
- const { surveyUnitProgress } = useCoreState(selectors.loadingData.surveyUnitProgress);
- */
-
- const loadingDataState = useCoreState(state=> state.loadingData);
+ const loadingDataState = useCoreState(state => state.loadingData);
const { loadingData } = useCoreFunctions();
@@ -29,31 +19,19 @@ export function LoadingData() {
const { evtLoadingData } = useCoreEvts();
useEvt(
- ctx=> {
-
+ ctx => {
evtLoadingData.$attach(
- data => data.action === "redirect" ? [data.url] : null,
+ data => data.action === "redirect" ? [data] : null,
ctx,
- url => {
- alert("redirect to " + url)
+ () => {
+ alert("redirect to " + window.location.href)
}
);
-
},
[]
);
- /*
- if (!isRunning) {
- return null;
- }
-
- assert(nomenclatureProgress !== undefined);
- assert(surveyProgress !== undefined);
- assert(surveyUnitProgress !== undefined);
- */
-
- if( loadingDataState.stateDescription !== "running"){
+ if (loadingDataState.stateDescription !== "running") {
return null;
}
diff --git a/drama-queen/src/ui/pages/synchronize/SynchronizePage.tsx b/drama-queen/src/ui/pages/synchronize/SynchronizePage.tsx
index cddd992b..8a241b19 100644
--- a/drama-queen/src/ui/pages/synchronize/SynchronizePage.tsx
+++ b/drama-queen/src/ui/pages/synchronize/SynchronizePage.tsx
@@ -6,7 +6,7 @@ import preloader from 'ui/assets/preloader.svg';
import { tss } from "tss-react/mui";
import { Fragment, useEffect, useState } from "react";
import { type PullData, usePullData } from 'hooks/usePullData';
-import type { SurveyUnitWithId } from "core/model/surveyUnit";
+import type { SurveyUnitWithId } from "core/ports/QueenApi/SurveyUnit";
import { SyncError } from "hooks/queries/SyncError";
import { storeSyncProgress } from "./storeSyncProgress";
import { db } from 'core/indexedDb';
diff --git a/drama-queen/src/ui/queenApi.tsx b/drama-queen/src/ui/queenApi.tsx
index dfb1b6a3..def760dd 100644
--- a/drama-queen/src/ui/queenApi.tsx
+++ b/drama-queen/src/ui/queenApi.tsx
@@ -1,10 +1,6 @@
-import { Oidc } from "core/keycloakClient/Oidc";
-import { QueenApi } from "core/queenApi/QueenApi";
-import { createApiClient } from "core/queenApi/createApiClient";
-import { createMockApiClient } from "core/queenApi/createMockApiClient";
import { ReactNode, createContext, useContext, useMemo, useRef } from "react";
-import { useOidc } from "ui/auth";
import { useGuaranteedMemo } from "hooks/tools/useGuaranteedMemo";
+import { QueenApi } from "core/ports/QueenApi/QueenApi";
const context = createContext(undefined);
@@ -28,17 +24,7 @@ export function createQueenApiProvider(
}) {
const { children } = props;
- const oidc = useOidc()
-
- const apiClient = useGuaranteedMemo(() =>
- apiUrl
- ? createApiClient({
- apiUrl: apiUrl,
- getAccessToken: () => oidc.isUserLoggedIn ? oidc.getAccessToken() : null
- })
- : createMockApiClient(),
- []
- );
+ const apiClient = undefined;
return {children};
}
diff --git a/drama-queen/src/vite-env.d.ts b/drama-queen/src/vite-env.d.ts
index cb067d8f..cbd85044 100644
--- a/drama-queen/src/vite-env.d.ts
+++ b/drama-queen/src/vite-env.d.ts
@@ -1,16 +1,13 @@
///
///
-import { KeycloakParams } from "core/keycloakClient/Oidc";
-
+import { Oidc } from "core/ports/Oidc";
interface ImportMetaEnv {
readonly VITE_QUEEN_URL: string;
readonly VITE_QUEEN_V2_URL: string;
- readonly VITE_AUTH_TYPE?: "OIDC";
readonly VITE_QUEEN_API_URL: string;
- readonly VITE_KEYCLOAK_URL: KeycloakParams["url"];
- readonly VITE_KEYCLOAK_CLIENT_ID: KeycloakParams["clientId"];
- readonly VITE_KEYCLOAK_REALM: KeycloakParams["realm"];
+ readonly VITE_OIDC_ISSUER: Oidc.Common["params"]["issuerUri"];
+ readonly VITE_OIDC_CLIENT_ID: Oidc.Common["params"]["clientId"];
// more env variables...
}
diff --git a/yarn.lock b/yarn.lock
index f7632cf2..eb3d5a25 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1601,7 +1601,7 @@
remove-accents "^0.4.2"
sass "^1.32.2"
-"@inseefr/lunatic@^2.4.10", "@inseefr/lunatic@^2.4.7":
+"@inseefr/lunatic@^2.4.7":
version "2.4.10"
resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.4.10.tgz#a86c14ecbe5cf32706eef84c6f24ff6df99a194e"
integrity sha512-9QuWMbaIz7X1twZtwspEqf2rhwSYgkhKi8Ksyx4wqXHs66nLEgMK0M721B5NDWH8TexMx6ymxuIqVay8+nz2Cg==
@@ -1625,7 +1625,31 @@
snowball "^0.3.1"
string-tokenizer "^0.0.8"
-"@inseefr/trevas@^0.1.14", "@inseefr/trevas@^0.1.16", "@inseefr/trevas@^0.1.17":
+"@inseefr/lunatic@^2.7.4":
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.7.4.tgz#1effadafd95d9333f73a84a3a0da0ac6b2c192c2"
+ integrity sha512-82+PRRChVK3DeyrhAVBCTYxVi9jTmqUbelWnfjHu4ktDqeRPk6Wm6LubcF3nn29Kzw46Vf7RsVmwi1RDj0+I6A==
+ dependencies:
+ "@inseefr/trevas" "^0.1.20"
+ "@inseefr/vtl-2.0-antlr-tools" "^0.1.0-bundle"
+ antlr4 "4.11.0"
+ classnames "^2.3.1"
+ date-fns "^2.25.0"
+ lodash.camelcase "^4.3.0"
+ lodash.debounce "^4.0.8"
+ lodash.isequal "^4.5.0"
+ object-hash "^2.2.0"
+ prop-types "^15.7.2"
+ react-keyboard-event-handler "^1.5.4"
+ react-markdown "^8.0.3"
+ react-number-format "^5.1.3"
+ react-tooltip "^4.2.15"
+ remove-accents "^0.4.2"
+ sass "^1.58.3"
+ snowball "^0.3.1"
+ string-tokenizer "^0.0.8"
+
+"@inseefr/trevas@^0.1.14", "@inseefr/trevas@^0.1.16", "@inseefr/trevas@^0.1.17", "@inseefr/trevas@^0.1.20":
version "0.1.20"
resolved "https://registry.yarnpkg.com/@inseefr/trevas/-/trevas-0.1.20.tgz#a1d68cf3d22a4da1ef99c1c8560470c8dda407d7"
integrity sha512-x1UotSHqHfGhut0JgPCLu+TXZtDpcYSrFQtlIl/L1kav6zYBa888AHhkADWB2hpJM/XAG3lQEfZrqgnsgbQK1g==
@@ -5657,6 +5681,11 @@ crypto-js@^4.0.0:
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
+crypto-js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
+ integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+
crypto-random-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
@@ -12113,6 +12142,14 @@ obuf@^1.0.0, obuf@^1.1.2:
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+oidc-client-ts@^2.3.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-2.4.0.tgz#764c8a33de542026e2798de9849ce8049047d7e5"
+ integrity sha512-WijhkTrlXK2VvgGoakWJiBdfIsVGz6CFzgjNNqZU1hPKV2kyeEaJgLs7RwuiSp2WhLfWBQuLvr2SxVlZnk3N1w==
+ dependencies:
+ crypto-js "^4.2.0"
+ jwt-decode "^3.1.2"
+
oidc-client@^1.11.5:
version "1.11.5"
resolved "https://registry.yarnpkg.com/oidc-client/-/oidc-client-1.11.5.tgz#020aa193d68a3e1f87a24fcbf50073b738de92bb"
@@ -12124,6 +12161,15 @@ oidc-client@^1.11.5:
crypto-js "^4.0.0"
serialize-javascript "^4.0.0"
+oidc-spa@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-2.0.3.tgz#387a6c92b2fbd097d75ca9f3fa4b10f7f5213cdc"
+ integrity sha512-pZJgjpdVr2CRGKhqQGj6z7qu1INo9/xP6HkkqIata3zXEmFrIK/zv6SCpDdFMfeIVfqQWV946FVbccUqBrUlcA==
+ dependencies:
+ jwt-decode "^3.1.2"
+ oidc-client-ts "^2.3.0"
+ tsafe "^1.6.5"
+
on-finished@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@@ -16138,6 +16184,11 @@ tsafe@^1.6.4:
resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.4.tgz#048a114761714538c72f16abd25bb247d4e3780e"
integrity sha512-l4Z54QFGHO8GF0gBpb3yPGHjkIkIirl8rwW+lMBmtEMzOJeRs8BdjkDEx6nU8Ak9PQVp/KNDtECxTja8MMIDoA==
+tsafe@^1.6.5:
+ version "1.6.5"
+ resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.5.tgz#74943b69190069168a53d2accd6d07891cf1cce8"
+ integrity sha512-895zss8xqqHKTc28sHGIfZKnt3C5jrstB1DyPr/h3/flK0zojsZUMQL1/W4ytdDW6KI4Oth62nb9rrxmA3s3Iw==
+
tsconfck@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-2.1.2.tgz#f667035874fa41d908c1fe4d765345fcb1df6e35"