Merge branch 'dev' into feature/ora-502-ask-another-document

This commit is contained in:
Maxime Lalo 2023-05-09 17:00:39 +02:00 committed by GitHub
commit 021a81ea1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 239 additions and 54 deletions

58
package-lock.json generated
View File

@ -19,7 +19,7 @@
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"eslint": "8.36.0", "eslint": "8.36.0",
"eslint-config-next": "13.2.4", "eslint-config-next": "13.2.4",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.38", "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.40",
"next": "13.2.4", "next": "13.2.4",
"prettier": "^2.8.7", "prettier": "^2.8.7",
"react": "18.2.0", "react": "18.2.0",
@ -1235,6 +1235,11 @@
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/available-typed-arrays": { "node_modules/available-typed-arrays": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
@ -1482,6 +1487,17 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -1637,6 +1653,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dir-glob": { "node_modules/dir-glob": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -2376,6 +2400,19 @@
"is-callable": "^1.1.3" "is-callable": "^1.1.3"
} }
}, },
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -3266,6 +3303,25 @@
"node": ">=8.6" "node": ">=8.6"
} }
}, },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mimic-fn": { "node_modules/mimic-fn": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",

View File

@ -21,7 +21,8 @@
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"eslint": "8.36.0", "eslint": "8.36.0",
"eslint-config-next": "13.2.4", "eslint-config-next": "13.2.4",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.38", "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.40",
"form-data": "^4.0.0",
"next": "13.2.4", "next": "13.2.4",
"prettier": "^2.8.7", "prettier": "^2.8.7",
"react": "18.2.0", "react": "18.2.0",

View File

