Merge branch 'staging' into preprod

This commit is contained in:
Vins 2023-09-20 10:25:33 +02:00
commit eb6d270215
23 changed files with 521 additions and 8742 deletions

View File

@ -1,11 +1,11 @@
dockerPullSecret: docker-pull-secret dockerPullSecret: docker-pull-secret
scwSecretKey: AgChoEnPitXp4Ny/rVMEcevaWKNVpyj2cJYAcq+yFqKwVwnLB+ffDvwqz9XBHu+6d4Nyyjkf37zUAMoaM21lEDWA7x3zfG2/D/j+rvX1qxzZgLD0mjBk7fGElVm332I6JA83oInes8AMMYEDPLElzHnpKRb9KtkIP4NzgOcCeW0ijft3N7Vroez6LEHsBPCA1I9XjKSkGEDvrO0MhWX3iJOlfz+SPMfJAV7rPawOs0ZmohTHrPW8qIvGDn8HCzKyU8zRBoMt+Ogpf5pH4U3JryEFuqD61KAQgablAM8edPIvsgNno9HAEuC2QtRLYA9aUhuKdaKuS58c9P2E80PHWXIlbpFCg6EugQTgNfnYp+3qDUNz8edeCfapYLvF4s9eCMGyMsGnpDR8EDNOyuGy7Y3l7okX8Xqu464gMp9E+hX7bHkcD6a4xfyIgJcWxsku0tm1TH1dpn4M1UXRuyZZif8P08nuE6MTUL67sAR9J1lpn4lVEL4kflk0pP2tZ5ncgPQFafJrRz05krMb0eU5tb2H4gs7ao/LL6idWo8MM9K1yr8lIuT5x2WW5CX+RjA+i50ex114V6vX3PNP5oVyt+DynTUB9QmXzVm3oLfDc3Cae1uqh7X0CFd+xiztJBtg0VtJaD/xUJcuWfY4cV2lERo9fRrykltzlJqiXHO4nowt8OtN0BcViVV8NJhPhYFzyb4ympxpOlTjm3GETuT2TYhUqdgS9nzleEAbOmOHZdIO2COunPE= scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy1ulbB34v6vpZI2kxnGNqERA/U5BaYDAyfKSBwMAy4br7HVKhhuwkoF5qoG5JzJXseSmqB1U9vncVIGOZWzJc1Y4/eGlWcvLcLyfw2z/WEpyeNiWJfEhTYpJOB7gv0XnRb2U/JM3jRy1QgEUIk1WR6kgBalF+xaczPQ6uKh+PR2pqkbZa3WaKUrddmzNsgEz4d8PZMWt8IBwR2JOQEHUqCd34p/pJNyLdUgcdDhg02DKwn1oRoAxKTbAio/a7WrMbodjCb3TNWIYGal5mFmItZ7Ok/EBmUf4E85eOkTR+j8ynuuiexld3Q5Kw3o8LsHjgzVL9uP+T2rYaKkjtVt+YQRX1U8l9CrsdUEz0/wEBA0jwCWMfnh1qhD5pM/xwwjsEEAcK4rYV+Q7iAgGZZvZBCQ5aEHzrtn5D95tr1GZCV2hmrW6Seu+LKKLVBS1JmsuEsOuhudYsEK9m2RYVcxbjuS5eokKEjNrGobf2oB8rhBByavfw1JTBixR5JrI8lcYlnCa+oEhxXKJY+4Fx5SAB4YaLCMSo5vw6zsFQ3WKQzlEmCFt+EnapS+a+MGrdlwq07OHTDpvgk/1z39hopoCuhhKckGGfErLXsTYQvDOkFu+EPzgY7m7qDw/d9pSiht5tuSOkAqeOgm7tpNkUufZhaXmP+1aT7i+H5gq1JILGAmXzTI5Wc=
lecoffreFront: lecoffreFront:
serviceAccountName: lecoffre-front-sa serviceAccountName: lecoffre-front-sa
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run start'"
envSecrets: ppd-env envSecrets: ppd-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run start'"
imagePullSecrets: imagePullSecrets:
- name: docker-pull-secret - name: docker-pull-secret
image: image:

View File

@ -12,6 +12,7 @@ const nextConfig = {
NEXT_PUBLIC_FRONT_APP_PORT: process.env.NEXT_PUBLIC_FRONT_APP_PORT, NEXT_PUBLIC_FRONT_APP_PORT: process.env.NEXT_PUBLIC_FRONT_APP_PORT,
NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: process.env.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: process.env.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT,
NEXT_PUBLIC_IDNOT_CLIENT_ID: process.env.NEXT_PUBLIC_IDNOT_CLIENT_ID, NEXT_PUBLIC_IDNOT_CLIENT_ID: process.env.NEXT_PUBLIC_IDNOT_CLIENT_ID,
NEXT_PUBLIC_IDNOT_BASE_URL: process.env.NEXT_PUBLIC_IDNOT_BASE_URL,
}, },
// webpack: config => { // webpack: config => {
// config.node = { // config.node = {

