updated route sites available

This commit is contained in:
berkay 2025-04-09 17:44:06 +03:00
parent 9b02620d1d
commit 531e8b2e39
11 changed files with 173 additions and 134 deletions

View File

@ -431,3 +431,48 @@ def authentication_page_valid(
status_code=status.HTTP_202_ACCEPTED,
headers=headers,
)
@auth_route.get(
path="/sites/list",
summary="Verify if page is valid returns application avaliable",
description="Verify if page is valid returns application avaliable",
)
def authentication_page_valid(
request: Request,
language: str = Header(None, alias="language"),
domain: str = Header(None, alias="domain"),
tz: str = Header(None, alias="timezone"),
):
"""
Verify if page is valid returns application that can user reach
page: { url = /building/create}
result: { "sites": ['/dashboard', '/building/create'] }
"""
token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None)
headers = {
"language": language or "",
"domain": domain or "",
"eys-ext": f"{str(uuid.uuid4())}",
"tz": tz or "GMT+3",
"token": token,
}
if not domain or not language:
return JSONResponse(
content={"error": "EYS_0003"},
status_code=status.HTTP_406_NOT_ACCEPTABLE,
headers=headers,
)
result = AuthHandlers.PageHandlers.retrieve_valid_sites_via_token(access_token=token)
if not result:
return JSONResponse(
content={"error": "EYS_0004"},
status_code=status.HTTP_406_NOT_ACCEPTABLE,
headers=headers,
)
return JSONResponse(
content={"sites": result},
status_code=status.HTTP_202_ACCEPTED,
headers=headers,
)

View File

@ -367,12 +367,10 @@ class LoginHandler:
request: FastAPI request object
data: Request body containing login credentials
{
"data": {
"domain": "evyos.com.tr",
"access_key": "karatay.berkay.sup@evyos.com.tr",
"password": "string",
"remember_me": false
}
"domain": "evyos.com.tr",
"access_key": "karatay.berkay.sup@evyos.com.tr",
"password": "string",
"remember_me": false
}
Returns:
SuccessResponse containing authentication token and user info
@ -709,7 +707,15 @@ class PasswordHandler:
class PageHandlers:
@classmethod
def retrieve_valid_page_via_token(cls, access_token: str, page_url: str):
def retrieve_valid_page_via_token(cls, access_token: str, page_url: str) -> str:
"""
Retrieve valid page via token.
{
access_token: "string",
page_url: "string"
}
Results: str(application)
"""
if result := RedisHandlers.get_object_from_redis(access_token=access_token):
if result.is_employee:
if application := result.selected_company.reachable_app_codes.get(page_url, None):
@ -720,6 +726,23 @@ class PageHandlers:
raise ValueError("EYS_0013")
@classmethod
def retrieve_valid_sites_via_token(cls, access_token: str) -> list:
"""
Retrieve valid pages via token.
{
"access_token": "string"
}
Results: list(sites)
"""
if result := RedisHandlers.get_object_from_redis(access_token=access_token):
if result.is_employee:
return result.selected_company.reachable_app_codes.keys()
elif result.is_occupant:
return result.selected_company.reachable_app_codes.keys()
raise ValueError("EYS_0013")
class AuthHandlers:
LoginHandler: LoginHandler = LoginHandler()

View File

@ -2,11 +2,11 @@
import { fetchDataWithToken, fetchData } from "../api-fetcher";
import { baseUrlAuth, tokenSecret } from "../basics";
import { cookies } from "next/headers";
import NextCrypto from "next-crypto";
import NextCrypto from "next-crypto";
const checkToken = `${baseUrlAuth}/authentication/token/check`;
const pageValid = `${baseUrlAuth}/authentication/page/valid`;
const siteUrls = `${baseUrlAuth}/authentication/page/list`;
const siteUrls = `${baseUrlAuth}/authentication/sites/list`;
const nextCrypto = new NextCrypto(tokenSecret);

View File

