updated app reachable codes
This commit is contained in:
parent
7eadadbd1d
commit
7c2150a8b0
|
|
@ -342,7 +342,6 @@ def authentication_token_refresh_post(
|
||||||
status_code=status.HTTP_406_NOT_ACCEPTABLE,
|
status_code=status.HTTP_406_NOT_ACCEPTABLE,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
)
|
)
|
||||||
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={},
|
content={},
|
||||||
status_code=status.HTTP_202_ACCEPTED,
|
status_code=status.HTTP_202_ACCEPTED,
|
||||||
|
|
@ -374,7 +373,6 @@ def authentication_password_verify_otp(
|
||||||
"tz": tz or "GMT+3",
|
"tz": tz or "GMT+3",
|
||||||
"token": token,
|
"token": token,
|
||||||
}
|
}
|
||||||
print("Token&OTP : ", data.otp, data.token)
|
|
||||||
if not domain or not language:
|
if not domain or not language:
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={"error": "EYS_0003"},
|
content={"error": "EYS_0003"},
|
||||||
|
|
@ -419,8 +417,17 @@ def authentication_page_valid(
|
||||||
status_code=status.HTTP_406_NOT_ACCEPTABLE,
|
status_code=status.HTTP_406_NOT_ACCEPTABLE,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
)
|
)
|
||||||
|
result = AuthHandlers.PageHandlers.retrieve_valid_page_via_token(
|
||||||
|
page_url=data.page_url, access_token=token
|
||||||
|
)
|
||||||
|
if not result:
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={},
|
content={"error": "EYS_0004"},
|
||||||
|
status_code=status.HTTP_406_NOT_ACCEPTABLE,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
return JSONResponse(
|
||||||
|
content={"application": result},
|
||||||
status_code=status.HTTP_202_ACCEPTED,
|
status_code=status.HTTP_202_ACCEPTED,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,16 @@ from Schemas import (
|
||||||
)
|
)
|
||||||
from Modules.Token.password_module import PasswordModule
|
from Modules.Token.password_module import PasswordModule
|
||||||
from Schemas.building.build import RelationshipEmployee2Build
|
from Schemas.building.build import RelationshipEmployee2Build
|
||||||
from Schemas.event.event import Event2Occupant
|
from Schemas.event.event import Event2Occupant, Application2Employee
|
||||||
from Controllers.Redis.database import RedisActions
|
from Controllers.Redis.database import RedisActions
|
||||||
from Controllers.Mongo.database import mongo_handler
|
from Controllers.Mongo.database import mongo_handler
|
||||||
|
|
||||||
|
|
||||||
TokenDictType = Union[EmployeeTokenObject, OccupantTokenObject]
|
TokenDictType = Union[EmployeeTokenObject, OccupantTokenObject]
|
||||||
|
|
||||||
|
|
||||||
class RedisHandlers:
|
class RedisHandlers:
|
||||||
|
|
||||||
AUTH_TOKEN: str = "AUTH_TOKEN"
|
AUTH_TOKEN: str = "AUTH_TOKEN"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -79,9 +81,7 @@ class RedisHandlers:
|
||||||
return generated_access_token
|
return generated_access_token
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_token_at_redis(
|
def update_token_at_redis(cls, token: str, add_payload: Union[CompanyToken, OccupantToken]):
|
||||||
cls, token: str, add_payload: Union[CompanyToken, OccupantToken]
|
|
||||||
):
|
|
||||||
if already_token_data := RedisActions.get_json(
|
if already_token_data := RedisActions.get_json(
|
||||||
list_keys=[RedisHandlers.AUTH_TOKEN, token, "*"]
|
list_keys=[RedisHandlers.AUTH_TOKEN, token, "*"]
|
||||||
).first:
|
).first:
|
||||||
|
|
@ -124,9 +124,7 @@ class UserHandlers:
|
||||||
return found_user
|
return found_user
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_password_valid(
|
def check_password_valid(domain: str, id_: str, password: str, password_hashed: str) -> bool:
|
||||||
domain: str, id_: str, password: str, password_hashed: str
|
|
||||||
) -> bool:
|
|
||||||
"""
|
"""
|
||||||
Check if the password is valid.
|
Check if the password is valid.
|
||||||
"""
|
"""
|
||||||
|
|
@ -144,6 +142,10 @@ class UserHandlers:
|
||||||
return True
|
return True
|
||||||
raise ValueError("EYS_0004")
|
raise ValueError("EYS_0004")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_password():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class LoginHandler:
|
class LoginHandler:
|
||||||
|
|
||||||
|
|
@ -156,9 +158,7 @@ class LoginHandler:
|
||||||
return str(email).split("@")[1] == api_config.ACCESS_EMAIL_EXT
|
return str(email).split("@")[1] == api_config.ACCESS_EMAIL_EXT
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def do_employee_login(
|
def do_employee_login(cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None):
|
||||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Handle employee login.
|
Handle employee login.
|
||||||
"""
|
"""
|
||||||
|
|
@ -268,9 +268,7 @@ class LoginHandler:
|
||||||
raise ValueError("Something went wrong")
|
raise ValueError("Something went wrong")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def do_employee_occupant(
|
def do_employee_occupant(cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None):
|
||||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Handle occupant login.
|
Handle occupant login.
|
||||||
"""
|
"""
|
||||||
|
|
@ -421,9 +419,7 @@ class LoginHandler:
|
||||||
return request.headers.get(api_config.ACCESS_TOKEN_TAG)
|
return request.headers.get(api_config.ACCESS_TOKEN_TAG)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handle_employee_selection(
|
def handle_employee_selection(cls, access_token: str, data: Any, token_dict: TokenDictType):
|
||||||
cls, access_token: str, data: Any, token_dict: TokenDictType
|
|
||||||
):
|
|
||||||
with Users.new_session() as db:
|
with Users.new_session() as db:
|
||||||
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
||||||
ValueError("EYS_0011")
|
ValueError("EYS_0011")
|
||||||
|
|
@ -479,6 +475,10 @@ class LoginHandler:
|
||||||
db=db,
|
db=db,
|
||||||
).data
|
).data
|
||||||
|
|
||||||
|
reachable_app_codes = Application2Employee.get_application_codes(
|
||||||
|
employee_id=employee.id, db=db
|
||||||
|
)
|
||||||
|
|
||||||
# Create company token
|
# Create company token
|
||||||
company_token = CompanyToken(
|
company_token = CompanyToken(
|
||||||
company_uu_id=selected_company.uu_id.__str__(),
|
company_uu_id=selected_company.uu_id.__str__(),
|
||||||
|
|
@ -493,6 +493,7 @@ class LoginHandler:
|
||||||
employee_id=employee.id,
|
employee_id=employee.id,
|
||||||
employee_uu_id=employee.uu_id.__str__(),
|
employee_uu_id=employee.uu_id.__str__(),
|
||||||
reachable_event_codes=reachable_event_codes,
|
reachable_event_codes=reachable_event_codes,
|
||||||
|
reachable_app_codes=reachable_app_codes
|
||||||
)
|
)
|
||||||
redis_handler = RedisHandlers()
|
redis_handler = RedisHandlers()
|
||||||
redis_result = redis_handler.update_token_at_redis(
|
redis_result = redis_handler.update_token_at_redis(
|
||||||
|
|
@ -503,9 +504,7 @@ class LoginHandler:
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handle_occupant_selection(
|
def handle_occupant_selection(cls, access_token: str, data: Any, token_dict: TokenDictType):
|
||||||
cls, access_token: str, data: Any, token_dict: TokenDictType
|
|
||||||
):
|
|
||||||
"""Handle occupant type selection"""
|
"""Handle occupant type selection"""
|
||||||
with BuildLivingSpace.new_session() as db:
|
with BuildLivingSpace.new_session() as db:
|
||||||
# Get selected occupant type
|
# Get selected occupant type
|
||||||
|
|
@ -707,6 +706,22 @@ class PasswordHandler:
|
||||||
return found_user
|
return found_user
|
||||||
|
|
||||||
|
|
||||||
|
class PageHandlers:
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def retrieve_valid_page_via_token(cls, access_token: str, page_url: str):
|
||||||
|
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):
|
||||||
|
return application
|
||||||
|
elif result.is_occupant:
|
||||||
|
if application := result.selected_company.reachable_app_codes.get(page_url, None):
|
||||||
|
return application
|
||||||
|
raise ValueError("EYS_0013")
|
||||||
|
|
||||||
|
|
||||||
class AuthHandlers:
|
class AuthHandlers:
|
||||||
|
|
||||||
LoginHandler: LoginHandler = LoginHandler()
|
LoginHandler: LoginHandler = LoginHandler()
|
||||||
PasswordHandler: PasswordHandler = PasswordHandler()
|
PasswordHandler: PasswordHandler = PasswordHandler()
|
||||||
|
PageHandlers: PageHandlers = PageHandlers()
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ class OccupantToken(BaseModel):
|
||||||
responsible_employee_id: Optional[int] = None
|
responsible_employee_id: Optional[int] = None
|
||||||
responsible_employee_uuid: Optional[str] = None
|
responsible_employee_uuid: Optional[str] = None
|
||||||
|
|
||||||
reachable_event_codes: Optional[list[str]] = None # ID list of reachable modules
|
reachable_event_codes: Optional[dict[str, str]] = None # ID list of reachable modules
|
||||||
reachable_app_codes: Optional[list[str]] = None # ID list of reachable modules
|
reachable_app_codes: Optional[dict[str, str]] = None # ID list of reachable modules
|
||||||
|
|
||||||
|
|
||||||
class CompanyToken(BaseModel):
|
class CompanyToken(BaseModel):
|
||||||
|
|
@ -83,8 +83,8 @@ class CompanyToken(BaseModel):
|
||||||
|
|
||||||
bulk_duties_id: int
|
bulk_duties_id: int
|
||||||
|
|
||||||
reachable_event_codes: Optional[list[str]] = None # ID list of reachable modules
|
reachable_event_codes: Optional[dict[str, str]] = None # ID list of reachable modules
|
||||||
reachable_app_codes: Optional[list[str]] = None # ID list of reachable modules
|
reachable_app_codes: Optional[dict[str, str]] = None # ID list of reachable modules
|
||||||
|
|
||||||
|
|
||||||
class OccupantTokenObject(ApplicationToken):
|
class OccupantTokenObject(ApplicationToken):
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class RequestVerifyOTP(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class RequestApplication(BaseModel):
|
class RequestApplication(BaseModel):
|
||||||
page: str # /building/create
|
page_url: str # /building/create
|
||||||
|
|
||||||
|
|
||||||
class RequestSelectEmployee(BaseModel):
|
class RequestSelectEmployee(BaseModel):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
from Schemas import (
|
||||||
|
Applications,
|
||||||
|
Application2Employee,
|
||||||
|
Application2Occupant,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
name=Building Create
|
||||||
|
site_url=/buildings/create
|
||||||
|
application_type=CreateFrom
|
||||||
|
application_code=APP003
|
||||||
|
|
||||||
|
name=Building Create
|
||||||
|
site_url=/buildings/create
|
||||||
|
application_type=CreateFrom
|
||||||
|
application_code=APP004
|
||||||
|
|
||||||
|
name=Building Create
|
||||||
|
site_url=/buildings/create
|
||||||
|
application_type=CreateFrom
|
||||||
|
application_code=APP005
|
||||||
|
|
||||||
|
name=Building Update
|
||||||
|
site_url=/buildings/update
|
||||||
|
application_type=/building/update
|
||||||
|
application_code=APP002
|
||||||
|
|
||||||
|
name=Building List
|
||||||
|
site_url=/buildings
|
||||||
|
application_type=ListFrom
|
||||||
|
application_code=APP001
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
# Install system dependencies and Poetry
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends gcc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir poetry
|
||||||
|
|
||||||
|
# Copy Poetry configuration
|
||||||
|
COPY /pyproject.toml ./pyproject.toml
|
||||||
|
|
||||||
|
# Configure Poetry and install dependencies with optimizations
|
||||||
|
RUN poetry config virtualenvs.create false \
|
||||||
|
&& poetry install --no-interaction --no-ansi --no-root --only main \
|
||||||
|
&& pip cache purge && rm -rf ~/.cache/pypoetry
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
COPY /ApiServices/DealerService /ApiServices/DealerService
|
||||||
|
COPY /ApiServices/DealerService /
|
||||||
|
COPY /Controllers /Controllers
|
||||||
|
COPY /Modules /Modules
|
||||||
|
COPY /Schemas /Schemas
|
||||||
|
|
||||||
|
# Set Python path to include app directory
|
||||||
|
ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
|
||||||
|
|
||||||
|
# Run the application using the configured uvicorn server
|
||||||
|
CMD ["poetry", "run", "python", "ApiServices/DealerService/app.py"]
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
from Controllers.Postgres.database import get_db
|
||||||
|
from Schemas import (
|
||||||
|
Users,
|
||||||
|
Employees,
|
||||||
|
)
|
||||||
|
from init_service_to_events import init_service_to_event_matches_for_super_user
|
||||||
|
from init_applications import init_applications_for_super_user
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
"""
|
||||||
|
Create Applications to serve on Next.js | Create Events to add to Service
|
||||||
|
Set Events to service | Set Service to employee
|
||||||
|
"""
|
||||||
|
with get_db() as db_session:
|
||||||
|
if super_man := Users.filter_one(
|
||||||
|
Users.email == "karatay.berkay.sup@evyos.com.tr", db=db_session
|
||||||
|
).data:
|
||||||
|
super_employee = Employees.filter_one(
|
||||||
|
Employees.people_id == super_man.person_id, db=db_session
|
||||||
|
).data
|
||||||
|
|
||||||
|
init_service_to_event_matches_for_super_user(super_user=super_employee, db_session=db_session)
|
||||||
|
init_applications_for_super_user(super_user=super_employee, db_session=db_session)
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
from Schemas import (
|
||||||
|
Applications,
|
||||||
|
Application2Employee,
|
||||||
|
Employees
|
||||||
|
)
|
||||||
|
|
||||||
|
def init_applications_for_super_user(super_user: Employees, db_session=None) -> None:
|
||||||
|
list_of_created_apps = [
|
||||||
|
dict(
|
||||||
|
name="Dashboard1",
|
||||||
|
application_code = "app000001",
|
||||||
|
site_url = "/dashboard",
|
||||||
|
application_type = "info",
|
||||||
|
description = "Dashboard Page"
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
name="Dashboard2",
|
||||||
|
application_code = "app000002",
|
||||||
|
site_url = "/buildings/list",
|
||||||
|
application_type = "CreateFrom",
|
||||||
|
description = "Dashboard Page"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
for list_of_created_app in list_of_created_apps:
|
||||||
|
dashboard_page = Applications.find_or_create(
|
||||||
|
**list_of_created_app, db=db_session,
|
||||||
|
)
|
||||||
|
print('dashboard_page', dashboard_page)
|
||||||
|
if dashboard_page.meta_data.created:
|
||||||
|
dashboard_page.save(db=db_session)
|
||||||
|
Application2Employee.find_or_create(
|
||||||
|
employee_id=super_user.id,
|
||||||
|
employee_uu_id=str(super_user.uu_id),
|
||||||
|
site_url=dashboard_page.site_url,
|
||||||
|
application_code=dashboard_page.application_code,
|
||||||
|
application_id=dashboard_page.id,
|
||||||
|
application_uu_id=str(dashboard_page.uu_id),
|
||||||
|
db=db_session,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
from Schemas import (
|
||||||
|
Users,
|
||||||
|
Services,
|
||||||
|
Service2Events,
|
||||||
|
Applications,
|
||||||
|
Application2Employee,
|
||||||
|
Application2Occupant,
|
||||||
|
Employees,
|
||||||
|
Event2Employee,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
list_of_event_codes = []
|
||||||
|
|
||||||
|
|
||||||
|
def init_service_to_event_matches_for_super_user(super_user, db_session=None) -> None:
|
||||||
|
service_match = Services.filter_one(
|
||||||
|
Services.service_name == "Super User", db=db_session,
|
||||||
|
).data
|
||||||
|
for list_of_event_code in list_of_event_codes:
|
||||||
|
created_service = Service2Events.find_or_create(
|
||||||
|
service_id=service_match.id,
|
||||||
|
service_uu_id=str(service_match.uu_id),
|
||||||
|
event_id=list_of_event_code.id,
|
||||||
|
event_uu_id=str(list_of_event_code.uu_id),
|
||||||
|
is_confirmed=True,
|
||||||
|
active=True,
|
||||||
|
db=db_session,
|
||||||
|
)
|
||||||
|
if created_service.meta_data.created:
|
||||||
|
created_service.save(db=db_session)
|
||||||
|
print(
|
||||||
|
f"UUID: {created_service.uu_id} event is saved to {service_match.uu_id}"
|
||||||
|
)
|
||||||
|
employee_added_service = Event2Employee.find_or_create(
|
||||||
|
event_service_id=created_service.id,
|
||||||
|
event_service_uu_id=str(created_service.uu_id),
|
||||||
|
employee_id=super_user.id,
|
||||||
|
employee_uu_id=str(super_user.uu_id),
|
||||||
|
is_confirmed=True,
|
||||||
|
db=db_session
|
||||||
|
)
|
||||||
|
if employee_added_service.meta_data.created:
|
||||||
|
employee_added_service.save(db=db_session)
|
||||||
|
print(
|
||||||
|
f"UUID: {employee_added_service.uu_id} event is saved to {super_user.uu_id}"
|
||||||
|
)
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from fastapi import APIRouter, Request, Response, Header
|
from fastapi import APIRouter, Request, Response, Header
|
||||||
|
|
||||||
from ApiServices.TemplateService.config import api_config
|
from ApiServices.TemplateService.config import api_config
|
||||||
from ApiServices.TemplateService.events.template.event import template_event_cluster
|
from ApiServices.TemplateService.events.template.event import template_event_cluster
|
||||||
|
|
||||||
|
|
||||||
test_template_route = APIRouter(prefix="/test", tags=["Test"])
|
test_template_route = APIRouter(prefix="/test", tags=["Test"])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,9 @@ from Schemas.event.event import (
|
||||||
Event2Employee,
|
Event2Employee,
|
||||||
Event2OccupantExtra,
|
Event2OccupantExtra,
|
||||||
Event2EmployeeExtra,
|
Event2EmployeeExtra,
|
||||||
|
Applications,
|
||||||
|
Application2Employee,
|
||||||
|
Application2Occupant,
|
||||||
)
|
)
|
||||||
from Schemas.identity.identity import (
|
from Schemas.identity.identity import (
|
||||||
UsersTokens,
|
UsersTokens,
|
||||||
|
|
@ -175,6 +178,9 @@ __all__ = [
|
||||||
"Event2Employee",
|
"Event2Employee",
|
||||||
"Event2OccupantExtra",
|
"Event2OccupantExtra",
|
||||||
"Event2EmployeeExtra",
|
"Event2EmployeeExtra",
|
||||||
|
"Applications",
|
||||||
|
"Application2Employee",
|
||||||
|
"Application2Occupant",
|
||||||
"Addresses",
|
"Addresses",
|
||||||
"AddressCity",
|
"AddressCity",
|
||||||
"AddressStreet",
|
"AddressStreet",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,25 @@ from sqlalchemy.orm import mapped_column, Mapped
|
||||||
from Controllers.Postgres.mixin import CrudCollection
|
from Controllers.Postgres.mixin import CrudCollection
|
||||||
|
|
||||||
|
|
||||||
|
class Applications(CrudCollection):
|
||||||
|
"""
|
||||||
|
Applications class based on declarative_base and BaseMixin via session
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "applications"
|
||||||
|
__exclude__fields__ = []
|
||||||
|
|
||||||
|
name: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application Name"
|
||||||
|
)
|
||||||
|
site_url: Mapped[str] = mapped_column(String, nullable=False, comment="Site URL")
|
||||||
|
application_code: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application Code"
|
||||||
|
)
|
||||||
|
application_type: Mapped[str] = mapped_column(String, comment="Application Type")
|
||||||
|
description: Mapped[str] = mapped_column(String, comment="Application Description")
|
||||||
|
|
||||||
|
|
||||||
class Events(CrudCollection):
|
class Events(CrudCollection):
|
||||||
"""
|
"""
|
||||||
Events class based on declarative_base and BaseMixin via session
|
Events class based on declarative_base and BaseMixin via session
|
||||||
|
|
@ -82,6 +101,42 @@ class Modules(CrudCollection):
|
||||||
__table_args__ = ({"comment": "Modules Information"},)
|
__table_args__ = ({"comment": "Modules Information"},)
|
||||||
|
|
||||||
|
|
||||||
|
class ModulePrice(CrudCollection):
|
||||||
|
"""
|
||||||
|
ModulePrice class based on declarative_base and BaseMixin via session
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "module_price"
|
||||||
|
__exclude__fields__ = []
|
||||||
|
|
||||||
|
campaign_code: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Campaign Code"
|
||||||
|
)
|
||||||
|
module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
|
||||||
|
module_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Module UUID"
|
||||||
|
)
|
||||||
|
service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
|
||||||
|
service_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Service UUID"
|
||||||
|
)
|
||||||
|
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
|
||||||
|
event_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Event UUID"
|
||||||
|
)
|
||||||
|
is_counted_percentage: Mapped[float] = mapped_column(
|
||||||
|
Numeric(6, 2), server_default="0.00"
|
||||||
|
) # %22
|
||||||
|
discounted_price: Mapped[float] = mapped_column(
|
||||||
|
Numeric(20, 2), server_default="0.00"
|
||||||
|
) # Normal: 78.00 TL
|
||||||
|
calculated_price: Mapped[float] = mapped_column(
|
||||||
|
Numeric(20, 2), server_default="0.00"
|
||||||
|
) # sana düz 75.00 TL yapar
|
||||||
|
|
||||||
|
__table_args__ = ({"comment": "ModulePrice Information"},)
|
||||||
|
|
||||||
|
|
||||||
class Services(CrudCollection):
|
class Services(CrudCollection):
|
||||||
"""
|
"""
|
||||||
Services class based on declarative_base and BaseMixin via session
|
Services class based on declarative_base and BaseMixin via session
|
||||||
|
|
@ -143,6 +198,10 @@ class Service2Events(CrudCollection):
|
||||||
__table_args__ = ({"comment": "Service2Events Information"},)
|
__table_args__ = ({"comment": "Service2Events Information"},)
|
||||||
|
|
||||||
|
|
||||||
|
# class Service2Application(CrudCollection):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
class Event2OccupantExtra(CrudCollection):
|
class Event2OccupantExtra(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "event2occupant_extra"
|
__tablename__ = "event2occupant_extra"
|
||||||
|
|
@ -229,7 +288,7 @@ class Event2Employee(CrudCollection):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_event_codes(cls, employee_id: int, db) -> list:
|
def get_event_codes(cls, employee_id: int, db) -> dict[str : list[str]]:
|
||||||
employee_events = cls.filter_all(
|
employee_events = cls.filter_all(
|
||||||
cls.employee_id == employee_id,
|
cls.employee_id == employee_id,
|
||||||
db=db,
|
db=db,
|
||||||
|
|
@ -253,43 +312,13 @@ class Event2Employee(CrudCollection):
|
||||||
db=db,
|
db=db,
|
||||||
).data
|
).data
|
||||||
active_events.extend(events_extra)
|
active_events.extend(events_extra)
|
||||||
return [event.function_code for event in active_events]
|
events_dict = {}
|
||||||
|
for event in active_events:
|
||||||
# @classmethod
|
if event.endpoint_code in events_dict:
|
||||||
# def get_event_endpoints(cls, employee_id: int) -> list:
|
events_dict[event.endpoint_code].append(event.function_code)
|
||||||
# from Schemas import EndpointRestriction
|
else:
|
||||||
#
|
events_dict[event.endpoint_code] = [event.function_code]
|
||||||
# db = cls.new_session()
|
return events_dict
|
||||||
# employee_events = cls.filter_all(
|
|
||||||
# cls.employee_id == employee_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# active_event_ids = Service2Events.filter_all(
|
|
||||||
# Service2Events.service_id.in_(
|
|
||||||
# [event.event_service_id for event in employee_events]
|
|
||||||
# ),
|
|
||||||
# db=db,
|
|
||||||
# system=True,
|
|
||||||
# ).data
|
|
||||||
# active_events = Events.filter_all(
|
|
||||||
# Events.id.in_([event.event_id for event in active_event_ids]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# if extra_events := Event2EmployeeExtra.filter_all(
|
|
||||||
# Event2EmployeeExtra.employee_id == employee_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data:
|
|
||||||
# events_extra = Events.filter_all(
|
|
||||||
# Events.id.in_([event.event_id for event in extra_events]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# active_events.extend(events_extra)
|
|
||||||
# endpoint_restrictions = EndpointRestriction.filter_all(
|
|
||||||
# EndpointRestriction.id.in_([event.endpoint_id for event in active_events]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# return [event.endpoint_name for event in endpoint_restrictions]
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
class Event2Occupant(CrudCollection):
|
class Event2Occupant(CrudCollection):
|
||||||
|
|
@ -326,7 +355,7 @@ class Event2Occupant(CrudCollection):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_event_codes(cls, build_living_space_id, db) -> list:
|
def get_event_codes(cls, build_living_space_id: int, db) -> dict[str : list[str]]:
|
||||||
occupant_events = cls.filter_all(
|
occupant_events = cls.filter_all(
|
||||||
cls.build_living_space_id == build_living_space_id,
|
cls.build_living_space_id == build_living_space_id,
|
||||||
db=db,
|
db=db,
|
||||||
|
|
@ -350,75 +379,106 @@ class Event2Occupant(CrudCollection):
|
||||||
db=db,
|
db=db,
|
||||||
).data
|
).data
|
||||||
active_events.extend(events_extra)
|
active_events.extend(events_extra)
|
||||||
return [event.function_code for event in active_events]
|
events_dict = {}
|
||||||
|
for event in active_events:
|
||||||
# @classmethod
|
if event.endpoint_code in events_dict:
|
||||||
# def get_event_endpoints(cls, build_living_space_id) -> list:
|
events_dict[event.endpoint_code].append(event.function_code)
|
||||||
# from Schemas import EndpointRestriction
|
else:
|
||||||
#
|
events_dict[event.endpoint_code] = [event.function_code]
|
||||||
# db = cls.new_session()
|
return events_dict
|
||||||
# occupant_events = cls.filter_all(
|
|
||||||
# cls.build_living_space_id == build_living_space_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# active_event_ids = Service2Events.filter_all(
|
|
||||||
# Service2Events.service_id.in_(
|
|
||||||
# [event.event_service_id for event in occupant_events]
|
|
||||||
# ),
|
|
||||||
# db=db,
|
|
||||||
# system=True,
|
|
||||||
# ).data
|
|
||||||
# active_events = Events.filter_all(
|
|
||||||
# Events.id.in_([event.event_id for event in active_event_ids]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# if extra_events := Event2OccupantExtra.filter_all(
|
|
||||||
# Event2OccupantExtra.build_living_space_id == build_living_space_id,
|
|
||||||
# db=db,
|
|
||||||
# ).data:
|
|
||||||
# events_extra = Events.filter_all(
|
|
||||||
# Events.id.in_([event.event_id for event in extra_events]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# active_events.extend(events_extra)
|
|
||||||
# endpoint_restrictions = EndpointRestriction.filter_all(
|
|
||||||
# EndpointRestriction.id.in_([event.endpoint_id for event in active_events]),
|
|
||||||
# db=db,
|
|
||||||
# ).data
|
|
||||||
# return [event.endpoint_name for event in endpoint_restrictions]
|
|
||||||
|
|
||||||
|
|
||||||
class ModulePrice(CrudCollection):
|
class Application2Employee(CrudCollection):
|
||||||
"""
|
"""
|
||||||
ModulePrice class based on declarative_base and BaseMixin via session
|
Application2Employee class based on declarative_base and BaseMixin via session
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__tablename__ = "module_price"
|
__tablename__ = "application2employee"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
|
||||||
campaign_code: Mapped[str] = mapped_column(
|
employee_id: Mapped[int] = mapped_column(ForeignKey("employees.id"), nullable=False)
|
||||||
String, nullable=False, comment="Campaign Code"
|
employee_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Employee UUID"
|
||||||
)
|
)
|
||||||
module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
|
|
||||||
module_uu_id: Mapped[str] = mapped_column(
|
|
||||||
String, nullable=False, comment="Module UUID"
|
|
||||||
)
|
|
||||||
service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
|
|
||||||
service_uu_id: Mapped[str] = mapped_column(
|
|
||||||
String, nullable=False, comment="Service UUID"
|
|
||||||
)
|
|
||||||
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
|
|
||||||
event_uu_id: Mapped[str] = mapped_column(
|
|
||||||
String, nullable=False, comment="Event UUID"
|
|
||||||
)
|
|
||||||
is_counted_percentage: Mapped[float] = mapped_column(
|
|
||||||
Numeric(6, 2), server_default="0.00"
|
|
||||||
) # %22
|
|
||||||
discounted_price: Mapped[float] = mapped_column(
|
|
||||||
Numeric(20, 2), server_default="0.00"
|
|
||||||
) # Normal: 78.00 TL
|
|
||||||
calculated_price: Mapped[float] = mapped_column(
|
|
||||||
Numeric(20, 2), server_default="0.00"
|
|
||||||
) # sana düz 75.00 TL yapar
|
|
||||||
|
|
||||||
__table_args__ = ({"comment": "ModulePrice Information"},)
|
application_id: Mapped[int] = mapped_column(ForeignKey("applications.id"))
|
||||||
|
application_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application UUID"
|
||||||
|
)
|
||||||
|
|
||||||
|
site_url: Mapped[str] = mapped_column(String, nullable=False, comment="Site URL")
|
||||||
|
application_code: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application Code"
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_application_codes(cls, employee_id: int, db) -> dict[str , str]:
|
||||||
|
print('employee_id', employee_id)
|
||||||
|
employee_applications = cls.filter_all(
|
||||||
|
Application2Employee.employee_id == employee_id, db=db,
|
||||||
|
).data
|
||||||
|
applications_dict = {}
|
||||||
|
print('employee_applications', employee_applications)
|
||||||
|
for employee_application in employee_applications:
|
||||||
|
if employee_application.site_url not in applications_dict:
|
||||||
|
applications_dict[str(employee_application.site_url)] = str(employee_application.application_code)
|
||||||
|
return applications_dict
|
||||||
|
|
||||||
|
__table_args__ = (
|
||||||
|
Index(
|
||||||
|
"application_to_employee",
|
||||||
|
employee_id,
|
||||||
|
site_url,
|
||||||
|
application_id,
|
||||||
|
unique=True,
|
||||||
|
),
|
||||||
|
{"comment": "Application2Employee Information"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Application2Occupant(CrudCollection):
|
||||||
|
"""
|
||||||
|
Application2Occupant class based on declarative_base and BaseMixin via session
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "application2occupant"
|
||||||
|
__exclude__fields__ = []
|
||||||
|
|
||||||
|
build_living_space_id: Mapped[int] = mapped_column(
|
||||||
|
ForeignKey("build_living_space.id"), nullable=False
|
||||||
|
)
|
||||||
|
build_living_space_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Build Living Space UUID"
|
||||||
|
)
|
||||||
|
|
||||||
|
application_id: Mapped[int] = mapped_column(ForeignKey("applications.id"))
|
||||||
|
application_uu_id: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application UUID"
|
||||||
|
)
|
||||||
|
|
||||||
|
site_url: Mapped[str] = mapped_column(String, nullable=False, comment="Site URL")
|
||||||
|
application_code: Mapped[str] = mapped_column(
|
||||||
|
String, nullable=False, comment="Application Code"
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_application_codes(cls, build_living_space_id: int, db) -> dict[str , str]:
|
||||||
|
occupant_applications = cls.filter_all(
|
||||||
|
cls.build_living_space_id == build_living_space_id, db=db,
|
||||||
|
).data
|
||||||
|
applications_dict = {}
|
||||||
|
for occupant_application in occupant_applications:
|
||||||
|
if occupant_application.site_url not in applications_dict:
|
||||||
|
applications_dict[str(occupant_application.site_url)] = str(occupant_application.application_code)
|
||||||
|
return applications_dict
|
||||||
|
|
||||||
|
__table_args__ = (
|
||||||
|
Index(
|
||||||
|
"application_to_occupant",
|
||||||
|
build_living_space_id,
|
||||||
|
site_url,
|
||||||
|
application_id,
|
||||||
|
unique=True,
|
||||||
|
),
|
||||||
|
{"comment": "Application2Occupant Information"},
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"flatpickr": "^4.6.13",
|
"flatpickr": "^4.6.13",
|
||||||
|
"lucide-react": "^0.487.0",
|
||||||
"next": "15.2.4",
|
"next": "15.2.4",
|
||||||
"next-crypto": "^1.0.8",
|
"next-crypto": "^1.0.8",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|
@ -1152,6 +1153,14 @@
|
||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "0.487.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.487.0.tgz",
|
||||||
|
"integrity": "sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"flatpickr": "^4.6.13",
|
"flatpickr": "^4.6.13",
|
||||||
|
"lucide-react": "^0.487.0",
|
||||||
"next": "15.2.4",
|
"next": "15.2.4",
|
||||||
"next-crypto": "^1.0.8",
|
"next-crypto": "^1.0.8",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
"use server";
|
||||||
|
import React from "react";
|
||||||
|
import { Home, User, Settings, Mail, Calendar } from "lucide-react";
|
||||||
|
import { transformMenu, LanguageTranslation } from "@/components/menu/runner";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
async function LeftMenu({
|
||||||
|
searchParams,
|
||||||
|
pageUuidList,
|
||||||
|
lang,
|
||||||
|
}: {
|
||||||
|
pageUuidList: string[];
|
||||||
|
lang: keyof LanguageTranslation;
|
||||||
|
searchParams: { [key: string]: string | string[] | undefined };
|
||||||
|
}) {
|
||||||
|
const transformedMenu = transformMenu(pageUuidList);
|
||||||
|
|
||||||
|
// Get the menuContext from searchParams without setting a default value
|
||||||
|
const menuContext = searchParams?.menu;
|
||||||
|
|
||||||
|
// Only parse the indices if menuContext exists
|
||||||
|
let firstLayerIndex = -1;
|
||||||
|
let secondLayerIndex = -1;
|
||||||
|
|
||||||
|
if (menuContext) {
|
||||||
|
const indices = menuContext.toString().split("*").map(Number);
|
||||||
|
firstLayerIndex = indices[0] || 0;
|
||||||
|
secondLayerIndex = indices[1] || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageSelected = searchParams?.page;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{/* 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.appUUID}
|
||||||
|
href={`/dashboard?page=${subSubItem.appUUID}&menu=${firstIndex}*${secondIndex}`}
|
||||||
|
className={`flex flex-row text-xl py-4 my-4 w-full space-x-2 p-2 rounded ${
|
||||||
|
pageSelected === subSubItem.appUUID
|
||||||
|
? " 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LeftMenu;
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
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;
|
||||||
|
|
@ -2,13 +2,56 @@ import React from "react";
|
||||||
import { checkAccessTokenIsValid } from "@/apicalls/cookies/token";
|
import { checkAccessTokenIsValid } from "@/apicalls/cookies/token";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
async function DashboardPage() {
|
import LeftMenu from "./leftMenu";
|
||||||
const token_is_valid = await checkAccessTokenIsValid();
|
import MainPage from "./main";
|
||||||
|
|
||||||
|
export default async function DashboardLayout({
|
||||||
|
searchParams,
|
||||||
|
}: {
|
||||||
|
searchParams: { [key: string]: string | undefined };
|
||||||
|
}) {
|
||||||
|
const token_is_valid = await checkAccessTokenIsValid();
|
||||||
if (!token_is_valid) {
|
if (!token_is_valid) {
|
||||||
redirect("/auth/login");
|
redirect("/auth/login");
|
||||||
}
|
}
|
||||||
return <div>You have arrived to Dashboard Page</div>;
|
const pageUuidList = [
|
||||||
}
|
"6015129b-f665-479c-a440-04fb82ea6114",
|
||||||
|
"14a98ae7-c64e-403d-9b53-32e7ea867ab4",
|
||||||
|
"e368137d-d548-4ed4-90da-337bcc5d1559",
|
||||||
|
"d3d97973-41c6-4bad-881b-6bf77d837fa5",
|
||||||
|
]; // Mock data of pageUUID list []
|
||||||
|
const lang = "tr"; // Assuming you have a way to determine the current language
|
||||||
|
const queryParams = await searchParams;
|
||||||
|
const pageSelected = queryParams?.page || undefined;
|
||||||
|
|
||||||
export default DashboardPage;
|
return (
|
||||||
|
<div className="flex h-screen overflow-hidden">
|
||||||
|
{/* Sidebar */}
|
||||||
|
<aside className="w-1/4 border-r p-4 overflow-y-auto">
|
||||||
|
<LeftMenu
|
||||||
|
pageUuidList={pageUuidList}
|
||||||
|
lang={lang}
|
||||||
|
searchParams={queryParams}
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content Area */}
|
||||||
|
|
||||||
|
<div className="flex flex-col w-3/4">
|
||||||
|
{/* 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">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search..."
|
||||||
|
className="border px-3 py-2 rounded-lg"
|
||||||
|
/>
|
||||||
|
<div className="w-10 h-10 bg-gray-300 rounded-full"></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<MainPage pageSelected={pageSelected} lang={lang} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { PageProps } from "./interFaces";
|
||||||
|
import Page0001 from "./page0001";
|
||||||
|
|
||||||
|
const PageIndexs = {
|
||||||
|
"6015129b-f665-479c-a440-04fb82ea6114": Page0001,
|
||||||
|
};
|
||||||
|
|
||||||
|
function UnAuthorizedPage({ lang }: PageProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col h-screen">
|
||||||
|
<header className="bg-gray-800 text-white p-4 text-center">
|
||||||
|
<h1 className="text-2xl font-bold">Unauthorized Access</h1>
|
||||||
|
</header>
|
||||||
|
<main className="flex-grow p-4 bg-gray-100">
|
||||||
|
<p className="text-gray-700">
|
||||||
|
You do not have permission to access this page.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-700">Please contact the administrator.</p>
|
||||||
|
</main>
|
||||||
|
<footer className="bg-gray-800 text-white p-4 text-center">
|
||||||
|
<p>© 2023 My Application</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function retrievePage({
|
||||||
|
pageId,
|
||||||
|
}: {
|
||||||
|
pageId: string;
|
||||||
|
}): React.ComponentType<PageProps> {
|
||||||
|
const PageComponent = PageIndexs[pageId as keyof typeof PageIndexs];
|
||||||
|
if (!PageComponent) {
|
||||||
|
return UnAuthorizedPage;
|
||||||
|
}
|
||||||
|
return PageComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default retrievePage;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface PageProps {
|
||||||
|
lang: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import React from "react";
|
||||||
|
import { PageProps } from "./interFaces";
|
||||||
|
|
||||||
|
const pageContext = {
|
||||||
|
tr: {
|
||||||
|
pageTitle: "Sayfa 0001",
|
||||||
|
pageDescription: "Bu, Sayfa 0001'in içeriğidir.",
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
pageTitle: "Page 0001",
|
||||||
|
pageDescription: "This is the content of Page 0001.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function Page0001({ lang }: PageProps) {
|
||||||
|
const { pageTitle, pageDescription } =
|
||||||
|
pageContext[lang as keyof typeof pageContext];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col h-screen">
|
||||||
|
<header className="bg-gray-800 text-white p-4 text-center">
|
||||||
|
<h1 className="text-2xl font-bold">{pageTitle}</h1>
|
||||||
|
</header>
|
||||||
|
<main className="flex-grow p-4 bg-gray-100">
|
||||||
|
<p className="text-gray-700">{pageDescription}</p>
|
||||||
|
</main>
|
||||||
|
<footer className="bg-gray-800 text-white p-4 text-center">
|
||||||
|
<p>© 2023 My Application</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Page0001;
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* Filters the menu structure based on intersections with provided UUIDs
|
||||||
|
* @param {string[]} uuids - Array of UUIDs to check for intersection
|
||||||
|
* @param {Array} menu - The original menu structure
|
||||||
|
* @returns {Array} - Filtered menu structure with only matching items
|
||||||
|
*/
|
||||||
|
import Menu from "@/menu/store"; // Assuming you have a menu structure imported
|
||||||
|
|
||||||
|
// Define TypeScript interfaces for menu structure
|
||||||
|
interface LanguageTranslation {
|
||||||
|
tr: string;
|
||||||
|
en: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MenuThirdLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
appList: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MenuSecondLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
subList: MenuThirdLevel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MenuFirstLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
subList: MenuSecondLevel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define interfaces for the filtered menu structure
|
||||||
|
interface FilteredMenuThirdLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
appUUID: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FilteredMenuSecondLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
subList: FilteredMenuThirdLevel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FilteredMenuFirstLevel {
|
||||||
|
name: string;
|
||||||
|
lg: LanguageTranslation;
|
||||||
|
subList: FilteredMenuSecondLevel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { LanguageTranslation };
|
||||||
|
|
||||||
|
function transformMenu(uuids: string[]) {
|
||||||
|
// Helper function to check if arrays have at least one common element
|
||||||
|
const hasIntersection = (array1: string[], array2: string[]): boolean => {
|
||||||
|
return array1.some((item) => array2.includes(item));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Process the menu structure
|
||||||
|
const filteredMenu: FilteredMenuFirstLevel[] = Menu.reduce(
|
||||||
|
(acc: FilteredMenuFirstLevel[], firstLevel: MenuFirstLevel) => {
|
||||||
|
// Create a new first level item with empty subList
|
||||||
|
const newFirstLevel: FilteredMenuFirstLevel = {
|
||||||
|
name: firstLevel.name,
|
||||||
|
lg: { ...firstLevel.lg },
|
||||||
|
subList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Process second level items
|
||||||
|
firstLevel.subList.forEach((secondLevel: MenuSecondLevel) => {
|
||||||
|
// Create a new second level item with empty subList
|
||||||
|
const newSecondLevel: FilteredMenuSecondLevel = {
|
||||||
|
name: secondLevel.name,
|
||||||
|
lg: { ...secondLevel.lg },
|
||||||
|
subList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Process third level items
|
||||||
|
secondLevel.subList.forEach((thirdLevel: MenuThirdLevel) => {
|
||||||
|
// Check if the third level's appList has an intersection with our UUIDs
|
||||||
|
if (
|
||||||
|
thirdLevel.appList &&
|
||||||
|
hasIntersection(thirdLevel.appList, uuids)
|
||||||
|
) {
|
||||||
|
// Find the first matching UUID
|
||||||
|
const matchedUUID = thirdLevel.appList.find((uuid) =>
|
||||||
|
uuids.includes(uuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Only proceed if we found a matching UUID (should always be true due to hasIntersection)
|
||||||
|
if (matchedUUID) {
|
||||||
|
// Create a modified third level item with the matched UUID
|
||||||
|
const newThirdLevel: FilteredMenuThirdLevel = {
|
||||||
|
name: thirdLevel.name,
|
||||||
|
lg: { ...thirdLevel.lg },
|
||||||
|
appUUID: matchedUUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the modified third level to the second level's subList
|
||||||
|
newSecondLevel.subList.push(newThirdLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only add the second level to the first level if it has any matching third level items
|
||||||
|
if (newSecondLevel.subList.length > 0) {
|
||||||
|
newFirstLevel.subList.push(newSecondLevel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only add the first level to the result if it has any matching second level items
|
||||||
|
if (newFirstLevel.subList.length > 0) {
|
||||||
|
acc.push(newFirstLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
return filteredMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { transformMenu };
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
const Individual = {
|
||||||
|
name: "Individual",
|
||||||
|
lg: {
|
||||||
|
tr: "Birey",
|
||||||
|
en: "Individual",
|
||||||
|
},
|
||||||
|
appList: [
|
||||||
|
"0362071d-90d9-48db-8fa0-3528aaf450bd",
|
||||||
|
"6015129b-f665-479c-a440-04fb82ea6114",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const User = {
|
||||||
|
name: "User",
|
||||||
|
lg: {
|
||||||
|
tr: "Kullanıcı",
|
||||||
|
en: "User",
|
||||||
|
},
|
||||||
|
appList: ["14a98ae7-c64e-403d-9b53-32e7ea867ab4"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const Build = {
|
||||||
|
name: "Build",
|
||||||
|
lg: {
|
||||||
|
tr: "Apartman",
|
||||||
|
en: "Build",
|
||||||
|
},
|
||||||
|
appList: ["e368137d-d548-4ed4-90da-337bcc5d1559"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuildParts = {
|
||||||
|
name: "BuildParts",
|
||||||
|
lg: {
|
||||||
|
tr: "Daire",
|
||||||
|
en: "BuildParts",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuildArea = {
|
||||||
|
name: "BuildArea",
|
||||||
|
lg: {
|
||||||
|
tr: "Daire",
|
||||||
|
en: "BuildArea",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const ManagementAccounting = {
|
||||||
|
name: "ManagementAccounting",
|
||||||
|
lg: {
|
||||||
|
tr: "Yönetim Cari Hareketler",
|
||||||
|
en: "ManagementAccounting",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const ManagementBudget = {
|
||||||
|
name: "ManagementBudget",
|
||||||
|
lg: {
|
||||||
|
tr: "Yönetim Bütçe İşlemleri",
|
||||||
|
en: "Management Budget",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuildPartsAccounting = {
|
||||||
|
name: "BuildPartsAccounting",
|
||||||
|
lg: {
|
||||||
|
tr: "Daire Cari Hareketler",
|
||||||
|
en: "Build Parts Accounting",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const AnnualMeeting = {
|
||||||
|
name: "AnnualMeeting",
|
||||||
|
lg: {
|
||||||
|
tr: "Yıllık Olağan Toplantı Tanımlama ve Davet",
|
||||||
|
en: "Annual Meetings and Invitations",
|
||||||
|
},
|
||||||
|
appList: ["d3d97973-41c6-4bad-881b-6bf77d837fa5"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const AnnualMeetingClose = {
|
||||||
|
name: "AnnualMeetingClose",
|
||||||
|
lg: {
|
||||||
|
tr: "Yıllık Olağan Toplantı kapatma ve Cari Yaratma",
|
||||||
|
en: "Annual Meeting Close and Accountings",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const EmergencyMeeting = {
|
||||||
|
name: "EmergencyMeeting",
|
||||||
|
lg: {
|
||||||
|
tr: "Acil Toplantı Tanımlama ve Davet",
|
||||||
|
en: "Emergency Meeting and Invitations",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const EmergencyMeetingClose = {
|
||||||
|
name: "EmergencyMeetingClose",
|
||||||
|
lg: {
|
||||||
|
tr: "Acil Olağan Toplantı kapatma ve Cari Yaratma",
|
||||||
|
en: "Emergency Meeting Close and Accountings",
|
||||||
|
},
|
||||||
|
appList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const MeetingParticipations = {
|
||||||
|
name: "MeetingParticipations",
|
||||||
|
lg: {
|
||||||
|
tr: "Toplantı Katılım İşlemleri",
|
||||||
|
en: "Meeting Participations",
|
||||||
|
},
|
||||||
|
appList: ["SomeUUID"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const Menu = [
|
||||||
|
{
|
||||||
|
name: "Definitions",
|
||||||
|
lg: {
|
||||||
|
tr: "Tanımlar",
|
||||||
|
en: "Definitions",
|
||||||
|
},
|
||||||
|
subList: [
|
||||||
|
{
|
||||||
|
name: "People",
|
||||||
|
lg: {
|
||||||
|
tr: "Kişiler",
|
||||||
|
en: "People",
|
||||||
|
},
|
||||||
|
subList: [Individual, User],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Building",
|
||||||
|
lg: {
|
||||||
|
tr: "Binalar",
|
||||||
|
en: "Building",
|
||||||
|
},
|
||||||
|
subList: [Build, BuildParts, BuildArea],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Building Management",
|
||||||
|
lg: {
|
||||||
|
tr: "Bina Yönetimi",
|
||||||
|
en: "Building Management",
|
||||||
|
},
|
||||||
|
subList: [
|
||||||
|
{
|
||||||
|
name: "Management Accounting",
|
||||||
|
lg: {
|
||||||
|
tr: "Cari işlemler",
|
||||||
|
en: "Management Accounting",
|
||||||
|
},
|
||||||
|
subList: [ManagementAccounting, ManagementBudget, BuildPartsAccounting],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Meetings",
|
||||||
|
lg: {
|
||||||
|
tr: "Toplantılar",
|
||||||
|
en: "Meetings",
|
||||||
|
},
|
||||||
|
subList: [
|
||||||
|
AnnualMeeting,
|
||||||
|
AnnualMeetingClose,
|
||||||
|
EmergencyMeeting,
|
||||||
|
EmergencyMeetingClose,
|
||||||
|
MeetingParticipations,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default Menu;
|
||||||
|
|
@ -49,19 +49,19 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "11222:6379"
|
- "11222:6379"
|
||||||
|
|
||||||
client_frontend:
|
# client_frontend:
|
||||||
container_name: client_frontend
|
# container_name: client_frontend
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: WebServices/client-frontend/Dockerfile
|
# dockerfile: WebServices/client-frontend/Dockerfile
|
||||||
networks:
|
# networks:
|
||||||
- wag-services
|
# - wag-services
|
||||||
ports:
|
# ports:
|
||||||
- "3000:3000"
|
# - "3000:3000"
|
||||||
# volumes:
|
# # volumes:
|
||||||
# - client-frontend:/WebServices/client-frontend
|
# # - client-frontend:/WebServices/client-frontend
|
||||||
environment:
|
# environment:
|
||||||
- NODE_ENV=development
|
# - NODE_ENV=development
|
||||||
|
|
||||||
# management_frontend:
|
# management_frontend:
|
||||||
# container_name: management_frontend
|
# container_name: management_frontend
|
||||||
|
|
@ -77,47 +77,61 @@ services:
|
||||||
# environment:
|
# environment:
|
||||||
# - NODE_ENV=development
|
# - NODE_ENV=development
|
||||||
|
|
||||||
# initializer_service:
|
# initializer_service:
|
||||||
# container_name: initializer_service
|
# container_name: initializer_service
|
||||||
# build:
|
# build:
|
||||||
# context: .
|
# context: .
|
||||||
# dockerfile: ApiServices/InitialService/Dockerfile
|
# dockerfile: ApiServices/InitialService/Dockerfile
|
||||||
# networks:
|
# networks:
|
||||||
# - wag-services
|
# - wag-services
|
||||||
# env_file:
|
# env_file:
|
||||||
# - api_env.env
|
# - api_env.env
|
||||||
# depends_on:
|
# depends_on:
|
||||||
# - postgres-service
|
# - postgres-service
|
||||||
# - mongo_service
|
# - mongo_service
|
||||||
# - redis_service
|
# - redis_service
|
||||||
|
|
||||||
# template_service:
|
dealer_service:
|
||||||
# container_name: template_service
|
container_name: dealer_service
|
||||||
# build:
|
build:
|
||||||
# context: .
|
context: .
|
||||||
# dockerfile: ApiServices/TemplateService/Dockerfile
|
dockerfile: ApiServices/DealerService/Dockerfile
|
||||||
# networks:
|
networks:
|
||||||
# - wag-services
|
- wag-services
|
||||||
# env_file:
|
env_file:
|
||||||
# - api_env.env
|
- api_env.env
|
||||||
# environment:
|
depends_on:
|
||||||
# - API_PATH=app:app
|
- postgres-service
|
||||||
# - API_HOST=0.0.0.0
|
- mongo_service
|
||||||
# - API_PORT=8000
|
- redis_service
|
||||||
# - API_LOG_LEVEL=info
|
|
||||||
# - API_RELOAD=1
|
# template_service:
|
||||||
# - API_ACCESS_TOKEN_TAG=1
|
# container_name: template_service
|
||||||
# - API_APP_NAME=evyos-template-api-gateway
|
# build:
|
||||||
# - API_TITLE=WAG API Template Api Gateway
|
# context: .
|
||||||
# - API_FORGOT_LINK=https://template_service/forgot-password
|
# dockerfile: ApiServices/TemplateService/Dockerfile
|
||||||
# - API_DESCRIPTION=This api is serves as web template api gateway only to evyos web services.
|
# networks:
|
||||||
# - API_APP_URL=https://template_service
|
# - wag-services
|
||||||
# ports:
|
# env_file:
|
||||||
# - "8000:8000"
|
# - api_env.env
|
||||||
# depends_on:
|
# environment:
|
||||||
# - postgres-service
|
# - API_PATH=app:app
|
||||||
# - mongo_service
|
# - API_HOST=0.0.0.0
|
||||||
# - redis_service
|
# - API_PORT=8000
|
||||||
|
# - API_LOG_LEVEL=info
|
||||||
|
# - API_RELOAD=1
|
||||||
|
# - API_ACCESS_TOKEN_TAG=1
|
||||||
|
# - API_APP_NAME=evyos-template-api-gateway
|
||||||
|
# - API_TITLE=WAG API Template Api Gateway
|
||||||
|
# - API_FORGOT_LINK=https://template_service/forgot-password
|
||||||
|
# - API_DESCRIPTION=This api is serves as web template api gateway only to evyos web services.
|
||||||
|
# - API_APP_URL=https://template_service
|
||||||
|
# ports:
|
||||||
|
# - "8000:8000"
|
||||||
|
# depends_on:
|
||||||
|
# - postgres-service
|
||||||
|
# - mongo_service
|
||||||
|
# - redis_service
|
||||||
|
|
||||||
auth_service:
|
auth_service:
|
||||||
container_name: auth_service
|
container_name: auth_service
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue