Merge branch 'staging' into preprod
This commit is contained in:
commit
346e51b473
16
package-lock.json
generated
16
package-lock.json
generated
@ -23,7 +23,7 @@
|
||||
"eslint-config-next": "13.2.4",
|
||||
"form-data": "^4.0.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.130",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.132",
|
||||
"next": "13.2.4",
|
||||
"prettier": "^2.8.7",
|
||||
"react": "18.2.0",
|
||||
@ -1526,9 +1526,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001610",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001610.tgz",
|
||||
"integrity": "sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==",
|
||||
"version": "1.0.30001611",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001611.tgz",
|
||||
"integrity": "sha512-19NuN1/3PjA3QI8Eki55N8my4LzfkMCRLgCVfrl/slbSAchQfV0+GwjPrK3rq37As4UCLlM/DHajbKkAqbv92Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -3504,7 +3504,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/le-coffre-resources": {
|
||||
"resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#1ecb4711cfdf1c6efc59e06642ba4dbbeb746e74",
|
||||
"resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#888194736ec642c64a7f6e878f5ded4fc480d4a0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"class-transformer": "^0.5.1",
|
||||
@ -3742,9 +3742,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "3.58.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.58.0.tgz",
|
||||
"integrity": "sha512-pXY1jnGf5T7b8UNzWzIqf0EkX4bx/w8N2AvwlGnk2SYYA/kzDVPaH0Dh0UG4EwxBB5eKOIZKPr8VAHSHL1DPGg==",
|
||||
"version": "3.59.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.59.0.tgz",
|
||||
"integrity": "sha512-HyyfzvTLCE8b1SX2nWimlra8cibEsypcSu/Az4SXMhWhtuctkwAX7qsEYNjUOIoYtPV884oN3wtYTN+iZKBtvw==",
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
|
@ -25,7 +25,7 @@
|
||||
"eslint-config-next": "13.2.4",
|
||||
"form-data": "^4.0.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.130",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.132",
|
||||
"next": "13.2.4",
|
||||
"prettier": "^2.8.7",
|
||||
"react": "18.2.0",
|
||||
|
49
src/front/Api/LeCoffreApi/Admin/RulesGroups/RulesGroups.ts
Normal file
49
src/front/Api/LeCoffreApi/Admin/RulesGroups/RulesGroups.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { RulesGroup } from "le-coffre-resources/dist/Admin";
|
||||
|
||||
import BaseAdmin from "../BaseAdmin";
|
||||
|
||||
export type IGetRulesGroupsParams = {
|
||||
where?: {};
|
||||
include?: {};
|
||||
select?: {};
|
||||
};
|
||||
|
||||
export default class RulesGroups extends BaseAdmin {
|
||||
private static instance: RulesGroups;
|
||||
private readonly baseURl = this.namespaceUrl.concat("/rules-groups");
|
||||
|
||||
private constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static getInstance() {
|
||||
if (!this.instance) {
|
||||
return new RulesGroups();
|
||||
} else {
|
||||
return this.instance;
|
||||
}
|
||||
}
|
||||
|
||||
public async get(q: IGetRulesGroupsParams): Promise<RulesGroup[]> {
|
||||
const url = new URL(this.baseURl);
|
||||
const query = { q };
|
||||
Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
||||
try {
|
||||
return await this.getRequest<RulesGroup[]>(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public async getByUid(uid: string, q?: any): Promise<RulesGroup> {
|
||||
const url = new URL(this.baseURl.concat(`/${uid}`));
|
||||
if (q) Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
||||
try {
|
||||
return await this.getRequest<RulesGroup>(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ export default function BlockList({ blocks, onSelectedBlock }: IProps) {
|
||||
},
|
||||
[blocks, onSelectedBlock],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{blocks.map((folder) => {
|
||||
@ -35,8 +36,8 @@ export default function BlockList({ blocks, onSelectedBlock }: IProps) {
|
||||
</div>
|
||||
<div className={classes["right-side"]}>
|
||||
{folder.hasFlag && <WarningBadge />}
|
||||
{folder.rightIcon}
|
||||
<Image alt="chevron" src={ChevronIcon} />
|
||||
{folder.rightIcon && folder.rightIcon}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -53,6 +53,18 @@ export default function CollaboratorListContainer(props: IProps) {
|
||||
name: user.contact?.first_name + " " + user.contact?.last_name,
|
||||
id: user.uid!,
|
||||
selected: user.uid === collaboratorUid,
|
||||
rightIcon: user.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) ? (
|
||||
<div
|
||||
style={{
|
||||
height: "12px",
|
||||
width: "12px",
|
||||
borderRadius: "100px",
|
||||
backgroundColor: "var(--green-flash)",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
};
|
||||
})}
|
||||
onSelectedBlock={onSelectedBlock}
|
||||
|
@ -103,7 +103,6 @@ export default class DefaultCollaboratorDashboard extends React.Component<IProps
|
||||
};
|
||||
|
||||
const collaborators = await Users.getInstance().get(query);
|
||||
console.log(collaborators);
|
||||
this.setState({ collaborators });
|
||||
}
|
||||
public override componentWillUnmount() {
|
||||
|
@ -1,6 +1,22 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
.folder-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.subscription-active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.subscription-active-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: var(--green-flash);
|
||||
border-radius: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.user-infos {
|
||||
background-color: var(--grey-soft);
|
||||
display: flex;
|
||||
|
@ -123,6 +123,11 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
contact: true,
|
||||
office_role: true,
|
||||
role: true,
|
||||
seats: {
|
||||
include: {
|
||||
subscription: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!user) return;
|
||||
@ -145,6 +150,14 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["folder-header"]}>
|
||||
<Typography typo={ITypo.H1Bis}>{userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name}</Typography>
|
||||
{userSelected && userSelected.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) && (
|
||||
<div className={classes["subscription-active"]}>
|
||||
<div className={classes["subscription-active-dot"]} />
|
||||
<Typography typo={ITypo.P_18} color={ITypoColor.GREEN_FLASH}>
|
||||
Abonnement actif
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes["user-infos"]}>
|
||||
<div className={classes["user-infos-row"]}>
|
||||
|
@ -1,28 +1,28 @@
|
||||
import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles";
|
||||
import Rules from "@Front/Api/LeCoffreApi/Admin/Rules/Rules";
|
||||
import Button from "@Front/Components/DesignSystem/Button";
|
||||
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
|
||||
import Form from "@Front/Components/DesignSystem/Form";
|
||||
import Confirm from "@Front/Components/DesignSystem/Modal/Confirm";
|
||||
import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import DefaultRoleDashboard from "@Front/Components/LayoutTemplates/DefaultRoleDashboard";
|
||||
import { OfficeRole, Rule } from "le-coffre-resources/dist/Admin";
|
||||
import { OfficeRole, Rule, RulesGroup } from "le-coffre-resources/dist/Admin";
|
||||
import { useRouter } from "next/router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import React from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import RulesGroups from "@Front/Api/LeCoffreApi/Admin/RulesGroups/RulesGroups";
|
||||
|
||||
type IProps = {};
|
||||
type RuleCheckbox = Rule & {
|
||||
type RuleGroupsCheckbox = RulesGroup & {
|
||||
checked: boolean;
|
||||
};
|
||||
export default function RolesInformations(props: IProps) {
|
||||
|
||||
export default function RolesInformations() {
|
||||
const router = useRouter();
|
||||
let { roleUid } = router.query;
|
||||
|
||||
const [roleSelected, setRoleSelected] = useState<OfficeRole | null>(null);
|
||||
const [rulesCheckboxes, setRulesCheckboxes] = useState<RuleCheckbox[]>([]);
|
||||
const [rulesGroupsCheckboxes, setRulesGroupsCheckboxes] = useState<RuleGroupsCheckbox[]>([]);
|
||||
const [selectAll, setSelectAll] = useState<boolean>(false);
|
||||
|
||||
const [isConfirmModalOpened, setIsConfirmModalOpened] = useState<boolean>(false);
|
||||
@ -45,35 +45,28 @@ export default function RolesInformations(props: IProps) {
|
||||
},
|
||||
});
|
||||
|
||||
const rules = await Rules.getInstance().get({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
namespace: "notary",
|
||||
},
|
||||
{
|
||||
namespace: "collaborator",
|
||||
},
|
||||
],
|
||||
const rulesGroups = await RulesGroups.getInstance().get({
|
||||
include: {
|
||||
rules: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!role) return;
|
||||
setRoleSelected(role);
|
||||
if (!role.rules) return;
|
||||
const rulesCheckboxes = rules
|
||||
.map((rule) => {
|
||||
if (role.rules?.find((r) => r.uid === rule.uid)) {
|
||||
return { ...rule, checked: true };
|
||||
const rulesCheckboxes = rulesGroups
|
||||
.map((ruleGroup) => {
|
||||
if (ruleGroup.rules?.every((rule) => role.rules?.find((r) => r.uid === rule.uid))) {
|
||||
return { ...ruleGroup, checked: true };
|
||||
}
|
||||
return { ...rule, checked: false };
|
||||
return { ...ruleGroup, checked: false };
|
||||
})
|
||||
.sort((ruleA, ruleB) => (ruleA.label < ruleB.label ? 1 : -1))
|
||||
.sort((ruleA, ruleB) => (ruleA.name! < ruleB.name! ? 1 : -1))
|
||||
.sort((rule) => (rule.checked ? -1 : 1));
|
||||
|
||||
const selectAll = rulesCheckboxes.every((rule) => rule.checked);
|
||||
setSelectAll(selectAll);
|
||||
setRulesCheckboxes(rulesCheckboxes);
|
||||
setRulesGroupsCheckboxes(rulesCheckboxes);
|
||||
}
|
||||
|
||||
getUser();
|
||||
@ -83,18 +76,25 @@ export default function RolesInformations(props: IProps) {
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSelectAll(e.target.checked);
|
||||
const checked = e.target.checked;
|
||||
rulesCheckboxes.forEach((rule) => (rule.checked = checked));
|
||||
setRulesCheckboxes([...rulesCheckboxes]);
|
||||
rulesGroupsCheckboxes.forEach((rule) => (rule.checked = checked));
|
||||
setRulesGroupsCheckboxes([...rulesGroupsCheckboxes]);
|
||||
},
|
||||
[rulesCheckboxes],
|
||||
[rulesGroupsCheckboxes],
|
||||
);
|
||||
|
||||
const modifyRules = useCallback(async () => {
|
||||
if (!roleSelected || !roleSelected.uid) return;
|
||||
const rules = rulesCheckboxes.filter((rule) => rule.checked)?.map((rule) => Rule.hydrate<Rule>(rule));
|
||||
const rulesGroupsChecked = rulesGroupsCheckboxes.filter((rule) => rule.checked);
|
||||
|
||||
let newRules: Rule[] = [];
|
||||
|
||||
for (let ruleGroup of rulesGroupsChecked) {
|
||||
if (!ruleGroup.rules) continue;
|
||||
newRules = [...newRules, ...ruleGroup.rules];
|
||||
}
|
||||
await OfficeRoles.getInstance().put(roleSelected.uid, {
|
||||
uid: roleSelected.uid,
|
||||
rules,
|
||||
rules: newRules,
|
||||
});
|
||||
|
||||
const roleUpdated = await OfficeRoles.getInstance().getByUid(roleSelected.uid, {
|
||||
@ -104,17 +104,17 @@ export default function RolesInformations(props: IProps) {
|
||||
});
|
||||
setRoleSelected(roleUpdated);
|
||||
closeConfirmModal();
|
||||
}, [closeConfirmModal, roleSelected, rulesCheckboxes]);
|
||||
}, [closeConfirmModal, roleSelected, rulesGroupsCheckboxes]);
|
||||
|
||||
const handleRuleChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const ruleUid = e.target.value;
|
||||
const rule = rulesCheckboxes.find((rule) => rule.uid === ruleUid);
|
||||
const rule = rulesGroupsCheckboxes.find((rule) => rule.uid === ruleUid);
|
||||
if (!rule) return;
|
||||
rule.checked = e.target.checked;
|
||||
setRulesCheckboxes([...rulesCheckboxes]);
|
||||
setRulesGroupsCheckboxes([...rulesGroupsCheckboxes]);
|
||||
},
|
||||
[rulesCheckboxes],
|
||||
[rulesGroupsCheckboxes],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -142,11 +142,11 @@ export default function RolesInformations(props: IProps) {
|
||||
</div>
|
||||
<Form>
|
||||
<div className={classes["rights"]}>
|
||||
{rulesCheckboxes.map((rule) => (
|
||||
<div className={classes["right"]} key={rule.uid}>
|
||||
{rulesGroupsCheckboxes.map((ruleGroup) => (
|
||||
<div className={classes["right"]} key={ruleGroup.uid}>
|
||||
<CheckBox
|
||||
option={{ label: rule.label, value: rule.uid }}
|
||||
checked={rule.checked}
|
||||
option={{ label: ruleGroup.name!, value: ruleGroup.uid }}
|
||||
checked={ruleGroup.checked}
|
||||
onChange={handleRuleChange}
|
||||
/>
|
||||
</div>
|
||||
|
@ -81,7 +81,6 @@ export default function SubscriptionFacturation() {
|
||||
loadSubscription();
|
||||
}, [loadSubscription]);
|
||||
|
||||
console.log(forfeitsPrices[EForfeitType.unlimited].toString());
|
||||
return (
|
||||
<DefaultTemplate title="Nouvelle souscription">
|
||||
{subscription && (
|
||||
|
Loading…
x
Reference in New Issue
Block a user