ENCOA-273

This commit is contained in:
Tiago Ribeiro
2024-12-11 14:09:10 +00:00
parent d074ec390c
commit eabfcd026b
7 changed files with 144 additions and 97 deletions

View File

@@ -4,34 +4,35 @@ import Layout from "@/components/High/Layout";
import Select from "@/components/Low/Select";
import Tooltip from "@/components/Low/Tooltip";
import { useEntityPermission } from "@/hooks/useEntityPermissions";
import {useListSearch} from "@/hooks/useListSearch";
import { useListSearch } from "@/hooks/useListSearch";
import usePagination from "@/hooks/usePagination";
import {Entity, EntityWithRoles, Role} from "@/interfaces/entity";
import {GroupWithUsers, User} from "@/interfaces/user";
import {sessionOptions} from "@/lib/session";
import {USER_TYPE_LABELS} from "@/resources/user";
import { Entity, EntityWithRoles, Role } from "@/interfaces/entity";
import { GroupWithUsers, User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import { USER_TYPE_LABELS } from "@/resources/user";
import { findBy, mapBy, redirect, serialize } from "@/utils";
import {getEntityWithRoles} from "@/utils/entities.be";
import {convertToUsers, getGroup} from "@/utils/groups.be";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import {checkAccess, doesEntityAllow, getTypesOfUser} from "@/utils/permissions";
import {getUserName, isAdmin} from "@/utils/users";
import {filterAllowedUsers, getEntitiesUsers, getEntityUsers, getLinkedUsers, getSpecificUsers, getUsers} from "@/utils/users.be";
import { getEntityWithRoles } from "@/utils/entities.be";
import { convertToUsers, getGroup } from "@/utils/groups.be";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import { checkAccess, doesEntityAllow, getTypesOfUser } from "@/utils/permissions";
import { getUserName, isAdmin } from "@/utils/users";
import { filterAllowedUsers, getEntitiesUsers, getEntityUsers, getLinkedUsers, getSpecificUsers, getUsers } from "@/utils/users.be";
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
import axios from "axios";
import clsx from "clsx";
import {withIronSessionSsr} from "iron-session/next";
import { withIronSessionSsr } from "iron-session/next";
import moment from "moment";
import Head from "next/head";
import Link from "next/link";
import {useRouter} from "next/router";
import {Divider} from "primereact/divider";
import {useEffect, useMemo, useState} from "react";
import { useRouter } from "next/router";
import { Divider } from "primereact/divider";
import { useEffect, useMemo, useState } from "react";
import {
BsChevronLeft,
BsClockFill,
BsEnvelopeFill,
BsFillPersonVcardFill,
BsHash,
BsPerson,
BsPlus,
BsSquare,
@@ -40,15 +41,15 @@ import {
BsTrash,
BsX,
} from "react-icons/bs";
import {toast} from "react-toastify";
import { toast } from "react-toastify";
export const getServerSideProps = withIronSessionSsr(async ({req, params}) => {
export const getServerSideProps = withIronSessionSsr(async ({ req, params }) => {
const user = req.session.user as User;
if (!user) return redirect("/login")
if (shouldRedirectHome(user)) return redirect("/")
const {id} = params as {id: string};
const { id } = params as { id: string };
const entity = await getEntityWithRoles(id);
if (!entity) return redirect("/entities")
@@ -56,12 +57,12 @@ export const getServerSideProps = withIronSessionSsr(async ({req, params}) => {
if (!doesEntityAllow(user, entity, "view_entities")) return redirect(`/entities`)
const linkedUsers = await (isAdmin(user) ? getUsers() : getEntitiesUsers(mapBy(user.entities, 'id'),
{$and: [{type: {$ne: "developer"}}, {type: {$ne: "admin"}}]}))
{ $and: [{ type: { $ne: "developer" } }, { type: { $ne: "admin" } }] }))
const entityUsers = await (isAdmin(user) ? getEntityUsers(id) : filterAllowedUsers(user, [entity]));
const usersWithRole = entityUsers.map((u) => {
const e = u.entities.find((e) => e.id === id);
return {...u, role: findBy(entity.roles, 'id', e?.role)};
return { ...u, role: findBy(entity.roles, 'id', e?.role) };
});
return {
@@ -74,7 +75,7 @@ export const getServerSideProps = withIronSessionSsr(async ({req, params}) => {
};
}, sessionOptions);
type UserWithRole = User & {role?: Role};
type UserWithRole = User & { role?: Role };
interface Props {
user: User;
@@ -83,7 +84,7 @@ interface Props {
linkedUsers: User[];
}
export default function Home({user, entity, users, linkedUsers}: Props) {
export default function Home({ user, entity, users, linkedUsers }: Props) {
const [isAdding, setIsAdding] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [selectedUsers, setSelectedUsers] = useState<string[]>([]);
@@ -110,7 +111,7 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
setIsLoading(true);
axios
.patch(`/api/entities/${entity.id}/users`, {add: false, members: selectedUsers})
.patch(`/api/entities/${entity.id}/users`, { add: false, members: selectedUsers })
.then(() => {
toast.success("The entity has been updated successfully!");
router.replace(router.asPath);
@@ -132,7 +133,7 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
const defaultRole = findBy(entity.roles, 'isDefault', true)!
axios
.patch(`/api/entities/${entity.id}/users`, {add: true, members: selectedUsers, role: defaultRole.id})
.patch(`/api/entities/${entity.id}/users`, { add: true, members: selectedUsers, role: defaultRole.id })
.then(() => {
toast.success("The entity has been updated successfully!");
router.replace(router.asPath);
@@ -153,7 +154,28 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
setIsLoading(true);
axios
.patch(`/api/entities/${entity.id}`, {label})
.patch(`/api/entities/${entity.id}`, { label })
.then(() => {
toast.success("The entity has been updated successfully!");
router.replace(router.asPath);
})
.catch((e) => {
console.error(e);
toast.error("Something went wrong!");
})
.finally(() => setIsLoading(false));
};
const editLicenses = () => {
if (!isAdmin(user)) return;
const licenses = prompt("Update the number of licenses:", (entity.licenses || 0).toString());
if (!licenses) return;
if (!parseInt(licenses) || parseInt(licenses) <= 0) return toast.error("Write a valid number of licenses!")
setIsLoading(true);
axios
.patch(`/api/entities/${entity.id}`, { licenses })
.then(() => {
toast.success("The entity has been updated successfully!");
router.replace(router.asPath);
@@ -190,7 +212,7 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
setIsLoading(true);
axios
.post(`/api/roles/${role}/users`, {users: selectedUsers})
.post(`/api/roles/${role}/users`, { users: selectedUsers })
.then(() => {
toast.success("The role has been assigned successfully!");
router.replace(router.asPath);
@@ -274,7 +296,7 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
className="text-mti-purple hover:text-mti-purple-dark transition ease-in-out duration-300 text-xl">
<BsChevronLeft />
</Link>
<h2 className="font-bold text-2xl">{entity.label}</h2>
<h2 className="font-bold text-2xl">{entity.label} {isAdmin(user) && `- ${entity.licenses || 0} licenses`}</h2>
</div>
</div>
<div className="flex items-center gap-2">
@@ -285,6 +307,15 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
<BsTag />
<span className="text-xs">Rename Entity</span>
</button>
{isAdmin(user) && (
<button
onClick={editLicenses}
disabled={isLoading || !isAdmin(user)}
className="flex items-center gap-1 px-2 py-2 border rounded-full hover:bg-neutral-100 disabled:hover:bg-transparent disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer transition ease-in-out duration-300">
<BsHash />
<span className="text-xs">Edit Licenses</span>
</button>
)}
<button
onClick={() => router.push(`/entities/${entity.id}/roles`)}
disabled={isLoading || !canViewRoles}
@@ -325,7 +356,7 @@ export default function Home({user, entity, users, linkedUsers}: Props) {
{entity.roles.map((role) => (
<MenuItem key={role.id}>
<button onClick={() => assignUsersToRole(role.id)} className="p-4 hover:bg-neutral-100 w-32">
{ role.label }
{role.label}
</button>
</MenuItem>
))}