8419
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
import BaseApiService from "@Front/Api/BaseApiService"; import BaseApiService from "@Front/Api/BaseApiService";
import { FrontendVariables } from "@Front/Config/VariablesFront"; import { FrontendVariables } from "@Front/Config/VariablesFront";
//import User from "le-coffre-resources/dist/SuperAdmin";
export default class Auth extends BaseApiService { export default class Auth extends BaseApiService {
private static instance: Auth; private static instance: Auth;
@ -12,15 +13,40 @@ export default class Auth extends BaseApiService {
return (this.instance = this.instance ?? new this()); return (this.instance = this.instance ?? new this());
} }
public async getIdnotJwt(autorizationCode: string | string[]): Promise<any> { public async logOutWithIdNot() {
const variables = FrontendVariables.getInstance(); const variables = FrontendVariables.getInstance();
const baseBackUrl = variables.BACK_API_PROTOCOL + variables.BACK_API_HOST; const url = new URL(`${variables.IDNOT_BASE_URL}/user/auth/logout?post_logout_redirect_uri=${variables.FRONT_APP_HOST}`);
const url = new URL(`${baseBackUrl}/api/v1/idnot-user/${autorizationCode}`); console.log(url.toString())
try { try {
return await this.postRequest<any>(url); return await fetch(url);
} catch (err) {
console.log(err);
this.onError(err);
return Promise.reject(err);
}
}
public async loginWithIdNot() {
const variables = FrontendVariables.getInstance();
const url = new URL(`${variables.IDNOT_BASE_URL + variables.IDNOT_AUTHORIZE_ENDPOINT}?client_id=${variables.IDNOT_CLIENT_ID}&redirect_uri=${variables.FRONT_APP_HOST}/authorized-client&scope=openid,profile&response_type=code`);
try {
return await this.getRequest(url);
} catch (err) { } catch (err) {
this.onError(err); this.onError(err);
return Promise.reject(err); return Promise.reject(err);
} }
} }
public async getIdnotJwt(autorizationCode: string | string[]): Promise<{accessToken: string, refreshToken: string}> {
const variables = FrontendVariables.getInstance();
const baseBackUrl = variables.BACK_API_PROTOCOL + variables.BACK_API_HOST;
const url = new URL(`${baseBackUrl}/api/v1/idnot/user/${autorizationCode}`);
try {
return await this.postRequest<{accessToken: string, refreshToken: string}>(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
} }

View File

@ -13,4 +13,7 @@ export enum AppRuleActions {
export enum AppRuleNames { export enum AppRuleNames {
users = "users", users = "users",
officeFolders = "folders", officeFolders = "folders",
officeRoles = "office-roles",
deedTypes = "deed-types",
offices = "offices"
} }

View File

@ -21,7 +21,7 @@
display: inline-flex; display: inline-flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
overflow-wrap: anywhere;
.warning { .warning {
margin-left: 32px; margin-left: 32px;
} }

View File

@ -23,13 +23,13 @@
.text-container { .text-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-wrap: anywhere;
> :first-child { > :first-child {
margin-bottom: 12px; margin-bottom: 12px;
} }
} }
@media (max-width: $screen-ls) { @media (max-width: $screen-ls) {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
@ -37,8 +37,6 @@
@media (max-width: $screen-s) { @media (max-width: $screen-s) {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
.edit-icon-container { .edit-icon-container {
@ -54,5 +52,4 @@
margin-top: 24px; margin-top: 24px;
} }
} }
} }

View File

@ -26,6 +26,7 @@ type IPropsClass = IProps & {
type IState = { type IState = {
filteredFolders: OfficeFolder[]; filteredFolders: OfficeFolder[];
blocks: IBlock[];
}; };
class FolderListContainerClass extends React.Component<IPropsClass, IState> { class FolderListContainerClass extends React.Component<IPropsClass, IState> {
@ -36,6 +37,7 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
super(props); super(props);
this.state = { this.state = {
filteredFolders: this.props.folders, filteredFolders: this.props.folders,
blocks: this.getBlocks(this.props.folders),
}; };
this.filterFolders = this.filterFolders.bind(this); this.filterFolders = this.filterFolders.bind(this);
this.onSelectedFolder = this.onSelectedFolder.bind(this); this.onSelectedFolder = this.onSelectedFolder.bind(this);
@ -50,7 +52,7 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
<SearchBar onChange={this.filterFolders} placeholder="Chercher un dossier" /> <SearchBar onChange={this.filterFolders} placeholder="Chercher un dossier" />
</div> </div>
<div className={classes["folderlist-container"]}> <div className={classes["folderlist-container"]}>
<BlockList blocks={this.getBlocks()} onSelectedBlock={this.onSelectedFolder} /> <BlockList blocks={this.state.blocks} onSelectedBlock={this.onSelectedFolder} />
</div> </div>
</div> </div>
{!this.props.isArchived && ( {!this.props.isArchived && (
@ -73,8 +75,8 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
); );
} }
private getBlocks(): IBlock[] { private getBlocks(folders: OfficeFolder[]): IBlock[] {
const pendingFolders = this.props.folders const pendingFolders = folders
.filter((folder) => { .filter((folder) => {
const pendingDocuments = (folder.documents ?? []).filter( const pendingDocuments = (folder.documents ?? []).filter(
(document) => document.document_status === EDocumentStatus.DEPOSITED, (document) => document.document_status === EDocumentStatus.DEPOSITED,
@ -85,7 +87,7 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
return folder1.created_at! > folder2.created_at! ? -1 : 1; return folder1.created_at! > folder2.created_at! ? -1 : 1;
}); });
const otherFolders = this.props.folders const otherFolders = folders
.filter((folder) => { .filter((folder) => {
const pendingDocuments = (folder.documents ?? []).filter( const pendingDocuments = (folder.documents ?? []).filter(
(document) => document.document_status === EDocumentStatus.DEPOSITED, (document) => document.document_status === EDocumentStatus.DEPOSITED,
@ -104,6 +106,7 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
}; };
}); });
} }
private onSelectedFolder(block: IBlock) { private onSelectedFolder(block: IBlock) {
const folder = this.props.folders.find((folder) => folder.uid === block.id); const folder = this.props.folders.find((folder) => folder.uid === block.id);
if (!folder) return; if (!folder) return;
@ -116,19 +119,21 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
const filteredFolders: OfficeFolder[] = this.props.folders.filter((folder) => { const filteredFolders: OfficeFolder[] = this.props.folders.filter((folder) => {
const name = folder.name.toLowerCase(); const name = folder.name.toLowerCase();
const number = folder.folder_number.toLowerCase(); const number = folder.folder_number.toLowerCase();
value = value.toLowerCase();
if (folder.customers) { if (folder.customers) {
const customerNames = folder.customers const customerNames = folder.customers
.map((customer) => { .map((customer) => {
return `${customer.contact?.first_name.toLowerCase()} ${customer.contact?.last_name.toLowerCase()}`; return `${customer.contact?.first_name.toLowerCase()} ${customer.contact?.last_name.toLowerCase()}`;
}) })
.join(", "); .join(", ");
return name.includes(value) || number.includes(value) || customerNames.includes(value); return name.includes(value) || number.includes(value) || customerNames.includes(value);
} }
return name.includes(value) || number.includes(value); return name.includes(value) || number.includes(value);
}); });
this.setState({ filteredFolders });
this.setState({ filteredFolders, blocks: this.getBlocks(filteredFolders) });
} }
} }

View File

@ -4,6 +4,8 @@ import React from "react";
import NavigationLink from "../../NavigationLink"; import NavigationLink from "../../NavigationLink";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
type IProps = { type IProps = {
isOpen: boolean; isOpen: boolean;
@ -32,11 +34,28 @@ export default class BurgerModal extends React.Component<IProps, IState> {
text="Dossiers archivés" text="Dossiers archivés"
routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]} routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]}
/> />
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.officeRoles,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Collaborators.props.path} path={Module.getInstance().get().modules.pages.Collaborators.props.path}
text="Collaborateurs" text="Collaborateurs"
routesActive={[Module.getInstance().get().modules.pages.Collaborators.props.path]} routesActive={[Module.getInstance().get().modules.pages.Collaborators.props.path]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.deedTypes,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.DeedTypes.props.path} path={Module.getInstance().get().modules.pages.DeedTypes.props.path}
text="Paramétrage des listes de pièces" text="Paramétrage des listes de pièces"
@ -51,6 +70,15 @@ export default class BurgerModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.DocumentTypes.props.path, Module.getInstance().get().modules.pages.DocumentTypes.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.officeRoles,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Roles.props.path} path={Module.getInstance().get().modules.pages.Roles.props.path}
text="Gestion des rôles" text="Gestion des rôles"
@ -59,6 +87,15 @@ export default class BurgerModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path, Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.create,
name: AppRuleNames.officeRoles,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Users.props.path} path={Module.getInstance().get().modules.pages.Users.props.path}
text="Gestion des utilisateurs" text="Gestion des utilisateurs"
@ -67,6 +104,15 @@ export default class BurgerModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path, Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.offices,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Offices.props.path} path={Module.getInstance().get().modules.pages.Offices.props.path}
text="Gestion des offices" text="Gestion des offices"
@ -75,6 +121,7 @@ export default class BurgerModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path, Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path,
]} ]}
/> />
</Rules>
<NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" /> <NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" />
<NavigationLink text="CGU" /> <NavigationLink text="CGU" />
<div className={classes["separator"]} /> <div className={classes["separator"]} />

