Skip to content

Commit

Permalink
Merge pull request #26 from 2060-io/Services-list-Performance
Browse files Browse the repository at this point in the history
feat: State update added
  • Loading branch information
lotharking authored Aug 10, 2024
2 parents 41141d5 + 027a98e commit aea3ae7
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/app/services/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const Service = () => {

return (
<DefaultLayout>
<Breadcrumb pageName="Service" />
<Breadcrumb pageName="Service" sectionName="Service Provider / " />

<div className="flex flex-col gap-10">
<DtsViewEdit />
Expand Down
2 changes: 1 addition & 1 deletion src/app/services/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const metadata: Metadata = {
const Services = () => {
return (
<DefaultLayout>
<Breadcrumb pageName="Services" />
<Breadcrumb pageName="Services" sectionName="Service Provider / " />

<div className="flex flex-col gap-10">
<DtsList />
Expand Down
2 changes: 1 addition & 1 deletion src/app/templates/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import SelectDtsTemplate from "@/components/Templates/SelectDtsTemplate";
const Templates = () => {
return (
<DefaultLayout>
<Breadcrumb pageName="Templates" />
<Breadcrumb pageName="Templates" sectionName="Service Provider / " />

<div className="flex flex-col gap-10">
<SelectDtsTemplate />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { ChangeEvent, useMemo } from 'react';

function Pagination({
export function Pagination({
itemsPerPage,
setItemsPerPage,
currentPage,
Expand Down
47 changes: 47 additions & 0 deletions src/app/ui/TimedToasts/WarningTimedToast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export interface WarningTimedToastProps {
idToast: string
message: string
}

export const WarningTimedToast: React.FC<WarningTimedToastProps> = ({ idToast, message }) => {
return (
(
<div className={`absolute invisible border-1 flex items-center w-md max-w-xs p-1 mt-2 text-gray-500 bg-white rounded-lg shadow-3 shadow-warning dark:text-black dark:bg-gray-800`} id={idToast}>
<div className="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-blue-500 rounded-lg">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="w-6 h-6 text-yellow-500"
>
<path d="M1 21h22L12 2 1 21z"></path>
<path d="M12 16v2"></path>
<path d="M12 10h.01"></path>
</svg>
</div>
<div className="ms-3 text-sm font-normal" >{message}</div>
</div>
)
);
};

export function showToastWarningUpdateState(id: string) {
let element = document.getElementById(id)
element?.classList.remove('invisible')
setTimeout(() => {
element?.classList.add('opacity-0', 'transition-opacity', 'ease-in-out', 'delay-300', 'duration-1000')
}, 4000)
}

export function setInitClassNameToastWarning(idService: string) {
let element = document.getElementById('toast-'+idService)
element?.classList.remove('opacity-0', 'transition-opacity', 'ease-in-out', 'delay-300', 'duration-1000')
element?.classList.add('invisible')
}


export default WarningTimedToast;
7 changes: 4 additions & 3 deletions src/components/Breadcrumbs/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Link from "next/link";
interface BreadcrumbProps {
pageName: string;
sectionName?: string;
}
const Breadcrumb = ({ pageName }: BreadcrumbProps) => {
const Breadcrumb = ({ pageName, sectionName }: BreadcrumbProps) => {
return (
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<h2 className="text-title-md2 font-semibold text-black dark:text-white">
Expand All @@ -12,8 +13,8 @@ const Breadcrumb = ({ pageName }: BreadcrumbProps) => {
<nav>
<ol className="flex items-center gap-2">
<li>
<Link className="font-medium" href="/">
Dashboard /
<Link className="font-medium" href="#">
{sectionName}
</Link>
</li>
<li className="font-medium text-primary">{pageName}</li>
Expand Down
132 changes: 132 additions & 0 deletions src/components/Dropdowns/DropdownUpdateState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { Configuration, ConfigurationParameters, DtsVO, EntityState, GenericEntityResourceApi, GenericStateEntityTypeIdNewStatePutRequest } from '@/openapi-client';
import { useEffect, useRef, useState } from "react";
import { useAuth } from "react-oidc-context";
import { useRouter } from "next/navigation";
import { showToastWarningUpdateState, setInitClassNameToastWarning } from "@/app/ui/TimedToasts/WarningTimedToast";

export interface DropdownUpdateStateProps {
dts: DtsVO
}

export const DropdownUpdateState: React.FC<DropdownUpdateStateProps> = ({dts}) => {
const [dropdownOpen, setDropdownOpen] = useState(false);

const trigger = useRef<any>(null);
const dropdown = useRef<any>(null);
const auth = useAuth();
const router = useRouter();

// close on click outside
useEffect(() => {
const clickHandler = ({ target }: MouseEvent) => {
if (!dropdown.current) return;
if (
!dropdownOpen ||
dropdown.current.contains(target) ||
trigger.current.contains(target)
)
return;
setDropdownOpen(false);
};
document.addEventListener("click", clickHandler);
return () => document.removeEventListener("click", clickHandler);
});

// close if the esc key is pressed
useEffect(() => {
const keyHandler = (event: KeyboardEvent) => {
if (!dropdownOpen || event.code !== 'Escape') return;
setDropdownOpen(false);
}
document.addEventListener("keydown", keyHandler);
return () => document.removeEventListener("keydown", keyHandler);
});

function setStyleState(state: string): string {
let color = 'text-black';
color = 'ENABLED' === state ? 'text-success dark:text-success' : 'DISABLED' === state ? 'text-danger dark:text-danger' : 'EDITING' === state ? 'text-warning dark:text-warning' : 'text-black dark:text-white'
return color;
}

async function updateStateEntity (idService: string, entityState: string){
await setInitClassNameToastWarning(idService);
const configParameters: ConfigurationParameters = {
headers: {
'Authorization': 'Bearer ' + auth.user?.access_token ,
},
basePath: process.env.NEXT_PUBLIC_BACKEND_BASE_PATH,
};

const config = new Configuration(configParameters);

const requesParameters: GenericStateEntityTypeIdNewStatePutRequest = {
entityType: "DTS",
id: idService,
newState: entityState as EntityState
}
const genericEntityResourceApi = new GenericEntityResourceApi(config);
genericEntityResourceApi.genericStateEntityTypeIdNewStatePut(requesParameters).
then(() => {
router.refresh()
setDropdownOpen(false);
}).
catch( () => {
showToastWarningUpdateState('toast-'+idService);
router.refresh()
setDropdownOpen(false);
})
}

return (
<div className="relative text-center w-full">
<button
className={`w-full font-medium bg-transparent text-center ${setStyleState(String(dts.state))}`}
ref={trigger}
onClick={() => setDropdownOpen(!dropdownOpen)}
>
{dts.state}
<svg
className="fill-current sm:inline ms-3"
width="12"
height="8"
viewBox="0 0 12 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.410765 0.910734C0.736202 0.585297 1.26384 0.585297 1.58928 0.910734L6.00002 5.32148L10.4108 0.910734C10.7362 0.585297 11.2638 0.585297 11.5893 0.910734C11.9147 1.23617 11.9147 1.76381 11.5893 2.08924L6.58928 7.08924C6.26384 7.41468 5.7362 7.41468 5.41077 7.08924L0.410765 2.08924C0.0853277 1.76381 0.0853277 1.23617 0.410765 0.910734Z"
fill=""
/>
</svg>
</button>
<div
ref={dropdown}
onFocus={() => setDropdownOpen(true)}
onBlur={() => setDropdownOpen(false)}
className={`absolute right-0 top-full z-40 w-40 space-y-1 rounded-sm border border-stroke bg-white p-1.5 shadow-default dark:border-strokedark dark:bg-boxdark ${dropdownOpen === true ? "block" : "hidden"}`}
>
{
Object.values(EntityState).map((state, index) => {
return(
<button
id={dts.id}
key={index}
className="flex w-full items-center gap-2 rounded-sm px-4 py-1.5 text-left text-sm hover:bg-gray dark:hover:bg-meta-4"
value={state}
onClick={(e: any) => {
updateStateEntity(String(dts.id), e.target.value)
}}
>
{state}
</button>
)
})
}
</div>
</div>
);
};

export default DropdownUpdateState;
18 changes: 4 additions & 14 deletions src/components/Services/DtsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Configuration, ConfigurationParameters } from "../../openapi-client";
import { useAuth } from "react-oidc-context";
import { Log } from "oidc-client-ts";
import Link from "next/link";
import Pagination from "../Pagination/Pagination";
import { Pagination, WarningTimedToast, DropdownUpdateState } from "./index";

const sortItems = <T extends Record<string, any>>(
items: T[],
Expand Down Expand Up @@ -184,7 +184,6 @@ function DtsList() {
</button>
);
}


if (auth.isAuthenticated) {
return (
Expand All @@ -203,7 +202,7 @@ function DtsList() {
<ButtonAddService className="rounded-full bg-white dark:bg-boxdark w-10 h-10 border-2 border-gray-300 dark:border-strokedark flex items-center justify-center relative"/>
</div>
</div>
<div className="max-w-full overflow-x-auto">
<div className="max-w-full">
<table className="w-full table-auto">
<thead>
<tr className="bg-gray-2 text-left dark:bg-meta-4">
Expand Down Expand Up @@ -283,17 +282,8 @@ function DtsList() {
)}
</td>
<td className="border-b border-[#eee] px-4 py-5 text-center dark:border-strokedark">
<p
className={`inline-flex rounded-full bg-opacity-10 px-3 py-1 text-sm font-medium ${
dts.state === "ENABLED"
? "bg-success text-success"
: dts.state === "DISABLED"
? "bg-danger text-danger"
: "bg-warning text-warning"
}`}
>
{dts.state}
</p>
<DropdownUpdateState dts={dts} ></DropdownUpdateState>
<WarningTimedToast message={"Error to update State"} idToast={'toast-'+dts.id} ></WarningTimedToast>
</td>
<td className="border-b border-[#eee] px-4 py-5 text-center dark:border-strokedark">
<div className="flex items-center space-x-3.5">
Expand Down
3 changes: 3 additions & 0 deletions src/components/Services/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from '@/app/ui/TimedToasts/WarningTimedToast'
export * from '@/app/ui/Pagination/Pagination'
export * from '@/components/Dropdowns/DropdownUpdateState'
17 changes: 13 additions & 4 deletions src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { usePathname } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import SidebarLinkGroup from "./SidebarLinkGroup";
import { validate } from "uuid";

interface SidebarProps {
sidebarOpen: boolean;
Expand All @@ -13,9 +14,15 @@ interface SidebarProps {

const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
const pathname = usePathname();
const pathnames: string [] = [
'dashboard',
'/services',
'/templates'
]

const trigger = useRef<any>(null);
const sidebar = useRef<any>(null);
const validateUuidv4 = validate

let storedSidebarExpanded = "true";

Expand Down Expand Up @@ -58,6 +65,8 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
}
}, [sidebarExpanded]);



return (
<aside
ref={sidebar}
Expand Down Expand Up @@ -115,7 +124,7 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {

<SidebarLinkGroup
activeCondition={
pathname === "/" || pathname.includes("dashboard")
pathname === "/" || pathnames.includes(pathname) || validateUuidv4(pathname.split("/")[pathname.split("/").length-1])
}
>
{(handleClick, open) => {
Expand Down Expand Up @@ -238,9 +247,9 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
</Link>*/}

<div
className={`translate transform overflow-hidden ${
!open && "hidden"
}`}
className={`overflow-hidden ${
!open ? "h-0" : "h-21"
} transition-height duration-500 ease-in-out`}
>
<ul className="mb-5.5 mt-4 flex flex-col gap-2.5 pl-6">
<li>
Expand Down

0 comments on commit aea3ae7

Please sign in to comment.