page retriever and menu @redis added

This commit is contained in:
Berkay 2025-08-07 13:04:02 +03:00
parent a986ddbb95
commit a830cc079d
19 changed files with 660 additions and 526 deletions

View File

@ -3,16 +3,18 @@ import { userSelectValidator } from '@/src/auth/select/dtoValidator';
import { RedisHandlers } from '@/src/utils/store/redisHandlers';
import { EmployeeTokenSchema, OccupantTokenSchema, UserType } from '@/src/types/auth/token';
import { PrismaService } from '@/src/prisma.service';
import { MongoService } from '@/src/database/mongo/mongo.service';
import { EventsService } from '@/src/navigator/events/events.service';
import { PagesService } from '@/src/navigator/pages/pages.service';
import { MenusService } from '@/src/navigator/menus/menu.service';
@Injectable()
export class SelectService {
constructor(
private readonly redis: RedisHandlers,
private readonly prisma: PrismaService,
private readonly mongoService: MongoService,
private readonly eventService: EventsService
private readonly pagesService: PagesService,
private readonly eventService: EventsService,
private readonly menusService: MenusService,
) { }
async run(dto: userSelectValidator, req: Request) {
@ -153,7 +155,17 @@ export class SelectService {
select: {
uu_id: true,
build_parts_uu_id: true,
occupant_type_uu_id: true
occupant_type_uu_id: true,
occupant_types: {
select: {
user_types: {
select: {
token: true,
type_token: true
}
}
}
}
}
});
const occupantType = await this.prisma.occupant_types.findFirstOrThrow({
@ -244,7 +256,10 @@ export class SelectService {
kind: UserType.occupant
});
occupantToken.events = await this.eventService.getEventsOccupants(livingSpace.uu_id) || null
occupantToken.events = await this.eventService.getEventsOccupants(livingSpace.uu_id);
occupantToken.pages = await this.pagesService.getPagesOccupants(accessObject.value.users.uu_id, livingSpace.occupant_types.user_types?.token || '');
occupantToken.menu = await this.menusService.renderOccupantMenu(occupantToken.pages);
const tokenSelect = await this.redis.setSelectToRedis(accessToken, occupantToken, accessObject.value.users.uu_id, dto.uuid);
return { message: 'Select successful', token: tokenSelect };
} else { throw new NotAcceptableException('Invalid user type') }

View File

@ -132,7 +132,7 @@ export class EventsService {
}
}
}
return eventsObject
return eventsObject || null;
}
async getEventsEmployees(employeeUUID: string) {
@ -154,7 +154,7 @@ export class EventsService {
}
}
}
return eventsObject
return eventsObject || null;
}
private async setSavedEventToMapper(data: any, useruuid: string) {

View File

@ -1,366 +1,6 @@
export interface interfaceMenu {
"key": string;
"icon": string;
"text": { "tr": string, "en": string };
"page": string | null;
"token": string | null;
"color": string;
"subs": interfaceMenu[] | null;
}
export interface interfaceMapper {
[key: string]: string;
}
export interface interfaceMenus {
"Menu": interfaceMenu[];
"Mapper": interfaceMapper;
}
function generateMapperKey(keys: string[]): string {
return keys.join(':') + ':';
}
function generateMapper(menu: interfaceMenu[], parentKeys: string[] = []): interfaceMapper {
let mapper: interfaceMapper = {};
for (const item of menu) {
const currentKeys = [...parentKeys, item.key];
// If this item has a page, add it to the mapper
if (item.page) {
mapper[item.page] = generateMapperKey(currentKeys);
}
if (item.subs) {
const subMapper = generateMapper(item.subs, currentKeys);
mapper = { ...mapper, ...subMapper };
}
}
return mapper;
}
function generateDynamicMapper(menus: interfaceMenu[]): interfaceMapper {
return generateMapper(menus);
}
{/*
*/}
const menuForEmployeeDefinition = [
{
key: "a6EoBlTPSgGbUQELbyRwMA",
icon: "",
text: { "tr": "Dashboard", "en": "Dashboard" },
page: "/dashboard",
token: null,
color: "",
subs: null,
},
{
key: "NV2kI8NERmqrNgIeiUYojQ",
icon: "",
text: { "tr": "Bireysel", "en": "Individual" },
page: null,
token: null,
color: "",
subs: [
{
key: "xnhFAyi3Sp2qVWcVcR6m9w",
icon: "",
text: { "tr": "Birey", "en": "Person" },
page: "/person",
token: null,
color: "",
subs: [
{
key: "7wdsqwCQSmXRsRPC9GSgwx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/person/create",
token: null,
color: "",
subs: null
},
{
key: "56O8WRP4TyC7F8bc1vjXgx",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/person/update",
token: null,
color: "",
subs: null
},
{
key: "RPaESp64SUmjNyEY1WUE8Q",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/person/delete",
token: null,
color: "",
subs: null
}
]
},
{
key: "qcRK3EPQSoLSWkJFhtWOwx",
icon: "",
text: { "tr": "Kullanıcı", "en": "User" },
page: "/users",
token: null,
color: "",
subs: [
{
key: "PqNGe0SaQKeyUGyzJoSLwx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/users/create",
token: null,
color: "",
subs: null
},
{
key: "ruvQlE7wQzqHqUvCNIoUnA",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/users/update",
token: null,
color: "",
subs: null
},
{
key: "DfDStf1dTBCRShNQeb5pZA",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/users/delete",
token: null,
color: "",
subs: null
}
]
}
]
},
{
key: "ALV19bQ8S7q8LpOkdRDMwx",
icon: "",
text: { "tr": "Bina", "en": "Build" },
page: null,
token: null,
color: "",
subs: [
{
key: "eToBYS4DTEKseVYMJLNZwx",
icon: "",
text: { "tr": "Binalar", "en": "Building" },
page: null,
token: null,
color: "",
subs: [
{
key: "EkR7p6qmRN2Wb1GLsH5aEQ",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/building/build/create",
token: null,
color: "",
subs: null
},
{
key: "qcoHwABjSli04D7xeWGOHQ",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/building/build/update",
token: null,
color: "",
subs: null
},
{
key: "vC2oPkjRfudvBDlNReeRAx",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/building/build/delete",
token: null,
color: "",
subs: null
}
],
},
{
key: "NFte61RnTHGPWlnoUItHAx",
icon: "",
text: { "tr": "Daireler", "en": "Parts" },
page: null,
token: null,
color: "",
subs: [
{
key: "7o6QNpelSpmxpJxTedEj4w",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/building/parts/create",
token: null,
color: "",
subs: null
},
{
key: "rP6idRkyToLcxwpalCxgxx",
icon: "OBKPalaMQwWhQmQ9Ni0y6Q",
text: { "tr": "Güncelle", "en": "Update" },
page: "/building/parts/update",
token: null,
color: "",
subs: null
},
{
key: "CBNaWzVqRaSpWaPTM54PbA",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/building/parts/delete",
token: null,
color: "",
subs: null
}
],
},
{
key: "NFte61RnTHGPWlnoUItHAx",
icon: "",
text: { "tr": "Alanlar", "en": "Area" },
page: null,
token: null,
color: "",
subs: []
}
],
},
{
key: "yzvyvqMhQ06TdC9paOw4Ax",
icon: "",
text: { "tr": "Yönetim", "en": "Management" },
page: null,
token: null,
color: "",
subs: [
{
key: "DEumSZtaTSKiDsD1VJPQxx",
icon: "",
text: { "tr": "Bütçe", "en": "Budget" },
page: "/management/budget",
token: null,
color: "",
subs: [
{
key: "PIPD61aZRveFZ6GGfK3VYw",
icon: "",
text: { "tr": "Eylemler", "en": "Actions" },
page: "/management/budget/actions",
token: null,
color: "",
subs: null,
},
{
key: "",
icon: "",
text: { "tr": "Durum", "en": "Status" },
page: "/management/budget/status",
token: null,
color: "",
subs: null,
}
],
},
],
},
{
key: "RHI0bthYRjWWf4tBaPBdgx",
icon: "",
text: { "tr": "Toplantılar", "en": "Meetings" },
page: "/meetings",
token: null,
color: "",
subs: [
{
key: "OESxDOI6S4eNcdeRCrKIjQ",
icon: "",
text: { "tr": "Yıllık", "en": "Annual" },
page: "/meetings/annual",
token: null,
color: "",
subs: [
{
key: "MhEHidsRWyHdCqtHJOcvAx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/meetings/annual/create",
token: null,
color: "",
subs: null,
},
{
key: "xhnSW4hWSDuJyREMjXOivA",
icon: "",
text: { "tr": "Kapat", "en": "Close" },
page: "/meetings/annual/close",
token: null,
color: "",
subs: null,
},
],
},
{
key: "A4raUDNFTpZ7mPfqJBGSwx",
icon: "",
text: { "tr": "Acil", "en": "Emergency" },
page: "/meetings/emergency",
token: null,
color: "",
subs: [
{
key: "T3Fd0C5Tf2V1dZhiZuNQxx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/meetings/emergency/create",
token: null,
color: "",
subs: null,
},
{
key: "L1ogOYhSl6BDPstufiSwxx",
icon: "",
text: { "tr": "Kapat", "en": "Close" },
page: "/meetings/emergency/close",
token: null,
color: "",
subs: null,
},
],
},
{
key: "vwzmxtBoQFW62YHes5OZAg",
icon: "",
text: { "tr": "Katılımlar", "en": "Participations" },
page: "/meetings/participations",
token: null,
color: "",
subs: [],
}
],
}
];
const menuForOccupantDefinition = [
{
key: "dzFGPzZJRgmft4HrrTeBtQ",
icon: "",
text: { "tr": "Pano", "en": "Dashboard" },
page: "/dashboard",
token: "IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE",
color: "",
subs: [],
},
]
import { interfaceMenu, interfaceMapper, interfaceMenus } from "@/src/utils/types/menus";
import { menuForEmployeeDefinition } from "./menuItems/employee";
import { menuForOccupantDefinition } from "./menuItems/occupant";
const config = {
FirstLayerColor: "#ebc334",
@ -370,6 +10,20 @@ const config = {
occupantPrefix: "/venue"
}
function generateMapperKey(keys: string[]): string { return keys.join(':') + ':' }
function generateMapper(menu: interfaceMenu[], parentKeys: string[] = []): interfaceMapper {
let mapper: interfaceMapper = {};
for (const item of menu) {
const currentKeys = [...parentKeys, item.key];
if (item.page) { mapper[item.page] = generateMapperKey(currentKeys) }
if (item.subs) { const subMapper = generateMapper(item.subs, currentKeys); mapper = { ...mapper, ...subMapper } }
}
return mapper;
}
function generateDynamicMapper(menus: interfaceMenu[]): interfaceMapper { return generateMapper(menus) }
function applyColorsAndPrefixes(menu: interfaceMenu[], isEmployee: boolean, config: any, layer: number = 1): interfaceMenu[] {
return menu.map(item => {
const newItem = { ...item };

View File

@ -1,5 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ServicesService } from './services.service';
import { ServicesService } from './menu.service';
describe('ServicesService', () => {
let service: ServicesService;

View File

@ -0,0 +1,56 @@
import { Injectable } from '@nestjs/common';
import { employeeMenus, occupantMenus } from "./main";
import { interfaceMenu } from "@/src/utils/types/menus";
// backend_service | Occupant pages
// backend_service | {
// backend_service | IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE: 'IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE:hES1KfaPRZeadmmjdryShA'
// backend_service | }
// backend_service | Occupant Menu Structure
// backend_service | Occupant pages
// backend_service | [
// backend_service | {
// backend_service | key: 'dzFGPzZJRgmft4HrrTeBtQ',
// backend_service | icon: '',
// backend_service | text: { tr: 'Pano', en: 'Dashboard' },
// backend_service | page: '/venue/dashboard',
// backend_service | token: 'IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE',
// backend_service | color: '#ebc334',
// backend_service | subs: []
// backend_service | }
// backend_service | ]
// backend_service | [
// backend_service | {
// backend_service | key: 'dzFGPzZJRgmft4HrrTeBtQ',
// backend_service | icon: '',
// backend_service | text: { tr: 'Pano', en: 'Dashboard' },
// backend_service | page: '/venue/dashboard',
// backend_service | token: 'IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE',
// backend_service | color: '#ebc334',
// backend_service | subs: []
// backend_service | }
// backend_service | ]
@Injectable()
export class MenusService {
constructor() { }
async renderOccupantMenu(pages: any) {
const defaultMenu: interfaceMenu[] = occupantMenus.Menu;
const userHasUrls = Object.keys(pages)
const renderedMenu: interfaceMenu[] = [];
defaultMenu.map((value) => { if (value.token && userHasUrls.includes(value.token)) { renderedMenu.push(value as interfaceMenu) } });
return renderedMenu || [];
}
async renderEmployeeMenu(pages: Record<string, string>) {
const defaultMenu = employeeMenus.Menu;
console.log('Employee pages');
console.dir(pages);
console.log('Employee Menu Structure');
console.dir(defaultMenu);
return null;
}
}

View File

@ -0,0 +1,301 @@
export const menuForEmployeeDefinition = [
{
key: "a6EoBlTPSgGbUQELbyRwMA",
icon: "",
text: { "tr": "Dashboard", "en": "Dashboard" },
page: "/dashboard",
token: "qY56XMEr08wJkNvOR6EYQZKMVdTQEfHdLXGzzxcKU24E",
color: "",
subs: null,
},
{
key: "NV2kI8NERmqrNgIeiUYojQ",
icon: "",
text: { "tr": "Bireysel", "en": "Individual" },
page: null,
token: null,
color: "",
subs: [
{
key: "xnhFAyi3Sp2qVWcVcR6m9w",
icon: "",
text: { "tr": "Birey", "en": "Person" },
page: "/person",
token: null,
color: "",
subs: [
{
key: "7wdsqwCQSmXRsRPC9GSgwx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/person/create",
token: null,
color: "",
subs: null
},
{
key: "56O8WRP4TyC7F8bc1vjXgx",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/person/update",
token: null,
color: "",
subs: null
},
{
key: "RPaESp64SUmjNyEY1WUE8Q",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/person/delete",
token: null,
color: "",
subs: null
}
]
},
{
key: "qcRK3EPQSoLSWkJFhtWOwx",
icon: "",
text: { "tr": "Kullanıcı", "en": "User" },
page: "/users",
token: null,
color: "",
subs: [
{
key: "PqNGe0SaQKeyUGyzJoSLwx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/users/create",
token: null,
color: "",
subs: null
},
{
key: "ruvQlE7wQzqHqUvCNIoUnA",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/users/update",
token: null,
color: "",
subs: null
},
{
key: "DfDStf1dTBCRShNQeb5pZA",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/users/delete",
token: null,
color: "",
subs: null
}
]
}
]
},
{
key: "ALV19bQ8S7q8LpOkdRDMwx",
icon: "",
text: { "tr": "Bina", "en": "Build" },
page: null,
token: null,
color: "",
subs: [
{
key: "eToBYS4DTEKseVYMJLNZwx",
icon: "",
text: { "tr": "Binalar", "en": "Building" },
page: null,
token: null,
color: "",
subs: [
{
key: "EkR7p6qmRN2Wb1GLsH5aEQ",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/building/build/create",
token: null,
color: "",
subs: null
},
{
key: "qcoHwABjSli04D7xeWGOHQ",
icon: "",
text: { "tr": "Güncelle", "en": "Update" },
page: "/building/build/update",
token: null,
color: "",
subs: null
},
{
key: "vC2oPkjRfudvBDlNReeRAx",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/building/build/delete",
token: null,
color: "",
subs: null
}
],
},
{
key: "NFte61RnTHGPWlnoUItHAx",
icon: "",
text: { "tr": "Daireler", "en": "Parts" },
page: null,
token: null,
color: "",
subs: [
{
key: "7o6QNpelSpmxpJxTedEj4w",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/building/parts/create",
token: null,
color: "",
subs: null
},
{
key: "rP6idRkyToLcxwpalCxgxx",
icon: "OBKPalaMQwWhQmQ9Ni0y6Q",
text: { "tr": "Güncelle", "en": "Update" },
page: "/building/parts/update",
token: null,
color: "",
subs: null
},
{
key: "CBNaWzVqRaSpWaPTM54PbA",
icon: "",
text: { "tr": "Sil", "en": "Delete" },
page: "/building/parts/delete",
token: null,
color: "",
subs: null
}
],
},
{
key: "NFte61RnTHGPWlnoUItHAx",
icon: "",
text: { "tr": "Alanlar", "en": "Area" },
page: null,
token: null,
color: "",
subs: []
}
],
},
{
key: "yzvyvqMhQ06TdC9paOw4Ax",
icon: "",
text: { "tr": "Yönetim", "en": "Management" },
page: null,
token: null,
color: "",
subs: [
{
key: "DEumSZtaTSKiDsD1VJPQxx",
icon: "",
text: { "tr": "Bütçe", "en": "Budget" },
page: "/management/budget",
token: null,
color: "",
subs: [
{
key: "PIPD61aZRveFZ6GGfK3VYw",
icon: "",
text: { "tr": "Eylemler", "en": "Actions" },
page: "/management/budget/actions",
token: null,
color: "",
subs: null,
},
{
key: "",
icon: "",
text: { "tr": "Durum", "en": "Status" },
page: "/management/budget/status",
token: null,
color: "",
subs: null,
}
],
},
],
},
{
key: "RHI0bthYRjWWf4tBaPBdgx",
icon: "",
text: { "tr": "Toplantılar", "en": "Meetings" },
page: "/meetings",
token: null,
color: "",
subs: [
{
key: "OESxDOI6S4eNcdeRCrKIjQ",
icon: "",
text: { "tr": "Yıllık", "en": "Annual" },
page: "/meetings/annual",
token: null,
color: "",
subs: [
{
key: "MhEHidsRWyHdCqtHJOcvAx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/meetings/annual/create",
token: null,
color: "",
subs: null,
},
{
key: "xhnSW4hWSDuJyREMjXOivA",
icon: "",
text: { "tr": "Kapat", "en": "Close" },
page: "/meetings/annual/close",
token: null,
color: "",
subs: null,
},
],
},
{
key: "A4raUDNFTpZ7mPfqJBGSwx",
icon: "",
text: { "tr": "Acil", "en": "Emergency" },
page: "/meetings/emergency",
token: null,
color: "",
subs: [
{
key: "T3Fd0C5Tf2V1dZhiZuNQxx",
icon: "",
text: { "tr": "Oluştur", "en": "Create" },
page: "/meetings/emergency/create",
token: null,
color: "",
subs: null,
},
{
key: "L1ogOYhSl6BDPstufiSwxx",
icon: "",
text: { "tr": "Kapat", "en": "Close" },
page: "/meetings/emergency/close",
token: null,
color: "",
subs: null,
},
],
},
{
key: "vwzmxtBoQFW62YHes5OZAg",
icon: "",
text: { "tr": "Katılımlar", "en": "Participations" },
page: "/meetings/participations",
token: null,
color: "",
subs: [],
}
],
}
];

View File

@ -0,0 +1,13 @@
import { interfaceMenu } from "@/src/utils/types/menus";
export const menuForOccupantDefinition: interfaceMenu[] = [
{
key: "dzFGPzZJRgmft4HrrTeBtQ",
icon: "",
text: { "tr": "Pano", "en": "Dashboard" },
page: "/dashboard",
token: "IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE",
color: "",
subs: [],
},
]

View File

@ -1,4 +0,0 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class MenusService { }

View File

@ -4,12 +4,19 @@ import { EventsService } from '@/src/navigator/events/events.service';
import { MongoService } from '@/src/database/mongo/mongo.service';
import { UrlHandler } from '@/src/utils/navigator/urlHandler';
import { eventSetValidator, eventGetValidator } from './dtoValidator';
import { PagesService } from './pages/pages.service';
const tokens = { employeeTypeToken: "L9wBdwV9OlxsLAgh", occupantTypeToken: "j0adQOsJBR0xq24d" }
@Controller('navigator')
export class NavigatorController {
constructor(private prismaService: PrismaService, private eventService: EventsService, private mongoService: MongoService, private urlHandler: UrlHandler) { }
constructor(
private prismaService: PrismaService,
private eventService: EventsService,
private mongoService: MongoService,
private urlHandler: UrlHandler,
private pagesService: PagesService
) { }
@Post('event/set')
async setEvent(@Body() body: eventSetValidator) {
@ -33,7 +40,7 @@ export class NavigatorController {
const allEvents = await this.eventService.getAllEventsEmployees(typeToken);
if (!allEvents) { throw new NotFoundException('Events not found') }
const selectedEvents = await this.eventService.getEventsEmployees(usersUUID);
const selectedEventsKeys = Object.values(selectedEvents).map((value: any) => value.key) || [];
const selectedEventsKeys = Object.values(selectedEvents || {}).map((value: any) => value.key) || [];
for (const event of allEvents) { if (selectedEventsKeys.includes(event.key)) { event.isSelected = true } else { event.isSelected = false } }
return { events: allEvents }
}
@ -41,7 +48,7 @@ export class NavigatorController {
const allEvents = await this.eventService.getAllEventsOccupants(typeToken);
if (!allEvents) { throw new NotFoundException('Events not found') }
const selectedEvents = await this.eventService.getEventsOccupants(usersUUID);
const selectedEventsKeys = Object.values(selectedEvents).map((value: any) => value.key) || [];
const selectedEventsKeys = Object.values(selectedEvents || {}).map((value: any) => value.key) || [];
for (const event of allEvents) { if (selectedEventsKeys.includes(event.key)) { event.isSelected = true } else { event.isSelected = false } }
return { events: allEvents }
} else { throw new NotFoundException('User type not found') }
@ -49,126 +56,18 @@ export class NavigatorController {
@Post('page/set')
async setPage(@Body() body: { usersUUID: string, usersToken: string, url: string, page: Record<string, any> }) {
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: body.usersUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: body.usersToken } })
const urlToken = await this.urlHandler.getSecureUrlToken(body.url)
if (userType.type_token == tokens.employeeTypeToken) {
const person = user.people[0]
const employee = await this.prismaService.employees.findFirstOrThrow({ where: { people_id: person.id, staff: { user_type_id: userType.id } } })
const companyUUID = await this.prismaService.companies.findFirstOrThrow({
where: { departments: { some: { duties: { some: { staff: { some: { uu_id: employee.staff_uu_id } } } } } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${companyUUID.uu_id}`);
const userPage = await this.mongoService.findOne({ [employee.uu_id]: { $exists: true } });
if (!userPage) {
console.log('urlToken', urlToken)
} else { console.log('urlToken', urlToken) }
} else if (userType.type_token == tokens.occupantTypeToken) {
const person = user.people
const livingSpace = await this.prismaService.build_living_space.findFirstOrThrow({
where: { person_id: person.id, occupant_types: { user_types: { id: userType.id } } },
select: { uu_id: true, build_parts_id: true }
})
const buildUUID = await this.prismaService.build.findFirstOrThrow({
where: { build_parts: { some: { id: livingSpace.build_parts_id } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${buildUUID.uu_id}`);
const userPage = await this.mongoService.findOne({ [user.uu_id]: { $exists: true } });
if (!userPage) {
const newUserPageSlot = await this.mongoService.create({ [user.uu_id]: { [`${body.usersToken}`]: { [`${urlToken}`]: `${body.page.key}` } } })
return newUserPageSlot
} else {
console.log('body')
console.dir(body, { depth: null })
console.log('userPage')
console.dir(userPage, { depth: null })
const updatedUserPageSlot = await this.mongoService.updateOne(
userPage._id, { [`${user.uu_id}.${body.usersToken}.${urlToken}`]: `${body.page.key}` }
)
return updatedUserPageSlot ? {
status: "success",
data: updatedUserPageSlot
} : {
status: "error",
data: null
}
}
// console.log('urlToken', { [user.uu_id]: { [`${body.usersToken}`]: { [`${urlToken}`]: `${body.page.key}` } } })
}
else { throw new NotFoundException('User type not found') }
return await this.pagesService.setPageViaToken(body.usersUUID, body.usersToken, body.url, body.page)
}
@Post('page/get')
async getPage(@Body() body: { usersUUID: string, token: string, url?: string, skip?: number, limit?: number }) {
this.mongoService.set("Pages");
const addUrlQuery = body.url ? { url: body.url } : {};
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: body.usersUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: body.token } })
if (userType.type_token == tokens.employeeTypeToken) {
const person = user.people[0]
const pages = await this.mongoService.findMany({
$and: [
{ $or: [{ includeTokens: { $in: ['*'] } }, { includeTokens: { $in: [body.token] } }] },
{ $nor: [{ excludeTokens: { $in: ['*'] } }, { excludeTokens: { $in: [body.token] } }] },
addUrlQuery,
{ typeToken: tokens.employeeTypeToken },
],
}, body.limit || 50, body.skip || 0, ['url'], ['asc'])
if (!pages) { throw new NotFoundException(`Pages not found. User type: ${userType.type_token}`) }
const employee = await this.prismaService.employees.findFirstOrThrow({
where: { people_id: person.id, staff: { user_type_id: userType.id } },
select: { uu_id: true, staff_uu_id: true }
})
const companyUUID = await this.prismaService.companies.findFirstOrThrow({
where: { departments: { some: { duties: { some: { staff: { some: { uu_id: employee.staff_uu_id } } } } } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${companyUUID.uu_id}`);
const usersPages = await this.mongoService.findMany({ [employee.uu_id]: { $exists: true } });
return pages;
}
else if (userType.type_token == tokens.occupantTypeToken) {
const person = user.people
const pages = await this.mongoService.findMany({
$and: [
{ $or: [{ includeTokens: { $in: ['*'] } }, { includeTokens: { $in: [body.token] } }] },
{ $nor: [{ excludeTokens: { $in: ['*'] } }, { excludeTokens: { $in: [body.token] } }] },
addUrlQuery,
{ typeToken: tokens.occupantTypeToken },
],
}, body.limit || 50, body.skip || 0, ['url'], ['asc'])
console.log('pages', pages)
if (!pages) { throw new NotFoundException(`Pages not found. User type: ${userType.type_token}`) }
const livingSpace = await this.prismaService.build_living_space.findFirstOrThrow({
where: { person_id: person.id, occupant_types: { user_types: { id: userType.id } } },
select: { uu_id: true, build_parts_id: true }
})
console.log('livingSpace', livingSpace)
const buildUUID = await this.prismaService.build.findFirstOrThrow({
where: { build_parts: { some: { id: livingSpace.build_parts_id } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${buildUUID.uu_id}`);
const usersPages = await this.mongoService.findMany({ [livingSpace.uu_id]: { $exists: true } });
console.log('usersPages', usersPages)
return Object.entries(pages).map(([key, value]: [string, any]) => {
if (usersPages.some((page: any) => page[key])) { value.isSelected = true } else { value.isSelected = false }
return value;
})
}
else { throw new NotFoundException('User type not found') }
}
private async saveChunkToDB(data: Record<string, any>, chunkIndex: number) {
await this.mongoService.set("Pages");
if (chunkIndex == 1) { await this.mongoService.deleteMany({}) }
await this.mongoService.createMany(Object.values(data));
const pages = await this.pagesService.getPageViaToken(body.usersUUID, body.token, body.url, body.skip, body.limit)
return { pages }
}
@Post('page/configure')
async setPages(@Body() body: { chunkIndex: number; chunkCount: number; data: Record<string, any> }) {
const count = Object.keys(body.data).length;
console.log(`🧩 Chunk [${body.chunkIndex}/${body.chunkCount}] alındı. Kayıt sayısı: ${count}`);
await this.saveChunkToDB(body.data, body.chunkIndex);
return { message: 'Chunk işlendi', count };
return await this.pagesService.configurePages(body.data, body.chunkIndex, body.chunkCount)
}
}

View File

@ -1,16 +1,17 @@
import { Module } from '@nestjs/common';
import { MongoModule } from '@/src/database/mongo/mongo.module';
import { MenusService } from '@/src/navigator/menus/services.service';
import { NavigatorController } from '@/src/navigator/navigator.controller';
import { EventsService } from './events/events.service';
import { PrismaService } from '@/src/prisma.service';
import { MenusService } from '@/src/navigator/menus/menu.service';
import { NavigatorController } from '@/src/navigator/navigator.controller';
import { EventsService } from '@/src/navigator/events/events.service';
import { UrlHandler } from '@/src/utils/navigator/urlHandler';
import { PagesService } from '@/src/navigator/pages/pages.service';
@Module({
controllers: [NavigatorController],
imports: [MongoModule],
providers: [MenusService, EventsService, PrismaService, UrlHandler],
exports: [MenusService, EventsService, PrismaService]
providers: [MenusService, EventsService, PagesService, PrismaService, UrlHandler],
exports: [MenusService, EventsService, PagesService, PrismaService]
})
export class NavigatorModule {
constructor() { }

View File

@ -1,4 +1,172 @@
import { Injectable } from '@nestjs/common';
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@/src/prisma.service';
import { MongoService } from '@/src/database/mongo/mongo.service';
import { UrlHandler } from '@/src/utils/navigator/urlHandler';
@Injectable()
export class PagesService {}
export class PagesService {
constructor(
private readonly prismaService: PrismaService,
private readonly mongoService: MongoService,
private readonly urlHandler: UrlHandler
) { }
tokens = { employeeTypeToken: "L9wBdwV9OlxsLAgh", occupantTypeToken: "j0adQOsJBR0xq24d" }
private async saveChunkToDB(data: Record<string, any>, chunkIndex: number) {
await this.mongoService.set("Pages");
if (chunkIndex == 1) { await this.mongoService.deleteMany({}) }
await this.mongoService.createMany(Object.values(data));
}
async getPagesOccupants(userUUID: string, usersToken: string) {
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: userUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: usersToken } })
if (userType.type_token == this.tokens.occupantTypeToken) {
const person = user.people
const livingSpace = await this.prismaService.build_living_space.findFirstOrThrow({
where: { person_id: person.id, occupant_types: { user_types: { id: userType.id } } },
select: { build_parts_id: true }
})
const buildUUID = await this.prismaService.build.findFirstOrThrow({
where: { build_parts: { some: { id: livingSpace.build_parts_id } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${buildUUID.uu_id}`);
console.log('usersToken', usersToken)
console.log('user.uu_id', user.uu_id)
const userPage = await this.mongoService.findOne({ [user.uu_id]: { $exists: true } })
console.log('userPage', userPage)
if (!userPage) { throw new NotFoundException('Users slot not found') }
const userPageSlot = userPage[user.uu_id][usersToken]
if (!userPageSlot) { throw new NotFoundException('Users slot not found') }
console.log('userPageSlot', userPageSlot)
const writeObject = {}
for (const [key, value] of Object.entries(userPageSlot)) {
writeObject[key] = `${key}:${value}`
}
console.log('writeObject', writeObject)
return writeObject
}
else { throw new NotFoundException('User type not found') }
}
async getPagesEmployee(userUUID: string, usersToken: string) {
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: userUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: usersToken } })
if (userType.type_token == this.tokens.employeeTypeToken) {
const person = user.people[0]
const employee = await this.prismaService.employees.findFirstOrThrow({ where: { people_id: person.id, staff: { user_type_id: userType.id } } })
const companyUUID = await this.prismaService.companies.findFirstOrThrow({
where: { departments: { some: { duties: { some: { staff: { some: { uu_id: employee.staff_uu_id } } } } } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${companyUUID.uu_id}`);
const userPage = await this.mongoService.findOne({ [user.uu_id]: { [usersToken]: { $exists: true } } })
if (!userPage) { throw new NotFoundException('Users slot not found') }
return userPage
}
else { throw new NotFoundException('User type not found') }
}
async setPageViaToken(userUUID: string, usersToken: string, url: string, page: Record<string, any>) {
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: userUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: usersToken } })
const urlToken = await this.urlHandler.getSecureUrlToken(url)
if (userType.type_token == this.tokens.employeeTypeToken) {
const person = user.people[0]
const employee = await this.prismaService.employees.findFirstOrThrow({ where: { people_id: person.id, staff: { user_type_id: userType.id } } })
const companyUUID = await this.prismaService.companies.findFirstOrThrow({
where: { departments: { some: { duties: { some: { staff: { some: { uu_id: employee.staff_uu_id } } } } } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${companyUUID.uu_id}`);
const userPage = await this.mongoService.findOne({ [employee.uu_id]: { $exists: true } });
if (!userPage) {
console.log('urlToken', urlToken)
} else { console.log('urlToken', urlToken) }
} else if (userType.type_token == this.tokens.occupantTypeToken) {
const person = user.people
const livingSpace = await this.prismaService.build_living_space.findFirstOrThrow({
where: { person_id: person.id, occupant_types: { user_types: { id: userType.id } } },
select: { uu_id: true, build_parts_id: true }
})
const buildUUID = await this.prismaService.build.findFirstOrThrow({
where: { build_parts: { some: { id: livingSpace.build_parts_id } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${buildUUID.uu_id}`);
const userPage = await this.mongoService.findOne({ [user.uu_id]: { $exists: true } });
if (!userPage) {
const newUserPageSlot = await this.mongoService.create({ [user.uu_id]: { [`${usersToken}`]: { [`${urlToken}`]: `${page.key}` } } })
return newUserPageSlot
} else {
const updatedUserPageSlot = await this.mongoService.updateOne(userPage._id, { [`${user.uu_id}.${usersToken}.${urlToken}`]: `${page.key}` })
return updatedUserPageSlot ? { status: "success", data: updatedUserPageSlot } : { status: "error", data: null }
}
// console.log('urlToken', { [user.uu_id]: { [`${body.usersToken}`]: { [`${urlToken}`]: `${body.page.key}` } } })
}
else { throw new NotFoundException('User type not found') }
}
async getPageViaToken(usersUUID: string, token: string, url?: string, skip?: number, limit?: number) {
this.mongoService.set("Pages");
const addUrlQuery = url ? { url: url } : {};
const user = await this.prismaService.users.findFirstOrThrow({ where: { uu_id: usersUUID }, include: { people: true } });
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: token } })
if (userType.type_token == this.tokens.employeeTypeToken) {
const person = user.people[0]
const pages = await this.mongoService.findMany({
$and: [
{ $or: [{ includeTokens: { $in: ['*'] } }, { includeTokens: { $in: [token] } }] },
{ $nor: [{ excludeTokens: { $in: ['*'] } }, { excludeTokens: { $in: [token] } }] },
addUrlQuery,
{ typeToken: this.tokens.employeeTypeToken },
],
}, limit || 50, skip || 0, ['url'], ['asc'])
if (!pages) { throw new NotFoundException(`Pages not found. User type: ${userType.type_token}`) }
const employee = await this.prismaService.employees.findFirstOrThrow({
where: { people_id: person.id, staff: { user_type_id: userType.id } },
select: { uu_id: true, staff_uu_id: true }
})
const companyUUID = await this.prismaService.companies.findFirstOrThrow({
where: { departments: { some: { duties: { some: { staff: { some: { uu_id: employee.staff_uu_id } } } } } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${companyUUID.uu_id}`);
const usersPages = await this.mongoService.findMany({ [employee.uu_id]: { $exists: true } });
return pages;
}
else if (userType.type_token == this.tokens.occupantTypeToken) {
const person = user.people
const pages = await this.mongoService.findMany({
$and: [
{ $or: [{ includeTokens: { $in: ['*'] } }, { includeTokens: { $in: [token] } }] },
{ $nor: [{ excludeTokens: { $in: ['*'] } }, { excludeTokens: { $in: [token] } }] },
addUrlQuery,
{ typeToken: this.tokens.occupantTypeToken },
],
}, limit || 50, skip || 0, ['url'], ['asc'])
console.log('pages', pages)
if (!pages) { throw new NotFoundException(`Pages not found. User type: ${userType.type_token}`) }
const livingSpace = await this.prismaService.build_living_space.findFirstOrThrow({
where: { person_id: person.id, occupant_types: { user_types: { id: userType.id } } },
select: { uu_id: true, build_parts_id: true }
})
console.log('livingSpace', livingSpace)
const buildUUID = await this.prismaService.build.findFirstOrThrow({
where: { build_parts: { some: { id: livingSpace.build_parts_id } } }, select: { uu_id: true }
})
this.mongoService.set(`Pages/${buildUUID.uu_id}`);
const usersPages = await this.mongoService.findMany({ [livingSpace.uu_id]: { $exists: true } });
console.log('usersPages', usersPages)
return Object.entries(pages).map(([key, value]: [string, any]) => {
if (usersPages.some((page: any) => page[key])) { value.isSelected = true } else { value.isSelected = false }
return value;
})
}
else { throw new NotFoundException('User type not found') }
}
async configurePages(data: Record<string, any>, chunkIndex: number, chunkCount: number) {
const count = Object.keys(data).length;
console.log(`🧩 Chunk [${chunkIndex}/${chunkCount}] alındı. Kayıt sayısı: ${count}`);
await this.saveChunkToDB(data, chunkIndex);
return { message: 'Chunk işlendi', count };
}
}

View File

@ -256,8 +256,16 @@ export const OccupantTokenSchema = z.object({
part: z.object({}),
company: z.object({}).optional(),
menu: z.array(z.object({})).nullable(),
pages: z.array(z.string()).nullable(),
menu: z.array(z.object({
key: z.string(),
icon: z.string(),
text: z.object({ tr: z.string(), en: z.string() }),
page: z.string().nullable(),
token: z.string().nullable(),
color: z.string(),
subs: z.array(z.lazy(() => OccupantTokenSchema.shape.menu.element)).nullable()
})).nullable(),
pages: z.record(z.string(), z.string()).nullable(),
events: z.record(z.string(), z.string()).nullable(),
selection: z.record(z.string(), z.unknown()).nullable(),
@ -266,9 +274,6 @@ export const OccupantTokenSchema = z.object({
kind: z.literal(UserType.occupant),
});
export const TokenDictTypes = z.discriminatedUnion('kind', [
EmployeeTokenSchema,
OccupantTokenSchema,
]);
export const TokenDictTypes = z.discriminatedUnion('kind', [EmployeeTokenSchema, OccupantTokenSchema]);
export type TokenDictInterface = z.infer<typeof TokenDictTypes>;

View File

@ -0,0 +1,18 @@
export interface interfaceMenu {
key: string;
icon: string;
text: { tr: string, en: string };
page: string | null;
token: string | null;
color: string;
subs: interfaceMenu[] | null;
}
export interface interfaceMapper {
[key: string]: string;
}
export interface interfaceMenus {
Menu: interfaceMenu[];
Mapper: interfaceMapper;
}

View File

@ -18,7 +18,6 @@
"next-intl": "^4.3.4",
"react": "19.1.0",
"react-dom": "19.1.0",
"undici": "^7.13.0",
"zod": "^4.0.10"
},
"devDependencies": {
@ -2319,15 +2318,6 @@
"node": ">=14.17"
}
},
"node_modules/undici": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.13.0.tgz",
"integrity": "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",

View File

@ -20,7 +20,6 @@
"next-intl": "^4.3.4",
"react": "19.1.0",
"react-dom": "19.1.0",
"undici": "^7.13.0",
"zod": "^4.0.10"
},
"devDependencies": {
@ -32,4 +31,4 @@
"tailwindcss": "^4.1.11",
"typescript": "^5"
}
}
}

View File

@ -7,9 +7,10 @@ import { getSelectToken } from '@/fetchers/token/select';
export default async function DashboardPage() {
const pageUrl = "/office/dashboard";
const pageToken = "qY56XMEr08wJkNvOR6EYQZKMVdTQEfHdLXGzzxcKU24E"
const selectToken = await getSelectToken();
try {
const RenderPage = renderPage(selectToken, pageUrl, dashboardPages);
const RenderPage = renderPage(selectToken, pageToken, dashboardPages);
if (RenderPage) {
return <>
<div>Dashboard Page</div>

View File

@ -6,15 +6,13 @@ import { getSelectTokenObject } from '@/fetchers/token/select';
export default async function DashboardPage() {
const pageUrl = "/venue/dashboard";
const pageToken = "IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE"
const selectToken = await getSelectTokenObject();
if (!selectToken) {
const RenderPage = renderPage(selectToken, pageUrl, dashboardPages);
if (selectToken) {
const RenderPage = renderPage(selectToken, pageToken, dashboardPages);
if (RenderPage) {
return <>
<div>Dashboard Page</div>
<div className='flex align-center justify-center h-screen w-screen mt-10 text-2xl'>
<RenderPage />
</div>
<div className='h-screen w-screen text-2xl'><RenderPage /></div>
</>
}
}

View File

@ -1,4 +1,3 @@
function renderPage(selectToken: any, pageUrl: string, fromTokenPages: any) {
const subPageKey = selectToken.pages[pageUrl];
if (Object.keys(fromTokenPages).includes(subPageKey)) {

View File

@ -1,11 +1,32 @@
'use client';
const DashboardhES1KfaPRZeadmmjdryShA: React.FC = () => {
import { useState } from "react";
const LeftMenu = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<h1>DashboardhES1KfaPRZeadmmjdryShA</h1>
<div className="z-50 h-screen">
{isOpen && <button className="" onClick={() => setIsOpen(!isOpen)}>Menu</button>}
{!isOpen && <h1 className="bg-red-500 w-full h-full">
<button className="" onClick={() => setIsOpen(!isOpen)}>LeftMenu</button>
</h1>}
</div>
);
}
const DashboardhES1KfaPRZeadmmjdryShA: React.FC = () => {
return (
<>
<div className="flex flex-col md:flex-row h-screen w-screen">
<div className="w-full md:w-1/4 lg:w-1/4 xl:w-1/4">
<LeftMenu />
</div>
<div className="w-full md:w-3/4 lg:w-3/4 xl:w-3/4">
<h1>DashboardhES1KfaPRZeadmmjdryShA</h1>
</div>
</div>
</>
);
}
export default DashboardhES1KfaPRZeadmmjdryShA;