@ -1,32 +0,0 @@
import React from "react";
import retrievePage from "@/components/NavigatePages";
function MainPage({
pageSelected,
lang,
}: {
pageSelected: string | undefined;
lang: string;
}) {
const ComponentPage = retrievePage({
pageId: pageSelected ?? "",
});
if (!ComponentPage) {
return (
<div className="flex flex-col w-full">
<h2 className="text-2xl font-semibold p-4">No Page Selected</h2>
</div>
);
}
return (
<>
{/* Main Content */}
<main className="flex-grow p-6 bg-gray-50 overflow-y-auto">
<ComponentPage lang={lang} />
</main>
</>
);
}
export default MainPage;

View File

@ -6,29 +6,14 @@ export const metadata: Metadata = {
description: "WAG Frontend Application",
};
export default function RootLayout({
export default function AuthLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<div className="min-h-screen flex">
<div className="w-1/3 bg-purple-600 p-8 text-white">
<h1 className="text-4xl font-bold mb-4">Welcome to evyos</h1>
<p className="text-lg">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
</p>
</div>
<div className="w-2/3">
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense>
</div>
</div>
</body>
</html>
<div className="min-h-screen flex">
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense>
</div>
);
}

View File

@ -11,26 +11,27 @@ import LeftMenu from "@/components/menu/leftMenu";
export default async function DashboardLayout({
searchParams,
}: {
searchParams: { [key: string]: string | undefined };
searchParams: Promise<{ [key: string]: string | undefined }>;
}) {
const token_is_valid = await checkAccessTokenIsValid();
const siteUrlsList = await retrievePageList();
const siteUrlsList = (await retrievePageList()) || [];
if (!token_is_valid) {
redirect("/auth/login");
}
const lang = "tr";
const searchParamsInstance = await searchParams;
const pageToDirect = await retrievePagebyUrl("/dashboard");
const PageComponent = retrievePage(pageToDirect);
return (
<>
<div className="flex h-screen overflow-hidden">
<div className="min-h-screen min-w-screen flex h-screen w-screen overflow-hidden">
{/* Sidebar */}
<aside className="w-1/4 border-r p-4 overflow-y-auto">
<LeftMenu
pageUuidList={siteUrlsList}
lang={lang}
searchParams={searchParams}
searchParams={searchParamsInstance}
/>
</aside>
@ -48,7 +49,7 @@ export default async function DashboardLayout({
<div className="w-10 h-10 bg-gray-300 rounded-full"></div>
</div>
</header>
<PageComponent lang={lang} queryParams={searchParams} />
<PageComponent lang={lang} queryParams={searchParamsInstance} />
</div>
</div>
</>

View File

@ -0,0 +1,19 @@
import type { Metadata } from "next";
import { Suspense } from "react";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function DashLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="min-h-screen min-w-screen flex h-screen w-screen overflow-hidden">
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense>
</div>
);
}

View File

@ -13,7 +13,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body>{children}</body>
<body className="text-black">{children}</body>
</html>
);
}

View File