View File

@ -3,6 +3,8 @@ import React from "react";
import HeaderLink from "../HeaderLink"; import HeaderLink from "../HeaderLink";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
type IProps = {}; type IProps = {};
type IState = {}; type IState = {};
@ -24,11 +26,20 @@ export default class Navigation extends React.Component<IProps, IState> {
path={Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path} path={Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path}
routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]} routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]}
/> />
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.officeRoles,
},
]}>
<HeaderLink <HeaderLink
text={"Collaborateurs"} text={"Collaborateurs"}
path={Module.getInstance().get().modules.pages.Collaborators.props.path} path={Module.getInstance().get().modules.pages.Collaborators.props.path}
routesActive={[Module.getInstance().get().modules.pages.Collaborators.props.path]} routesActive={[Module.getInstance().get().modules.pages.Collaborators.props.path]}
/> />
</Rules>
</div> </div>
); );
} }

View File

@ -4,6 +4,8 @@ import React from "react";
import NavigationLink from "../../NavigationLink"; import NavigationLink from "../../NavigationLink";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
type IProps = { type IProps = {
isOpen: boolean; isOpen: boolean;
@ -20,6 +22,14 @@ export default class ProfileModal extends React.Component<IProps, IState> {
<div className={classes["background"]} onClick={this.props.closeModal} /> <div className={classes["background"]} onClick={this.props.closeModal} />
<div className={classes["root"]}> <div className={classes["root"]}>
<NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" /> <NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" />
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.officeRoles,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Roles.props.path} path={Module.getInstance().get().modules.pages.Roles.props.path}
text="Gestion des rôles" text="Gestion des rôles"
@ -28,6 +38,15 @@ export default class ProfileModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path, Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.deedTypes,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.DeedTypes.props.path} path={Module.getInstance().get().modules.pages.DeedTypes.props.path}
text="Paramétrage des listes de pièces" text="Paramétrage des listes de pièces"
@ -42,6 +61,15 @@ export default class ProfileModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.DocumentTypes.props.path, Module.getInstance().get().modules.pages.DocumentTypes.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.create,
name: AppRuleNames.officeRoles,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Users.props.path} path={Module.getInstance().get().modules.pages.Users.props.path}
text="Gestion des utilisateurs" text="Gestion des utilisateurs"
@ -50,6 +78,15 @@ export default class ProfileModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path, Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path,
]} ]}
/> />
</Rules>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.update,
name: AppRuleNames.offices,
},
]}>
<NavigationLink <NavigationLink
path={Module.getInstance().get().modules.pages.Offices.props.path} path={Module.getInstance().get().modules.pages.Offices.props.path}
text="Gestion des offices" text="Gestion des offices"
@ -58,6 +95,7 @@ export default class ProfileModal extends React.Component<IProps, IState> {
Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path, Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path,
]} ]}
/> />
</Rules>
<NavigationLink text="CGU" /> <NavigationLink text="CGU" />
<div className={classes["separator"]} /> <div className={classes["separator"]} />
<LogOutButton /> <LogOutButton />

View File

@ -3,21 +3,23 @@ import Image from "next/image";
import DisconnectIcon from "@Assets/Icons/disconnect.svg"; import DisconnectIcon from "@Assets/Icons/disconnect.svg";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Typography, { ITypo } from "../Typography"; import Typography, { ITypo } from "../Typography";
import { useRouter } from "next/router";
import UserStore from "@Front/Stores/UserStore";
import { FrontendVariables } from "@Front/Config/VariablesFront";
type IProps = {}; export default function LogOut() {
type IState = { const router = useRouter();
isLogged: boolean; const variables = FrontendVariables.getInstance();
const disconnect = async() => {
await UserStore.instance.disconnect();
router.push(`https://qual-connexion.idnot.fr/user/auth/logout?post_logout_redirect_uri=${variables.FRONT_APP_HOST}/login`);
}; };
export default class LogOutButton extends React.Component<IProps, IState> {
public override render(): JSX.Element {
return ( return (
<div className={classes["root"]} onClick={this.disconnect}> <div className={classes["root"]} onClick={disconnect}>
<Typography typo={ITypo.NAV_HEADER_18}>Déconnexion</Typography> <Typography typo={ITypo.NAV_HEADER_18}>Déconnexion</Typography>
<Image src={DisconnectIcon} className={classes["disconnect-icon"]} alt="disconnect" /> <Image src={DisconnectIcon} className={classes["disconnect-icon"]} alt="disconnect" />
</div> </div>
); );
} }
private disconnect() {}
}

View File

@ -57,6 +57,7 @@
.button-container { .button-container {
width: 100%; width: 100%;
display: flex; display: flex;
gap: 16px;
text-align: center; text-align: center;
justify-content: center; justify-content: center;
@ -87,3 +88,13 @@
margin-bottom: 24px; margin-bottom: 24px;
} }
} }
.validate-document-container {
.document-validating-container {
.validate-gif {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}

View File

@ -13,10 +13,13 @@ import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document";
import Link from "next/link"; import Link from "next/link";
import { NextRouter, useRouter } from "next/router"; import { NextRouter, useRouter } from "next/router";
import { ChangeEvent } from "react"; import { ChangeEvent } from "react";
import Image from "next/image";
import ValidateAnchoringGif from "@Front/Assets/images/validate_anchoring.gif";
import BasePage from "../../Base"; import BasePage from "../../Base";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import ClientSection from "./ClientSection"; import ClientSection from "./ClientSection";
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
type IProps = {}; type IProps = {};
@ -29,6 +32,8 @@ type IState = {
selectedFolder: OfficeFolder | null; selectedFolder: OfficeFolder | null;
isArchivedModalOpen: boolean; isArchivedModalOpen: boolean;
inputArchivedDescripton: string; inputArchivedDescripton: string;
isValidateModalVisible: boolean;
hasValidateAnchoring: boolean;
}; };
class FolderInformationClass extends BasePage<IPropsClass, IState> { class FolderInformationClass extends BasePage<IPropsClass, IState> {
public constructor(props: IPropsClass) { public constructor(props: IPropsClass) {
@ -37,6 +42,8 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
selectedFolder: null, selectedFolder: null,
isArchivedModalOpen: false, isArchivedModalOpen: false,
inputArchivedDescripton: "", inputArchivedDescripton: "",
isValidateModalVisible: false,
hasValidateAnchoring: false,
}; };
this.onSelectedFolder = this.onSelectedFolder.bind(this); this.onSelectedFolder = this.onSelectedFolder.bind(this);
this.openArchivedModal = this.openArchivedModal.bind(this); this.openArchivedModal = this.openArchivedModal.bind(this);
@ -45,6 +52,9 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
this.getCompletionNumber = this.getCompletionNumber.bind(this); this.getCompletionNumber = this.getCompletionNumber.bind(this);
this.onArchivedDescriptionInputChange = this.onArchivedDescriptionInputChange.bind(this); this.onArchivedDescriptionInputChange = this.onArchivedDescriptionInputChange.bind(this);
this.deleteFolder = this.deleteFolder.bind(this); this.deleteFolder = this.deleteFolder.bind(this);
this.closeModal = this.closeModal.bind(this);
this.validateAnchoring = this.validateAnchoring.bind(this);
this.openValidateModal = this.openValidateModal.bind(this);
} }
// TODO: Message if the user has not created any folder yet // TODO: Message if the user has not created any folder yet
@ -93,6 +103,11 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
<Button variant={EButtonVariant.GHOST} onClick={this.openArchivedModal}> <Button variant={EButtonVariant.GHOST} onClick={this.openArchivedModal}>
Archiver le dossier Archiver le dossier
</Button> </Button>
{this.everyDocumentValidated() && (
<Button variant={EButtonVariant.PRIMARY} onClick={this.openValidateModal}>
Ancrer le dossier
</Button>
)}
{!this.doesFolderHaveCustomer() && ( {!this.doesFolderHaveCustomer() && (
<span className={classes["delete-folder"]} onClick={this.deleteFolder}> <span className={classes["delete-folder"]} onClick={this.deleteFolder}>
<Button variant={EButtonVariant.SECONDARY}>Supprimer le dossier</Button> <Button variant={EButtonVariant.SECONDARY}>Supprimer le dossier</Button>
@ -128,6 +143,41 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
</div> </div>
)} )}
</div> </div>
<Confirm
isOpen={this.state.isValidateModalVisible}
onClose={this.closeModal}
onAccept={this.validateAnchoring}
closeBtn={true}
hasContainerClosable={true}
header={
this.state.hasValidateAnchoring
? "Dossier en cours de certification"
: "Êtes-vous sûr de vouloir ancrer et certifier ?"
}
cancelText={"Annuler"}
confirmText={"Confirmer"}
showButtons={!this.state.hasValidateAnchoring}>
<div className={classes["validate-document-container"]}>
{!this.state.hasValidateAnchoring && (
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
Afin de certifier les documents associés au dossier, cliquez sur Ancrez et certifier et les documents
seront certifiés sur la blockchain.
</Typography>
)}
{this.state.hasValidateAnchoring && (
<div className={classes["document-validating-container"]}>
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
Vous pouvez désormais télécharger les feuilles d'ancrage et les mettre dans la GED de votre logiciel de
rédaction d'acte.
</Typography>
<Image src={ValidateAnchoringGif} alt="Anchoring animation" className={classes["validate-gif"]} />
<div className={classes["dont-show-again"]}>
<CheckBox option={{ label: "Ne plus afficher ce message", value: false }} />
</div>
</div>
)}
</div>
</Confirm>
</DefaultNotaryDashboard> </DefaultNotaryDashboard>
); );
} }
@ -137,6 +187,49 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
}); });
} }
private closeModal() {
this.setState({
isValidateModalVisible: false,
});
}
private openValidateModal() {
this.setState({
isValidateModalVisible: true,
});
}
private async validateAnchoring() {
this.setState({
hasValidateAnchoring: true,
});
try {
const timeoutDelay = 9800;
setTimeout(() => {
this.setState({
isValidateModalVisible: false,
});
}, timeoutDelay);
setTimeout(() => {
this.setState({
hasValidateAnchoring: false,
});
}, timeoutDelay + 1000);
} catch (e) {
console.error(e);
}
}
private everyDocumentValidated(): boolean {
if (!this.state.selectedFolder?.documents) return false;
return (
this.state.selectedFolder?.documents?.length >= 1 &&
this.state.selectedFolder?.documents.every((document) => document.document_status === EDocumentStatus.VALIDATED)
);
}
private async deleteFolder() { private async deleteFolder() {
if (!this.state.selectedFolder?.uid) return; if (!this.state.selectedFolder?.uid) return;
await Folders.getInstance().delete(this.state.selectedFolder.uid); await Folders.getInstance().delete(this.state.selectedFolder.uid);

View File

@ -24,7 +24,9 @@ type IState = {
selectedFolder: OfficeFolder | null; selectedFolder: OfficeFolder | null;
selectedOption?: ERadioBoxValue; selectedOption?: ERadioBoxValue;
availableCollaborators: User[]; availableCollaborators: User[];
defaultCheckedAllOffice: boolean;
selectedCollaborators: readonly IOption[]; selectedCollaborators: readonly IOption[];
loading: boolean;
}; };
enum ERadioBoxValue { enum ERadioBoxValue {
@ -39,6 +41,9 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
selectedFolder: null, selectedFolder: null,
availableCollaborators: [], availableCollaborators: [],
selectedCollaborators: [], selectedCollaborators: [],
defaultCheckedAllOffice: false,
selectedOption: ERadioBoxValue.SELECTION,
loading: true,
}; };
this.onSelectedFolder = this.onSelectedFolder.bind(this); this.onSelectedFolder = this.onSelectedFolder.bind(this);
this.onSelectedOptionAllOffice = this.onSelectedOptionAllOffice.bind(this); this.onSelectedOptionAllOffice = this.onSelectedOptionAllOffice.bind(this);
@ -55,6 +60,7 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
value: collaborator.uid, value: collaborator.uid,
}; };
}); });
return ( return (
<DefaultNotaryDashboard title={"Ajouter client(s)"} onSelectedFolder={this.onSelectedFolder}> <DefaultNotaryDashboard title={"Ajouter client(s)"} onSelectedFolder={this.onSelectedFolder}>
<div className={classes["root"]}> <div className={classes["root"]}>
@ -63,12 +69,21 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
</div> </div>
<Typography typo={ITypo.H1Bis}>Modifier les collaborateurs</Typography> <Typography typo={ITypo.H1Bis}>Modifier les collaborateurs</Typography>
{!this.state.loading && (
<Form className={classes["form"]} onSubmit={this.onFormSubmit}> <Form className={classes["form"]} onSubmit={this.onFormSubmit}>
<div className={classes["content"]}> <div className={classes["content"]}>
<RadioBox name="office" value={ERadioBoxValue.ALL} defaultChecked onChange={this.onSelectedOptionAllOffice}> <RadioBox
name="office"
value={ERadioBoxValue.ALL}
defaultChecked={this.state.defaultCheckedAllOffice}
onChange={this.onSelectedOptionAllOffice}>
Tout l'office Tout l'office
</RadioBox> </RadioBox>
<RadioBox name="office" value={ERadioBoxValue.SELECTION} onChange={this.onSelectedOptionSpecific}> <RadioBox
name="office"
value={ERadioBoxValue.SELECTION}
defaultChecked={!this.state.defaultCheckedAllOffice}
onChange={this.onSelectedOptionSpecific}>
Sélectionner des collaborateurs Sélectionner des collaborateurs
</RadioBox> </RadioBox>
</div> </div>
@ -91,6 +106,7 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
<Button type="submit">Enregistrer</Button> <Button type="submit">Enregistrer</Button>
</div> </div>
</Form> </Form>
)}
</div> </div>
</DefaultNotaryDashboard> </DefaultNotaryDashboard>
); );
@ -121,11 +137,6 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
value: collaborator.uid, value: collaborator.uid,
}; };
}); });
this.setState({ selectedCollaborators: preSelectedCollaborators });
} catch (error) {
this.props.router.push(Module.getInstance().get().modules.pages["404"].props.path);
return;
}
// no need to pass query 'where' param here, default query for notaries include only users which are in the same office as the caller // no need to pass query 'where' param here, default query for notaries include only users which are in the same office as the caller
const userQuery: IGetUsersParams = { const userQuery: IGetUsersParams = {
@ -140,8 +151,19 @@ class UpdateFolderCollaboratorsClass extends BasePage<IPropsClass, IState> {
}; };
const availableCollaborators = await Users.getInstance().get(userQuery); const availableCollaborators = await Users.getInstance().get(userQuery);
console.log(availableCollaborators)
this.setState({ availableCollaborators }); this.setState({
loading: false,
availableCollaborators,
selectedCollaborators: preSelectedCollaborators,
defaultCheckedAllOffice: preSelectedCollaborators.length === availableCollaborators.length,
selectedOption:
preSelectedCollaborators.length === availableCollaborators.length ? ERadioBoxValue.ALL : ERadioBoxValue.SELECTION,
});
} catch (error) {
this.props.router.push(Module.getInstance().get().modules.pages["404"].props.path);
return;
}
} }
private onSelectedOptionAllOffice(event: React.ChangeEvent<HTMLInputElement>) { private onSelectedOptionAllOffice(event: React.ChangeEvent<HTMLInputElement>) {

View File

@ -1,9 +1,7 @@
import LeftArrowIcon from "@Assets/Icons/left-arrow.svg"; import LeftArrowIcon from "@Assets/Icons/left-arrow.svg";
import RightArrowIcon from "@Assets/Icons/right-arrow.svg"; import RightArrowIcon from "@Assets/Icons/right-arrow.svg";
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
import ValidateAnchoringGif from "@Front/Assets/images/validate_anchoring.gif";
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
import FilePreview from "@Front/Components/DesignSystem/FilePreview"; import FilePreview from "@Front/Components/DesignSystem/FilePreview";
import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm";
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
@ -32,7 +30,6 @@ type IState = {
isRefuseModalVisible: boolean; isRefuseModalVisible: boolean;
isValidateModalVisible: boolean; isValidateModalVisible: boolean;
refuseText: string; refuseText: string;
hasValidateAnchoring: boolean;
selectedFileIndex: number; selectedFileIndex: number;
selectedFile: File | null; selectedFile: File | null;
validatedPercentage: number; validatedPercentage: number;
@ -47,7 +44,6 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
isValidateModalVisible: false, isValidateModalVisible: false,
isRefuseModalVisible: false, isRefuseModalVisible: false,
refuseText: "", refuseText: "",
hasValidateAnchoring: false,
selectedFileIndex: 0, selectedFileIndex: 0,
selectedFile: null, selectedFile: null,
validatedPercentage: this.getRandomPercentageForOcr(), validatedPercentage: this.getRandomPercentageForOcr(),
@ -58,7 +54,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
this.openValidateModal = this.openValidateModal.bind(this); this.openValidateModal = this.openValidateModal.bind(this);
this.openRefuseModal = this.openRefuseModal.bind(this); this.openRefuseModal = this.openRefuseModal.bind(this);
this.onRefuseTextChange = this.onRefuseTextChange.bind(this); this.onRefuseTextChange = this.onRefuseTextChange.bind(this);
this.validateAnchoring = this.validateAnchoring.bind(this); this.validateDocument = this.validateDocument.bind(this);
this.goToNext = this.goToNext.bind(this); this.goToNext = this.goToNext.bind(this);
this.goToPrevious = this.goToPrevious.bind(this); this.goToPrevious = this.goToPrevious.bind(this);
@ -117,7 +113,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
<Button variant={EButtonVariant.GHOST} onClick={this.openRefuseModal}> <Button variant={EButtonVariant.GHOST} onClick={this.openRefuseModal}>
Refuser Refuser
</Button> </Button>
<Button onClick={this.openValidateModal}>Valider et ancrer</Button> <Button onClick={this.openValidateModal}>Valider</Button>
<Button disabled>Télécharger</Button> <Button disabled>Télécharger</Button>
</> </>
)} )}
@ -129,30 +125,16 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
<Confirm <Confirm
isOpen={this.state.isValidateModalVisible} isOpen={this.state.isValidateModalVisible}
onClose={this.closeModals} onClose={this.closeModals}
onAccept={this.validateAnchoring} onAccept={this.validateDocument}
closeBtn={true} closeBtn={true}
hasContainerClosable={true} hasContainerClosable={true}
header={this.state.hasValidateAnchoring ? "Document en cours de validation" : "Ancrer le document"} header={"Valider le document ?"}
cancelText={"Annuler"} cancelText={"Annuler"}
confirmText={"Confirmer"} confirmText={"Confirmer"}>
showButtons={!this.state.hasValidateAnchoring}>
<div className={classes["validate-document-container"]}> <div className={classes["validate-document-container"]}>
{!this.state.hasValidateAnchoring && (
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}> <Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
Êtes-vous sûr de vouloir ancrer ce document ? Êtes-vous sûr de vouloir valider ce document ?
</Typography> </Typography>
)}
{this.state.hasValidateAnchoring && (
<div className={classes["document-validating-container"]}>
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
Le document s'ancre dans la blockchain.
</Typography>
<Image src={ValidateAnchoringGif} alt="Anchoring animation" className={classes["validate-gif"]} />
<div className={classes["dont-show-again"]}>
<CheckBox option={{ label: "Ne plus afficher ce message", value: false }} />
</div>
</div>
)}
</div> </div>
</Confirm> </Confirm>
<Confirm <Confirm
@ -290,33 +272,17 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
} }
} }
private async validateAnchoring() { private async validateDocument() {
this.setState({
hasValidateAnchoring: true,
});
try { try {
await Documents.getInstance().put(this.props.documentUid, { await Documents.getInstance().put(this.props.documentUid, {
document_status: EDocumentStatus.VALIDATED, document_status: EDocumentStatus.VALIDATED,
}); });
const timeoutDelay = 9800;
setTimeout(() => {
this.setState({
isValidateModalVisible: false,
});
this.props.router.push( this.props.router.push(
Module.getInstance() Module.getInstance()
.get() .get()
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid), .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid),
); );
}, timeoutDelay);
setTimeout(() => {
this.setState({
hasValidateAnchoring: false,
});
}, timeoutDelay + 1000);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }

View File

@ -12,6 +12,7 @@ import { NextRouter, useRouter } from "next/router";
import BasePage from "../../Base"; import BasePage from "../../Base";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import ClientSection from "./ClientSection"; import ClientSection from "./ClientSection";
import Link from "next/link";
type IProps = {}; type IProps = {};
@ -40,6 +41,9 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
// TODO: Message if the user has not created any folder yet // TODO: Message if the user has not created any folder yet
// TODO: get the selected folder from the api in componentDidMount // TODO: get the selected folder from the api in componentDidMount
public override render(): JSX.Element { public override render(): JSX.Element {
const redirectPathEditCollaborators = Module.getInstance()
.get()
.modules.pages.Folder.pages.EditCollaborators.props.path.replace("[folderUid]", this.props.selectedFolderUid);
return ( return (
<DefaultNotaryDashboard title={"Dossier"} onSelectedFolder={this.onSelectedFolder} isArchived={true}> <DefaultNotaryDashboard title={"Dossier"} onSelectedFolder={this.onSelectedFolder} isArchived={true}>
<div className={classes["root"]}> <div className={classes["root"]}>
@ -50,9 +54,11 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
<div className={classes["title"]}> <div className={classes["title"]}>
<Typography typo={ITypo.H1Bis}>Informations du dossier</Typography> <Typography typo={ITypo.H1Bis}>Informations du dossier</Typography>
</div> </div>
<Link href={redirectPathEditCollaborators}>
<Button variant={EButtonVariant.LINE} icon={ChevronIcon}> <Button variant={EButtonVariant.LINE} icon={ChevronIcon}>
Modifier les collaborateurs Modifier les collaborateurs
</Button> </Button>
</Link>
</div> </div>
<FolderBoxInformation <FolderBoxInformation
folder={this.state.selectedFolder} folder={this.state.selectedFolder}

View File

@ -12,25 +12,18 @@ import { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import LandingImage from "./landing-connect.jpeg"; import LandingImage from "./landing-connect.jpeg";
import { FrontendVariables } from "@Front/Config/VariablesFront";
export default function Login() { export default function Login() {
const router = useRouter(); const router = useRouter();
const redirectUserOnConnection = useCallback(() => { const redirectUserOnConnection = useCallback(() => {
async function getUser() { const variables = FrontendVariables.getInstance();
try { router.push(
// Super admin `${variables.IDNOT_BASE_URL + variables.IDNOT_AUTHORIZE_ENDPOINT}?client_id=${variables.IDNOT_CLIENT_ID}&redirect_uri=${
await UserStore.instance.connect("jelkvelknvlkn"); variables.FRONT_APP_HOST
// Notaire }/authorized-client&scope=openid,profile&response_type=code`,
// await UserStore.instance.connect("ljfeflecnmd"); );
await JwtService.getInstance().checkJwt();
router.push(Module.getInstance().get().modules.pages.Folder.props.path);
} catch (e) {
console.error(e);
}
}
getUser();
}, [router]); }, [router]);
const redirectCustomerOnConnection = useCallback(() => { const redirectCustomerOnConnection = useCallback(() => {
@ -55,7 +48,7 @@ export default function Login() {
<div className={classes["title"]}>Connexion espace professionnel</div> <div className={classes["title"]}>Connexion espace professionnel</div>
</Typography> </Typography>
<Button onClick={redirectUserOnConnection} icon={idNoteLogo} iconposition={"left"}> <Button onClick={redirectUserOnConnection} icon={idNoteLogo} iconposition={"left"}>
S'identifier avec ID.not S'identifier avec ID.not !
</Button> </Button>
<Button onClick={redirectCustomerOnConnection} icon={idNoteLogo} iconposition={"left"}> <Button onClick={redirectCustomerOnConnection} icon={idNoteLogo} iconposition={"left"}>
S'identifier en tant que customer S'identifier en tant que customer

View File

@ -1,12 +1,25 @@
@import "@Themes/constants.scss";
.root { .root {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
height: 100%;
max-width: 530px;
margin: auto;
.title { .title {
margin: 32px 0; margin: 32px 0;
text-align: center; text-align: center;
@media (max-width: $screen-s) {
font-family: 48px;
}
}
.loader {
width: 32px;
height: 32px;
} }
.forget-password { .forget-password {

View File

@ -1,90 +1,52 @@
// import classes from "./classes.module.scss"; import LandingImage from "../Login/landing-connect.jpeg";
// import LandingImage from "../Login/landing-connect.png"; import Image from "next/image";
// import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; import CoffreIcon from "@Assets/Icons/coffre.svg";
// import Image from "next/image";
// import CoffreIcon from "@Assets/Icons/coffre.svg";
// import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
// import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useEffect } from "react";
import classes from "./classes.module.scss";
import Module from "@Front/Config/Module";
import Auth from "@Front/Api/Auth/IdNot";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
import Loader from "@Front/Components/DesignSystem/Loader";
import UserStore from "@Front/Stores/UserStore";
//import React, { useEffect, useState } from "react"; export default function LoginCallBack() {
import React from "react";
//import Loader from "@Front/Components/DesignSystem/Loader";
//import Auth from "@Front/Api/Auth/IdNot";
import Folder from "../Folder";
import LoginClass from "../Login";
type IPropsClass = {};
// type IStateClass = {};
// class LoginCallBackClass extends React.Component<IPropsClass, IStateClass> {
// public override render(): JSX.Element {
// return (
// <DefaultDoubleSidePage title={"Login"} image={LandingImage}>
// <div className={classes["root"]}>
// <Image alt="coffre" src={CoffreIcon} />
// <Typography typo={ITypo.H1}>
// <div className={classes["title"]}>
// Connexion espace professionnel
// </div>
// </Typography>
// <Loader />
// <Typography typo={ITypo.P_18}>
// <div className={classes["forget-password"]}>
// Vous n'arrivez pas à vous connecter ?
// </div>
// </Typography>
// <Button variant={EButtonVariant.LINE}>
// Contacter l'administrateur
// </Button>
// </div>
// </DefaultDoubleSidePage>
// );
// }
// }
// TODO: Refacto with functionnal component container of classcomponent
// export default function LoginCallBack(props: IPropsClass) {
// const [user, setUser] = useState(null);
// const [isLoading, setIsLoading] = useState(false);
// const router = useRouter();
// const { code } = router.query;
// if (code) {
// useEffect(() => {
// const getIdNotJwt = async () => {
// setIsLoading(true);
// try {
// const authService = Auth.getInstance();
// const fetchedUser = await authService.getIdnotJwt(code);
// setUser(fetchedUser);
// } catch (error) {
// console.error(error);
// // Router.push('/login');
// }
// };
// getIdNotJwt();
// }, []);
// if (isLoading) return <LoginCallBackClass {... props}/>
// return <Folder {...props} />;
// }
// return <LoginClass {...props}/>
// }
export default function LoginCallBack(props: IPropsClass) {
const router = useRouter(); const router = useRouter();
const { code } = router.query;
if (code) { useEffect(() => {
// const getIdNotJwt = async () => { async function getUser() {
// try { const code = router.query["code"];
// const authService = Auth.getInstance(); if (!code) return;
// await authService.getIdnotJwt(code); try {
// } catch (error) { const token = await Auth.getInstance().getIdnotJwt(code as string);
// console.error(error); await UserStore.instance.connect(token.accessToken, token.refreshToken);
// } return router.push(Module.getInstance().get().modules.pages.Folder.props.path);
// }; } catch (e) {
//getIdNotJwt(); console.error(e);
return <Folder {...props} />; return;
} }
return <LoginClass {...props} />; }
getUser();
}),
[router];
return (
<DefaultDoubleSidePage title={"Login"} image={LandingImage}>
<div className={classes["root"]}>
<Image alt="coffre" src={CoffreIcon} />
<Typography typo={ITypo.H1}>
<div className={classes["title"]}>Connexion espace professionnel</div>
</Typography>
<div className={classes["loader"]}>
<Loader />
</div>
<Typography typo={ITypo.P_18}>
<div className={classes["forget-password"]}>Vous n'arrivez pas à vous connecter ?</div>
</Typography>
<Button variant={EButtonVariant.LINE}>Contacter l'administrateur</Button>
</div>
</DefaultDoubleSidePage>
);
} }

View File

@ -11,6 +11,8 @@ export class FrontendVariables {
public FRONT_APP_HOST!: string; public FRONT_APP_HOST!: string;
public IDNOT_BASE_URL!: string;
public IDNOT_AUTHORIZE_ENDPOINT!: string; public IDNOT_AUTHORIZE_ENDPOINT!: string;
public IDNOT_CLIENT_ID!: string; public IDNOT_CLIENT_ID!: string;

View File

@ -1,6 +1,5 @@
"use client"; "use client";
import User from "@Front/Api/Auth/IdNot/User";
import Customer from "@Front/Api/Auth/franceConnect/Customer"; import Customer from "@Front/Api/Auth/franceConnect/Customer";
import CookieService from "@Front/Services/CookieService/CookieService"; import CookieService from "@Front/Services/CookieService/CookieService";
import EventEmitter from "@Front/Services/EventEmitter"; import EventEmitter from "@Front/Services/EventEmitter";
@ -23,14 +22,11 @@ export default class UserStore {
return decodedPayload?.role; return decodedPayload?.role;
} }
public async connect(idnotUid: string) { public async connect(accessToken: string, refreshToken: string) {
try { try {
//call connection function
const user: any = await User.getInstance().login(idnotUid);
//Save tokens in cookies //Save tokens in cookies
CookieService.getInstance().setCookie("leCoffreAccessToken", user.accessToken); CookieService.getInstance().setCookie("leCoffreAccessToken", accessToken);
CookieService.getInstance().setCookie("leCoffreRefreshToken", user.refreshToken); CookieService.getInstance().setCookie("leCoffreRefreshToken", refreshToken);
this.event.emit("connection", this.accessToken); this.event.emit("connection", this.accessToken);
} catch (error) { } catch (error) {

View File

@ -17,6 +17,7 @@ type AppPropsWithLayout = AppProps & {
backApiRootUrl: string; backApiRootUrl: string;
backApiVersion: string; backApiVersion: string;
frontAppHost: string; frontAppHost: string;
idNotBaseUrl: string;
idNotAuthorizeEndpoint: string; idNotAuthorizeEndpoint: string;
idNotClientId: string; idNotClientId: string;
fcAuthorizeEndpoint: string; fcAuthorizeEndpoint: string;
@ -31,6 +32,7 @@ const MyApp = (({
backApiRootUrl, backApiRootUrl,
backApiVersion, backApiVersion,
frontAppHost, frontAppHost,
idNotBaseUrl,
idNotAuthorizeEndpoint, idNotAuthorizeEndpoint,
idNotClientId, idNotClientId,
fcAuthorizeEndpoint, fcAuthorizeEndpoint,
@ -44,7 +46,8 @@ const MyApp = (({
instance.BACK_API_ROOT_URL = backApiRootUrl ?? "/api"; instance.BACK_API_ROOT_URL = backApiRootUrl ?? "/api";
instance.BACK_API_VERSION = backApiVersion ?? "/v1"; instance.BACK_API_VERSION = backApiVersion ?? "/v1";
instance.FRONT_APP_HOST = frontAppHost ?? "app.stg.lecoffre.smart-chain.fr"; instance.FRONT_APP_HOST = frontAppHost ?? "app.stg.lecoffre.smart-chain.fr";
instance.IDNOT_AUTHORIZE_ENDPOINT = idNotAuthorizeEndpoint ?? "https://qual-connexion.idnot.fr/IdPOAuth2/authorize/idnot_idp_v1"; instance.IDNOT_BASE_URL = idNotBaseUrl ?? "https://qual-connexion.idnot.fr";
instance.IDNOT_AUTHORIZE_ENDPOINT = idNotAuthorizeEndpoint ?? "/IdPOAuth2/authorize/idnot_idp_v1";
instance.IDNOT_CLIENT_ID = idNotClientId ?? "4501646203F3EF67"; instance.IDNOT_CLIENT_ID = idNotClientId ?? "4501646203F3EF67";
instance.FC_AUTHORIZE_ENDPOINT= fcAuthorizeEndpoint ?? "https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize"; instance.FC_AUTHORIZE_ENDPOINT= fcAuthorizeEndpoint ?? "https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize";
instance.FC_CLIENT_ID = fcClientId ?? "211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e"; instance.FC_CLIENT_ID = fcClientId ?? "211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e";
@ -60,6 +63,7 @@ MyApp.getInitialProps = async () => {
backApiVersion: process.env["NEXT_PUBLIC_BACK_API_VERSION"], backApiVersion: process.env["NEXT_PUBLIC_BACK_API_VERSION"],
frontAppHost: process.env["NEXT_PUBLIC_FRONT_APP_HOST"], frontAppHost: process.env["NEXT_PUBLIC_FRONT_APP_HOST"],
frontAppPort: process.env["NEXT_PUBLIC_FRONT_APP_PORT"], frontAppPort: process.env["NEXT_PUBLIC_FRONT_APP_PORT"],
idNotBaseUrl: process.env["NEXT_PUBLIC_IDNOT_BASE_URL"],
idNotAuthorizeEndpoint: process.env["NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT"], idNotAuthorizeEndpoint: process.env["NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT"],
idNotClientId: process.env["NEXT_PUBLIC_IDNOT_CLIENT_ID"], idNotClientId: process.env["NEXT_PUBLIC_IDNOT_CLIENT_ID"],
fcAuthorizeEndpoint: process.env["NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT"], fcAuthorizeEndpoint: process.env["NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT"],