@ -31,6 +31,7 @@ export default abstract class BaseApiService {
} }
protected buildBody(body: { [key: string]: unknown }): string { protected buildBody(body: { [key: string]: unknown }): string {
console.log("2 >> body >>>", JSON.stringify(body));
return JSON.stringify(body); return JSON.stringify(body);
} }
@ -54,6 +55,17 @@ export default abstract class BaseApiService {
); );
} }
protected async postRequestFormData<T>(url: URL, body: FormData) {
return this.sendRequest<T>(
async () =>
await fetch(url, {
method: "POST",
headers: this.buildHeaders(ContentType.FORM_DATA),
body,
}),
);
}
protected async putRequest<T>(url: URL, body: { [key: string]: unknown } = {}) { protected async putRequest<T>(url: URL, body: { [key: string]: unknown } = {}) {
const request = async () => const request = async () =>
await fetch(url, { await fetch(url, {

View File

@ -13,7 +13,8 @@ export interface IGetDocumentsparams {
// TODO Type getbyuid query params // TODO Type getbyuid query params
export type IPutDocumentsParams = { export type IPutDocumentsParams = {
document_status?: EDocumentStatus document_status?: EDocumentStatus;
refused_reason?: string;
}; };
export interface IPostDocumentsParams {} export interface IPostDocumentsParams {}
@ -37,7 +38,8 @@ export default class Documents extends BaseSuperAdmin {
public async get(q: IGetDocumentsparams): Promise<Document[]> { public async get(q: IGetDocumentsparams): Promise<Document[]> {
const url = new URL(this.baseURl); const url = new URL(this.baseURl);
Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); const query = { q };
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try { try {
return await this.getRequest<Document[]>(url); return await this.getRequest<Document[]>(url);
} catch (err) { } catch (err) {
@ -80,4 +82,14 @@ export default class Documents extends BaseSuperAdmin {
return Promise.reject(err); return Promise.reject(err);
} }
} }
public async delete(uid: string): Promise<Document> {
const url = new URL(this.baseURl.concat(`/${uid}`));
try {
return await this.deleteRequest<Document>(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
} }

View File

@ -35,13 +35,14 @@ export default class Files extends BaseSuperAdmin {
public async get(q: IGetFilesparams): Promise<File[]> { public async get(q: IGetFilesparams): Promise<File[]> {
const url = new URL(this.baseURl); const url = new URL(this.baseURl);
Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); const query = { q };
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try { try {
const files = await this.getRequest<File[]>(url); const files = await this.getRequest<File[]>(url);
files.forEach(async(file) => { files.forEach(async (file) => {
file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv); file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv);
}) });
return files return files;
} catch (err) { } catch (err) {
this.onError(err); this.onError(err);
return Promise.reject(err); return Promise.reject(err);
@ -54,7 +55,7 @@ export default class Files extends BaseSuperAdmin {
public async post(body: any): Promise<File> { public async post(body: any): Promise<File> {
const url = new URL(this.baseURl); const url = new URL(this.baseURl);
try { try {
return await this.postRequest<File>(url, body); return await this.postRequestFormData<File>(url, body);
} catch (err) { } catch (err) {
this.onError(err); this.onError(err);
return Promise.reject(err); return Promise.reject(err);
@ -84,4 +85,17 @@ export default class Files extends BaseSuperAdmin {
return Promise.reject(err); return Promise.reject(err);
} }
} }
/**
* @description : Delete a folder only if the folder don't contains customers
*/
public async delete(uid: string): Promise<File> {
const url = new URL(this.baseURl.concat(`/${uid}`));
try {
return await this.deleteRequest<File>(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
} }

View File

@ -9,13 +9,15 @@ import Button, { EButtonVariant } from "../Button";
import Tooltip from "../ToolTip"; import Tooltip from "../ToolTip";
import Typography, { ITypo, ITypoColor } from "../Typography"; import Typography, { ITypo, ITypoColor } from "../Typography";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { File as FileCustomer } from "le-coffre-resources/dist/Customer"; import { Document, File as FileCustomer } from "le-coffre-resources/dist/Customer";
import Files from "@Front/Api/LeCoffreApi/SuperAdmin/Files/Files";
type IProps = { type IProps = {
title: string; title: string;
dateAsked: Date; dateAsked: Date;
defaultFiles?: FileCustomer[]; defaultFiles?: FileCustomer[];
onChange?: (files: File[]) => void; onChange?: (files: File[]) => void;
document: Document;
}; };
type IFile = { type IFile = {
@ -26,6 +28,7 @@ type IFile = {
type IState = { type IState = {
files: IFile[]; files: IFile[];
isDragOver: boolean; isDragOver: boolean;
currentFiles?: FileCustomer[];
}; };
export default class DepositDocument extends React.Component<IProps, IState> { export default class DepositDocument extends React.Component<IProps, IState> {
@ -38,6 +41,7 @@ export default class DepositDocument extends React.Component<IProps, IState> {
this.state = { this.state = {
files: [], files: [],
isDragOver: false, isDragOver: false,
currentFiles: this.props.defaultFiles,
}; };
this.addDocument = this.addDocument.bind(this); this.addDocument = this.addDocument.bind(this);
@ -151,7 +155,7 @@ export default class DepositDocument extends React.Component<IProps, IState> {
if (file) this.addFile(file); if (file) this.addFile(file);
} }
private addFile(file: File) { private async addFile(file: File) {
this.setState({ this.setState({
files: [ files: [
...this.state.files, ...this.state.files,
@ -163,17 +167,33 @@ export default class DepositDocument extends React.Component<IProps, IState> {
}); });
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file)); if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
const formData = new FormData();
formData.append("file", file, file.name);
const query = JSON.stringify({ document: { uid: this.props.document.uid } });
formData.append("q", query);
const newFile = await Files.getInstance().post(formData);
const files = this.state.currentFiles ? [...this.state.currentFiles, newFile] : [newFile];
this.setState({
currentFiles: files,
});
} }
private removeFile(e: any) { private async removeFile(e: any) {
const image = e.target as HTMLElement; const image = e.target as HTMLElement;
const indexToRemove = image.getAttribute("data-file"); const indexToRemove = image.getAttribute("data-file");
if (!indexToRemove) return; if (!indexToRemove) return;
// const file = this.state.files.find((file) => file.index === parseInt(indexToRemove));
this.setState({ this.setState({
files: this.state.files.filter((file) => file.index !== parseInt(indexToRemove)), files: this.state.files.filter((file) => file.index !== parseInt(indexToRemove)),
}); });
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file)); if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
// TODO Finir la suppression de fichier
// const deletedFileUid = this.props.document.files?.find((file) => file.file_path === newFile.file_path)?.uid;
// console.log({ deletedFileUid });
// await Files.getInstance().delete(file?.uid);
} }
private async onFileChange() { private async onFileChange() {

View File

@ -67,7 +67,6 @@ export default class UserFolderHeader extends React.Component<IProps, IState> {
} }
private hasPendingFiles() { private hasPendingFiles() {
console.log(this.props.folder.documents);
const documents = const documents =
this.props.folder.documents?.filter((document) => document.depositor?.contact?.uid === this.props.customer.contact?.uid) ?? []; this.props.folder.documents?.filter((document) => document.depositor?.contact?.uid === this.props.customer.contact?.uid) ?? [];
const notAskedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.DEPOSITED) ?? []; const notAskedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.DEPOSITED) ?? [];

View File

@ -15,6 +15,7 @@ import classes from "./classes.module.scss";
import DocumentList from "./DocumentList"; import DocumentList from "./DocumentList";
import UserFolderHeader from "./UserFolderHeader"; import UserFolderHeader from "./UserFolderHeader";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import Documents from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents";
type IProps = { type IProps = {
customer: Customer; customer: Customer;
@ -26,6 +27,7 @@ type IProps = {
}; };
type IState = { type IState = {
isOpenDeletionModal: boolean; isOpenDeletionModal: boolean;
selectedDocumentToDelete: string;
}; };
export default class UserFolder extends React.Component<IProps, IState> { export default class UserFolder extends React.Component<IProps, IState> {
@ -39,10 +41,12 @@ export default class UserFolder extends React.Component<IProps, IState> {
super(props); super(props);
this.state = { this.state = {
isOpenDeletionModal: false, isOpenDeletionModal: false,
selectedDocumentToDelete: "",
}; };
this.closeDeletionModal = this.closeDeletionModal.bind(this); this.closeDeletionModal = this.closeDeletionModal.bind(this);
this.openDeletionModal = this.openDeletionModal.bind(this); this.openDeletionModal = this.openDeletionModal.bind(this);
this.changeUserFolder = this.changeUserFolder.bind(this); this.changeUserFolder = this.changeUserFolder.bind(this);
this.deleteAskedDocument = this.deleteAskedDocument.bind(this);
} }
public override render(): JSX.Element { public override render(): JSX.Element {
const documentsAsked: Document[] | null = this.getDocumentsByStatus("ASKED"); const documentsAsked: Document[] | null = this.getDocumentsByStatus("ASKED");
@ -55,6 +59,7 @@ export default class UserFolder extends React.Component<IProps, IState> {
<Confirm <Confirm
isOpen={this.state.isOpenDeletionModal} isOpen={this.state.isOpenDeletionModal}
onClose={this.closeDeletionModal} onClose={this.closeDeletionModal}
onAccept={this.deleteAskedDocument}
closeBtn closeBtn
header={"Supprimer la demande de document ?"} header={"Supprimer la demande de document ?"}
cancelText={"Cancel"} cancelText={"Cancel"}
@ -122,11 +127,23 @@ export default class UserFolder extends React.Component<IProps, IState> {
this.rootRefElement.current?.style.setProperty("--animation-delay", this.props.animationDelay!.toString().concat("ms")); this.rootRefElement.current?.style.setProperty("--animation-delay", this.props.animationDelay!.toString().concat("ms"));
} }
private async deleteAskedDocument(){
try{
await Documents.getInstance().delete(this.state.selectedDocumentToDelete);
window.location.reload();
}catch(e){
console.error(e);
}
}
private calculateDocumentsPercentageProgress(): number { private calculateDocumentsPercentageProgress(): number {
if (!this.props.customer.documents) return 0; if (!this.props.customer.documents) return 0;
const totalDocuments: number = this.props.customer.documents.length; const totalDocuments: number = this.props.customer.documents.length;
const numberDocumentsAsked: number = this.getDocumentsByStatus(EDocumentStatus.ASKED)?.length || 0; const numberDocumentsAsked: number = this.getDocumentsByStatus(EDocumentStatus.ASKED)?.length || 0;
return Math.round(((totalDocuments - numberDocumentsAsked) / totalDocuments) * 100);
const percentage = Math.round(((totalDocuments - numberDocumentsAsked) / totalDocuments) * 100);
if(!percentage) return 0;
return percentage;
} }
private getDocumentsByStatus(status: string): Document[] | null { private getDocumentsByStatus(status: string): Document[] | null {
@ -159,9 +176,11 @@ export default class UserFolder extends React.Component<IProps, IState> {
} }
private openDeletionModal(uid?: string): void { private openDeletionModal(uid?: string): void {
// TODO: call API to delete document if(!uid) return;
this.setState({ this.setState({
isOpenDeletionModal: true, isOpenDeletionModal: true,
selectedDocumentToDelete: uid,
}); });
} }
private closeDeletionModal(): void { private closeDeletionModal(): void {

View File

@ -8,10 +8,14 @@ import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
import React from "react"; import React from "react";
import { documentDeposited } from "../DesignSystem/dummyData"; import { documentDeposited } from "../DesignSystem/dummyData";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents";
import { Document } from "le-coffre-resources/dist/Customer";
import Users from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users";
type IProps = {}; type IProps = {};
type IState = { type IState = {
isAddDocumentModalVisible: boolean; isAddDocumentModalVisible: boolean;
documents: Document[];
}; };
export default class ClientDashboard extends Base<IProps, IState> { export default class ClientDashboard extends Base<IProps, IState> {
@ -19,6 +23,7 @@ export default class ClientDashboard extends Base<IProps, IState> {
super(props); super(props);
this.state = { this.state = {
isAddDocumentModalVisible: false, isAddDocumentModalVisible: false,
documents: [],
}; };
this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this); this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this);
this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this); this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this);
@ -31,16 +36,15 @@ export default class ClientDashboard extends Base<IProps, IState> {
{this.renderHeader()} {this.renderHeader()}
<div className={classes["sub-container"]}> <div className={classes["sub-container"]}>
<div className={classes["content"]}> <div className={classes["content"]}>
<DepositDocument {this.state.documents?.map((document) => (
title={"Carte d'identité - recto-verso"} <DepositDocument
dateAsked={new Date()} title={"Carte d'identité - recto-verso"}
defaultFiles={documentDeposited.files ?? []} dateAsked={new Date()}
/> document={document}
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} /> key={document.uid}
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} /> defaultFiles={document.files ?? []}
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} /> />
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} /> ))}
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
</div> </div>
<Typography typo={ITypo.H2}>Documents supplémentaires (facultatif)</Typography> <Typography typo={ITypo.H2}>Documents supplémentaires (facultatif)</Typography>
<Typography typo={ITypo.P_16} className={classes["text"]}> <Typography typo={ITypo.P_16} className={classes["text"]}>
@ -67,7 +71,7 @@ export default class ClientDashboard extends Base<IProps, IState> {
Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le
document correspondant. document correspondant.
</Typography> </Typography>
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} /> <DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} document={documentDeposited} />
</div> </div>
</Confirm> </Confirm>
</div> </div>
@ -100,6 +104,21 @@ export default class ClientDashboard extends Base<IProps, IState> {
); );
} }
public override async componentDidMount() {
// TODO Get documents of the current customer according to userStore
// REMOVE this mock
const mockUsers = (await Users.getInstance().get({}))[2];
const query: IGetDocumentsparams = {
where: { depositor: mockUsers?.uid },
include: {
files: true,
},
};
const documents: Document[] = await Documents.getInstance().get(query);
console.log({ documents });
this.setState({ documents });
}
private onCloseModalAddDocument() { private onCloseModalAddDocument() {
this.setState({ isAddDocumentModalVisible: false }); this.setState({ isAddDocumentModalVisible: false });
} }

View File

@ -276,7 +276,6 @@ class AskDocumentsClass extends BasePage<IPropsClass, IState> {
}catch(e){ }catch(e){
console.error(e); console.error(e);
} }
console.log(values["document_types"]);
} }
} }

View File

@ -66,6 +66,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
this.hasPrevious = this.hasPrevious.bind(this); this.hasPrevious = this.hasPrevious.bind(this);
this.hasNext = this.hasNext.bind(this); this.hasNext = this.hasNext.bind(this);
this.refuseDocument = this.refuseDocument.bind(this);
} }
public override render(): JSX.Element | null { public override render(): JSX.Element | null {
@ -156,7 +157,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
<Confirm <Confirm
isOpen={this.state.isRefuseModalVisible} isOpen={this.state.isRefuseModalVisible}
onClose={this.closeModals} onClose={this.closeModals}
onAccept={this.closeModals} onAccept={this.refuseDocument}
closeBtn closeBtn
header={"Refuser le document ?"} header={"Refuser le document ?"}
cancelText={"Annuler"} cancelText={"Annuler"}
@ -244,6 +245,23 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
return index < this.state.document!.files!.length; return index < this.state.document!.files!.length;
} }
private async refuseDocument(){
try{
await Documents.getInstance().put(this.props.documentUid, {
document_status: EDocumentStatus.REFUSED,
refused_reason: this.state.refuseText
});
this.props.router.push(
Module.getInstance()
.get()
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid),
);
}catch(e){
console.error(e);
}
}
private async validateAnchoring() { private async validateAnchoring() {
this.setState({ this.setState({
hasValidateAnchoring: true, hasValidateAnchoring: true,

View File

@ -5,7 +5,7 @@ import crypto from "crypto";
@Service() @Service()
export default class CryptoService { export default class CryptoService {
private jwkKey: JsonWebKey; private jwkKey: JsonWebKey;
private subtle: SubtleCrypto = crypto.webcrypto.subtle private subtle: SubtleCrypto = window.crypto.subtle;
constructor(protected variables: FrontendVariables) { constructor(protected variables: FrontendVariables) {
this.jwkKey = { this.jwkKey = {
kty: "oct", kty: "oct",
@ -16,7 +16,7 @@ export default class CryptoService {
} }
private async getKey() { private async getKey() {
return await this.subtle.importKey("jwk", this.jwkKey, {name: "AES-GCM"}, false, ["encrypt", "decrypt"]); return await this.subtle.importKey("jwk", this.jwkKey, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
} }
/** /**
@ -36,8 +36,8 @@ export default class CryptoService {
encodedData, encodedData,
); );
const cipherText = Buffer.from(cipherData).toString('base64'); const cipherText = Buffer.from(cipherData).toString("base64");
const ivStringified = Buffer.from(iv).toString('base64'); const ivStringified = Buffer.from(iv).toString("base64");
return { cipherText, ivStringified }; return { cipherText, ivStringified };
} }
@ -47,8 +47,8 @@ export default class CryptoService {
* @throws {Error} If data cannot be decrypted * @throws {Error} If data cannot be decrypted
*/ */
public async decrypt(cipherText: string, ivStringified: string): Promise<string> { public async decrypt(cipherText: string, ivStringified: string): Promise<string> {
const cipherData = Buffer.from(cipherText, 'base64'); const cipherData = Buffer.from(cipherText, "base64");
const iv = Buffer.from(ivStringified, 'base64'); const iv = Buffer.from(ivStringified, "base64");
const key = await this.getKey(); const key = await this.getKey();
const decryptedData = await this.subtle.decrypt( const decryptedData = await this.subtle.decrypt(
{ {
@ -59,6 +59,6 @@ export default class CryptoService {
cipherData, cipherData,
); );
return Buffer.from(decryptedData).toString('utf-8'); return Buffer.from(decryptedData).toString("utf-8");
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"incremental": false, "incremental": false,
"target": "es5", "target": "es5",
"module": "CommonJS", "module": "CommonJS",
"lib": [ "lib": [
@ -20,7 +20,7 @@
"allowUnusedLabels": false, "allowUnusedLabels": false,
"exactOptionalPropertyTypes": false, "exactOptionalPropertyTypes": false,
"noImplicitOverride": true, "noImplicitOverride": true,
"strict": true, "strict": true,
"noImplicitAny": true, "noImplicitAny": true,
"strictNullChecks": true, "strictNullChecks": true,
"strictFunctionTypes": true, "strictFunctionTypes": true,
@ -30,22 +30,38 @@
"alwaysStrict": true, "alwaysStrict": true,
"noPropertyAccessFromIndexSignature": true, "noPropertyAccessFromIndexSignature": true,
/* Additional Checks */ /* Additional Checks */
"noUnusedLocals": true, "noUnusedLocals": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
"useUnknownInCatchVariables": true, "useUnknownInCatchVariables": true,
/* Module Resolution Options */ /* Module Resolution Options */
"moduleResolution": "node", "moduleResolution": "node",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@Api/*": ["src/api/*"], "@Api/*": [
"@Front/*": ["src/front/*"], "src/api/*"
"@Assets/*": ["src/front/Assets/*"], ],
"@Components/*": ["src/front/Components/*"], "@Front/*": [
"@Themes/*": ["src/front/Themes/*"], "src/front/*"
"@Stores/*": ["src/front/Stores/*"], ],
"@FrontServices/*": ["src/front/services/*"], "@Assets/*": [
"@Page/*": ["src/pages/*"], "src/front/Assets/*"
],
"@Components/*": [
"src/front/Components/*"
],
"@Themes/*": [
"src/front/Themes/*"
],
"@Stores/*": [
"src/front/Stores/*"
],
"@FrontServices/*": [
"src/front/services/*"
],
"@Page/*": [
"src/pages/*"
],
}, },
// "rootDirs": [], // "rootDirs": [],
// "typeRoots": [], // "typeRoots": [],
@ -60,19 +76,19 @@
//"inlineSources": false, //"inlineSources": false,
/* Experimental Options */ /* Experimental Options */
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"skipLibCheck": true, "skipLibCheck": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"allowJs": true, "allowJs": true,
"isolatedModules": true "isolatedModules": true
}, },
"include": [ "include": [
"next-env.d.ts", "next-env.d.ts",
"**/*.ts", "**/*.ts",
"**/*.tsx" "**/*.tsx",
, "src/front/next.config.js" ], "src/front/next.config.js"
],
"exclude": [ "exclude": [
"node_modules" "node_modules"
] ]
} }