@ -4,15 +4,12 @@ import { PageProps } from "./interFaces";
function App000001({ lang, queryParams }: PageProps) {
return (
<>
<div className="flex flex-col w-3/4">
<div className="flex">
{/* Sticky Header */}
<header className="sticky top-0 bg-white shadow-md z-10 p-4 flex justify-between items-center">
<h1 className="text-2xl font-semibold">Dashboard</h1>
<div className="flex items-center space-x-4">
{JSON.stringify({
lang,
queryParams,
})}
{JSON.stringify({ lang, queryParams })}
<input
type="text"
placeholder="Search..."

View File

@ -8,7 +8,7 @@ export const PageIndexs = {
app000001: App000001,
};
function UnAuthorizedPage({ lang }: PageProps) {
function UnAuthorizedPage({ lang, queryParams }: PageProps) {
return (
<>
<div className="flex flex-col h-screen">

View File

@ -13,7 +13,7 @@ async function LeftMenu({
lang: keyof LanguageTranslation;
searchParams: { [key: string]: string | string[] | undefined };
}) {
const transformedMenu = transformMenu(pageUuidList);
const transformedMenu = transformMenu(pageUuidList) || [];
// Get the menuContext from searchParams without setting a default value
const menuContext = searchParams?.menu;
@ -34,68 +34,69 @@ async function LeftMenu({
<div>
<nav className="flex flex-col space-y-2">
<div className="text-xl font-bold mb-6 text-center">Dashboard</div>
{transformedMenu.map((item, firstIndex) => (
<div key={item.name} className="mb-4">
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*0`}
className={`text-xl font-semibold pl-5 my-2 py-2 block ${
firstIndex === firstLayerIndex
? "text-emerald-600"
: "text-emerald-400"
} hover:text-emerald-600`}
>
{item.lg[lang]}
</Link>
{transformedMenu &&
transformedMenu.map((item, firstIndex) => (
<div key={item.name} className="mb-4">
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*0`}
className={`text-xl font-semibold pl-5 my-2 py-2 block ${
firstIndex === firstLayerIndex
? "text-emerald-600"
: "text-emerald-400"
} hover:text-emerald-600`}
>
{item.lg[lang]}
</Link>
{/* Only render the second layer if menuContext exists and this first layer item is selected */}
{menuContext && firstIndex === firstLayerIndex && (
<ul className="space-y-2">
{item.subList.map((subItem, secondIndex) => (
<div key={subItem.name}>
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*${secondIndex}`}
className={`ml-5 my-4 pl-4 text-xl font-semibold block ${
secondIndex === secondLayerIndex
? "text-emerald-700"
: "text-emerald-500"
} hover:text-emerald-700`}
>
{subItem.lg[lang]}
</Link>
{/* Only render the third layer if this second layer item is selected */}
{firstIndex === firstLayerIndex &&
secondIndex === secondLayerIndex && (
<div className="ml-5">
{subItem.subList.map((subSubItem) => (
<Link
key={subSubItem.name}
href={`/dashboard?page=${subSubItem.name}&menu=${firstIndex}*${secondIndex}`}
className={`flex flex-row text-xl py-4 my-4 w-full space-x-2 p-2 rounded ${
pageSelected === subSubItem.name
? " bg-gray-100 cursor-not-allowed"
: "hover:bg-gray-200"
}`}
>
<span className="text-gray-400">
<Home />
</span>
<span className="ml-5 text-gray-700">
{subSubItem.lg[lang]}
</span>
</Link>
))}
</div>
)}
</div>
))}
</ul>
)}
</div>
))}
{/* Only render the second layer if menuContext exists and this first layer item is selected */}
{menuContext && firstIndex === firstLayerIndex && (
<ul className="space-y-2">
{item.subList.map((subItem, secondIndex) => (
<div key={subItem.name}>
<Link
href={`/dashboard?${
pageSelected ? `page=${pageSelected}` : ""
}&menu=${firstIndex}*${secondIndex}`}
className={`ml-5 my-4 pl-4 text-xl font-semibold block ${
secondIndex === secondLayerIndex
? "text-emerald-700"
: "text-emerald-500"
} hover:text-emerald-700`}
>
{subItem.lg[lang]}
</Link>
{/* Only render the third layer if this second layer item is selected */}
{firstIndex === firstLayerIndex &&
secondIndex === secondLayerIndex && (
<div className="ml-5">
{subItem.subList.map((subSubItem) => (
<Link
key={subSubItem.name}
href={`/dashboard?page=${subSubItem.name}&menu=${firstIndex}*${secondIndex}`}
className={`flex flex-row text-xl py-4 my-4 w-full space-x-2 p-2 rounded ${
pageSelected === subSubItem.name
? " bg-gray-100 cursor-not-allowed"
: "hover:bg-gray-200"
}`}
>
<span className="text-gray-400">
<Home />
</span>
<span className="ml-5 text-gray-700">
{subSubItem.lg[lang]}
</span>
</Link>
))}
</div>
)}
</div>
))}
</ul>
)}
</div>
))}
</nav>
</div>
);