added pages tested via backend
This commit is contained in:
parent
9232da69d3
commit
a986ddbb95
|
|
@ -37,7 +37,5 @@ export class AccountsController {
|
||||||
@Post('filter')
|
@Post('filter')
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
@UseGuards(AuthControlGuard, EndpointControlGuard)
|
@UseGuards(AuthControlGuard, EndpointControlGuard)
|
||||||
async filterAccounts(@Body() query: any, @Req() req: any) {
|
async filterAccounts(@Body() query: any, @Req() req: any) { return await this.navigator.getFunction(req, this.accountsService.mapper, query) }
|
||||||
return await this.navigator.getFunction(req, this.accountsService.mapper, query)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,10 @@ import {
|
||||||
import { SuperUsersService } from './superusers/superusers.service';
|
import { SuperUsersService } from './superusers/superusers.service';
|
||||||
import { UrlHandler } from '../utils/navigator/urlHandler';
|
import { UrlHandler } from '../utils/navigator/urlHandler';
|
||||||
import { Navigator } from '@/src/utils/navigator/navigator';
|
import { Navigator } from '@/src/utils/navigator/navigator';
|
||||||
|
import { NavigatorModule } from '../navigator/navigator.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PrismaModule, UtilsModule, RedisModule],
|
imports: [PrismaModule, UtilsModule, RedisModule, NavigatorModule],
|
||||||
providers: [
|
providers: [
|
||||||
AccountsService,
|
AccountsService,
|
||||||
AuthControlGuard,
|
AuthControlGuard,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { SuperUsersService } from './superusers/superusers.service';
|
import { SuperUsersService } from './superusers/superusers.service';
|
||||||
|
import { EventsService } from '../navigator/events/events.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AccountsService {
|
export class AccountsService {
|
||||||
|
|
@ -7,9 +8,32 @@ export class AccountsService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private superUsersService: SuperUsersService,
|
private superUsersService: SuperUsersService,
|
||||||
|
private eventService: EventsService,
|
||||||
) {
|
) {
|
||||||
this.mapper = {
|
this.mapper = {
|
||||||
"j0adQOsJBR0xq24dxLKdDU9EQRmt4gzE05CmhA": this.superUsersService,
|
"j0adQOsJBR0xq24dxLKdDU9EQRmt4gzE05CmhA": this.superUsersService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onModuleInit() {
|
||||||
|
Object.entries(this.mapper).map(async ([key, value]) => {
|
||||||
|
const service = value as any
|
||||||
|
await this.eventService.setEvents(service.events, "AccountsService")
|
||||||
|
})
|
||||||
|
// const accountPages = await fetch(
|
||||||
|
// "http://localhost:3000/pages",
|
||||||
|
// {
|
||||||
|
// method: 'POST',
|
||||||
|
// headers: {
|
||||||
|
// 'Content-Type': 'application/json',
|
||||||
|
// },
|
||||||
|
// body: JSON.stringify({
|
||||||
|
// token: 'j0adQOsJBR0xq24dxLKdDU9EQRmt4gzE05CmhA',
|
||||||
|
// pages: {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,7 @@ export class SelectService {
|
||||||
value: part.api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown.value
|
value: part.api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown.value
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
uu_id: build.uu_id,
|
uu_id: build.uu_id, build_name: build.build_name
|
||||||
build_name: build.build_name
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -245,19 +244,9 @@ export class SelectService {
|
||||||
kind: UserType.occupant
|
kind: UserType.occupant
|
||||||
});
|
});
|
||||||
|
|
||||||
// Render page and menu
|
occupantToken.events = await this.eventService.getEventsOccupants(livingSpace.uu_id) || null
|
||||||
const eventsObject = await this.eventService.getEventsOccupants(livingSpace.uu_id)
|
const tokenSelect = await this.redis.setSelectToRedis(accessToken, occupantToken, accessObject.value.users.uu_id, dto.uuid);
|
||||||
eventsObject && (occupantToken.events = eventsObject)
|
|
||||||
|
|
||||||
const tokenSelect = await this.redis.setSelectToRedis(
|
|
||||||
accessToken,
|
|
||||||
occupantToken,
|
|
||||||
accessObject.value.users.uu_id,
|
|
||||||
dto.uuid
|
|
||||||
);
|
|
||||||
return { message: 'Select successful', token: tokenSelect };
|
return { message: 'Select successful', token: tokenSelect };
|
||||||
} else {
|
} else { throw new NotAcceptableException('Invalid user type') }
|
||||||
throw new NotAcceptableException('Invalid user type');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Db, Document, Collection, Filter, ObjectId, UpdateResult } from 'mongodb';
|
import { Db, Document, Collection, Filter, ObjectId, UpdateResult, Sort, SortDirection } from 'mongodb';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MongoService {
|
export class MongoService {
|
||||||
|
|
@ -12,6 +12,35 @@ export class MongoService {
|
||||||
|
|
||||||
async getDb() { return this.collection }
|
async getDb() { return this.collection }
|
||||||
|
|
||||||
|
async create(data: Record<string, any>): Promise<Document> {
|
||||||
|
const insertResult = await this.collection.insertOne(data);
|
||||||
|
if (!insertResult.acknowledged) { throw new Error('Failed to insert document') }
|
||||||
|
return await this.getOne(insertResult.insertedId);
|
||||||
|
}
|
||||||
|
async createMany(data: Record<string, any>[]): Promise<number> {
|
||||||
|
const insertResult = await this.collection.insertMany(data);
|
||||||
|
if (!insertResult.acknowledged) { throw new Error('Failed to insert documents') }
|
||||||
|
return insertResult.insertedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findManyKeyWhere(value: string, limit?: number, skip?: number): Promise<Document[]> {
|
||||||
|
const docs = await this.collection.find({
|
||||||
|
$where: function () {
|
||||||
|
return Object.keys(this).some(key => key.includes(value));
|
||||||
|
}
|
||||||
|
}).toArray();
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findManyKeyWhereValue(value: string, limit?: number, skip?: number): Promise<Document[]> {
|
||||||
|
const docs = await this.collection.find({
|
||||||
|
$where: function () {
|
||||||
|
return Object.keys(this).some(key => this[key] === value);
|
||||||
|
}
|
||||||
|
}).toArray();
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a document by UUID or create it if it doesn't exist
|
* Find a document by UUID or create it if it doesn't exist
|
||||||
* @param data Document data with UUID field
|
* @param data Document data with UUID field
|
||||||
|
|
@ -53,10 +82,9 @@ export class MongoService {
|
||||||
* const user = await mongoService.findOne('12345');
|
* const user = await mongoService.findOne('12345');
|
||||||
* This will search for documents with uuid matching pattern ^TOKEN:12345:
|
* This will search for documents with uuid matching pattern ^TOKEN:12345:
|
||||||
*/
|
*/
|
||||||
async findOne(filter: Filter<Document>): Promise<Document> {
|
async findOne(filter: Filter<Document>): Promise<Document | null> {
|
||||||
const result = await this.collection.findOne(filter);
|
const result = await this.collection.findOne(filter);
|
||||||
if (!result) { throw new Error(`Document with ID key ${filter} not found`) }
|
return result ? result : null;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,11 +102,19 @@ export class MongoService {
|
||||||
* @example
|
* @example
|
||||||
* Find users by role
|
* Find users by role
|
||||||
* const admins = await mongoService.findMany({ role: 'admin' } as Filter<Document>);
|
* const admins = await mongoService.findMany({ role: 'admin' } as Filter<Document>);
|
||||||
|
* const documents = await mongoService.findMany(filter, limit, skip, ['name', 'createdAt'], ['asc', 'desc']);
|
||||||
*/
|
*/
|
||||||
async findMany(filter: Filter<Document>, limit?: number, skip?: number): Promise<Document[]> {
|
async findMany(filter: Filter<Document>, limit?: number, skip?: number, sortBys?: string[], sortDirections?: SortDirection[]): Promise<Document[]> {
|
||||||
let query = this.collection.find(filter);
|
let query = this.collection.find(filter);
|
||||||
if (typeof skip === 'number') { query = query.skip(skip) }
|
if (typeof skip === 'number') { query = query.skip(skip) }
|
||||||
if (typeof limit === 'number') { query = query.limit(limit) }
|
if (typeof limit === 'number') { query = query.limit(limit) }
|
||||||
|
if (sortBys && sortDirections && sortBys.length === sortDirections.length) {
|
||||||
|
const sortOptions = sortBys.reduce<Record<string, SortDirection>>((acc, sortBy, index) => ({
|
||||||
|
...acc,
|
||||||
|
[sortBy]: sortDirections[index]
|
||||||
|
}), {});
|
||||||
|
query = query.sort(sortOptions);
|
||||||
|
}
|
||||||
return await query.toArray();
|
return await query.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,4 +290,5 @@ export class MongoService {
|
||||||
|
|
||||||
return await this.collection.find(query as unknown as Filter<Document>).toArray();
|
return await this.collection.find(query as unknown as Filter<Document>).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ export class AuthControlGuard implements CanActivate {
|
||||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
const req = context.switchToHttp().getRequest();
|
const req = context.switchToHttp().getRequest();
|
||||||
const accessToken = this.cacheService.mergeLoginKey(req);
|
const accessToken = this.cacheService.mergeLoginKey(req);
|
||||||
|
if (!accessToken) { throw new ForbiddenException('Send to Login') }
|
||||||
|
this.cacheService.renewTtlLoginFromRedis(req);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +34,9 @@ export class EndpointControlGuard implements CanActivate {
|
||||||
const keyUrl = `${path}:${method.toUpperCase()}`;
|
const keyUrl = `${path}:${method.toUpperCase()}`;
|
||||||
const driveToken = await this.urlHandler.getSecureUrlToken(keyUrl);
|
const driveToken = await this.urlHandler.getSecureUrlToken(keyUrl);
|
||||||
const accessObject = await this.cacheService.getSelectFromRedis(req);
|
const accessObject = await this.cacheService.getSelectFromRedis(req);
|
||||||
|
if (!accessObject) { throw new ForbiddenException('Access denied') }
|
||||||
req.driveToken = `${driveToken}:${accessObject?.value.functionsRetriever}`;
|
req.driveToken = `${driveToken}:${accessObject?.value.functionsRetriever}`;
|
||||||
|
this.cacheService.renewTtlSelectFromRedis(req);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,20 @@ export class mongoGetValidator {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
skip: number;
|
skip: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class eventSetValidator {
|
||||||
|
@IsString()
|
||||||
|
usersUUID: string;
|
||||||
|
|
||||||
|
@IsObject()
|
||||||
|
event: Record<string, Record<string, Record<string, string>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class eventGetValidator {
|
||||||
|
@IsString()
|
||||||
|
usersUUID: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
typeToken: string;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ import { IsString, IsObject, IsOptional, IsNumber, ValidateNested } from 'class-
|
||||||
export class EventsSetterValidator {
|
export class EventsSetterValidator {
|
||||||
|
|
||||||
@IsObject()
|
@IsObject()
|
||||||
data: Record<string, Record<string, Record<string, string>>>;
|
event: Record<string, Record<string, Record<string, string>>>;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
dutyUUID: string; // UUID of employee or occupant
|
userUUID: string; // UUID of employee or occupant
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventsGetterValidator {
|
export class EventsGetterValidator {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export class EventsService {
|
||||||
seperator = "/"
|
seperator = "/"
|
||||||
|
|
||||||
private async getBuildUUID(uuid: string) {
|
private async getBuildUUID(uuid: string) {
|
||||||
|
console.log('uuid', uuid)
|
||||||
const livingSpace = await this.prisma.build_living_space.findFirstOrThrow({
|
const livingSpace = await this.prisma.build_living_space.findFirstOrThrow({
|
||||||
where: { uu_id: uuid },
|
where: { uu_id: uuid },
|
||||||
select: {
|
select: {
|
||||||
|
|
@ -97,20 +98,18 @@ export class EventsService {
|
||||||
await this.mongoService.set(`EVENTS${this.seperator}${buildUUID}`);
|
await this.mongoService.set(`EVENTS${this.seperator}${buildUUID}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findByRegexKey(regexKey: string, searchType: SearchType = 'value'): Promise<Document[]> {
|
private escapeRegex(text: string): string {
|
||||||
const tokens = await this.mongoService.findByRegexAcrossFields(regexKey, 'i', searchType);
|
return text.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
|
||||||
if (tokens.length === 0) {
|
|
||||||
throw new NotFoundException('Token not found')
|
|
||||||
}
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findByFilter(filter: object): Promise<Document[]> {
|
async getAllEventsOccupants(userTypeToken: string): Promise<Document[] | null> {
|
||||||
const tokens = await this.mongoService.findMany(filter);
|
await this.mongoService.set(`Events`)
|
||||||
if (tokens.length === 0) {
|
return await this.mongoService.findManyKeyWhere(userTypeToken) || null;
|
||||||
throw new NotFoundException('Token not found')
|
|
||||||
}
|
}
|
||||||
return tokens;
|
|
||||||
|
async getAllEventsEmployees(userTypeToken: string): Promise<Document[] | null> {
|
||||||
|
await this.mongoService.set(`Events`)
|
||||||
|
return await this.mongoService.findManyKeyWhere(userTypeToken) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEventsOccupants(livingSpaceUUID: string) {
|
async getEventsOccupants(livingSpaceUUID: string) {
|
||||||
|
|
@ -136,51 +135,67 @@ export class EventsService {
|
||||||
return eventsObject
|
return eventsObject
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEventsEmployees(@Body() body: EventsGetterValidator) {
|
async getEventsEmployees(employeeUUID: string) {
|
||||||
const companyUUID = await this.getCompanyUUID(body.dutyUUID);
|
const eventsObject = {}
|
||||||
|
const companyUUID = await this.getCompanyUUID(employeeUUID);
|
||||||
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
||||||
await this.mongoService.set(`EVENTS${this.seperator}${companyUUID}`);
|
await this.mongoService.set(`EVENTS${this.seperator}${companyUUID}`);
|
||||||
if (body.regexKey) {
|
const eventsResponse = await this.mongoService.findOne({ [employeeUUID]: { $exists: true } });
|
||||||
// Use the new flattened search for regex with search type
|
if (eventsResponse && typeof eventsResponse === 'object') {
|
||||||
const searchType: SearchType = body.searchType as SearchType || 'value';
|
const mapOfEvents = eventsResponse[employeeUUID];
|
||||||
const tokens = await this.mongoService.findByRegexAcrossFields(body.regexKey, 'i', searchType);
|
if (mapOfEvents && typeof mapOfEvents === 'object') {
|
||||||
if (tokens.length === 0) { throw new NotFoundException('Token not found') }
|
const userTypeTokenKey = Object.keys(mapOfEvents)[0];
|
||||||
return { data: tokens, message: 'Tokens found' };
|
const userTypeTokenValue = mapOfEvents[userTypeTokenKey];
|
||||||
} else if (body.filter) {
|
if (userTypeTokenValue && typeof userTypeTokenValue === 'object') {
|
||||||
const tokens = await this.mongoService.findMany(body.filter);
|
for (const siteUrlTokenKey of Object.keys(userTypeTokenValue)) {
|
||||||
if (tokens.length === 0) { throw new NotFoundException('Token not found') }
|
const siteUrlTokenValue = userTypeTokenValue[siteUrlTokenKey];
|
||||||
return { data: tokens, message: 'Tokens found' };
|
eventsObject[`${siteUrlTokenKey}:${userTypeTokenKey}`] = siteUrlTokenValue
|
||||||
} else { throw new NotFoundException('Regex key or filter is required') }
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventsObject
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setSavedEventToMapper(data: any, useruuid: string) {
|
private async setSavedEventToMapper(data: any, useruuid: string) {
|
||||||
await this.mongoService.set(`MAP${this.seperator}EVENTS`);
|
await this.mongoService.set(`MAP${this.seperator}EVENTS`);
|
||||||
const events = await this.mongoService.findOrCreate({ uuid: `EVENTS:${useruuid}:${data.uuid}`, data });
|
const events = await this.mongoService.findOrCreate({ uuid: `EVENTS${this.seperator}${useruuid}:${data.uuid}`, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteSavedEventFromMapper(data: any, useruuid: string) {
|
private async deleteSavedEventFromMapper(data: any, useruuid: string) {
|
||||||
await this.mongoService.set(`MAP${this.seperator}EVENTS`);
|
await this.mongoService.set(`MAP${this.seperator}EVENTS`);
|
||||||
const events = await this.mongoService.deleteMany({ uuid: `EVENTS:${useruuid}:${data.uuid}` });
|
const events = await this.mongoService.deleteMany({ uuid: `EVENTS${this.seperator}${useruuid}:${data.uuid}` });
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async setEventsEmployees(@Body() body: EventsSetterValidator) {
|
async setEventsEmployees(@Body() body: EventsSetterValidator) {
|
||||||
const companyUUID = await this.getCompanyUUID(body.dutyUUID);
|
const companyUUID = await this.getCompanyUUID(body.userUUID);
|
||||||
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
||||||
await this.mongoService.set(`EVENTS${this.seperator}${companyUUID}`);
|
await this.mongoService.set(`EVENTS${this.seperator}${companyUUID}`);
|
||||||
const events = await this.mongoService.findOrCreate(body.data);
|
const events = await this.mongoService.findOrCreate(body.event);
|
||||||
// await this.setSavedEventToMapper(events, body.dutyUUID);
|
// await this.setSavedEventToMapper(events, body.dutyUUID);
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setEventsOccupants(@Body() body: EventsSetterValidator) {
|
async setEventsOccupants(@Body() body: EventsSetterValidator) {
|
||||||
const buildUUID = await this.getBuildUUID(body.dutyUUID);
|
const buildUUID = await this.getBuildUUID(body.userUUID);
|
||||||
if (!buildUUID) { throw new NotFoundException('Build not found') }
|
if (!buildUUID) { throw new NotFoundException('Build not found') }
|
||||||
await this.mongoService.set(`EVENTS${this.seperator}${buildUUID}`);
|
await this.mongoService.set(`EVENTS${this.seperator}${buildUUID}`);
|
||||||
const events = await this.mongoService.findOrCreate(body.data);
|
const events = await this.mongoService.findOrCreate(body.event);
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setEvents(events: any, serviceName: string) {
|
||||||
|
await this.mongoService.set(`Events`);
|
||||||
|
for (const [key, value] of Object.entries(events)) {
|
||||||
|
const description = (value as Array<any>)[0].endpoint || "";
|
||||||
|
console.log(`Setting events for ${serviceName} ${description} is carried to nosql database store.`)
|
||||||
|
await this.mongoService.deleteMany({ [key]: { $exists: true } });
|
||||||
|
await this.mongoService.create({ [key]: value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async deleteEventsEmployees(@Body() body: EventsGetterValidator) {
|
async deleteEventsEmployees(@Body() body: EventsGetterValidator) {
|
||||||
const companyUUID = await this.getCompanyUUID(body.dutyUUID);
|
const companyUUID = await this.getCompanyUUID(body.dutyUUID);
|
||||||
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
if (!companyUUID) { throw new NotFoundException('Company not found') }
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ const menuForOccupantDefinition = [
|
||||||
icon: "",
|
icon: "",
|
||||||
text: { "tr": "Pano", "en": "Dashboard" },
|
text: { "tr": "Pano", "en": "Dashboard" },
|
||||||
page: "/dashboard",
|
page: "/dashboard",
|
||||||
token: null,
|
token: "IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE",
|
||||||
color: "",
|
color: "",
|
||||||
subs: [],
|
subs: [],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,174 @@
|
||||||
import { Controller, Post, NotFoundException, Body } from '@nestjs/common';
|
import { Controller, Post, NotFoundException, Body } from '@nestjs/common';
|
||||||
|
import { PrismaService } from '@/src/prisma.service';
|
||||||
|
import { EventsService } from '@/src/navigator/events/events.service';
|
||||||
import { MongoService } from '@/src/database/mongo/mongo.service';
|
import { MongoService } from '@/src/database/mongo/mongo.service';
|
||||||
import { mongoSetValidator, mongoGetValidator } from '@/src/navigator/dtoValidator';
|
import { UrlHandler } from '@/src/utils/navigator/urlHandler';
|
||||||
|
import { eventSetValidator, eventGetValidator } from './dtoValidator';
|
||||||
|
|
||||||
|
const tokens = { employeeTypeToken: "L9wBdwV9OlxsLAgh", occupantTypeToken: "j0adQOsJBR0xq24d" }
|
||||||
|
|
||||||
@Controller('navigator')
|
@Controller('navigator')
|
||||||
export class NavigatorController {
|
export class NavigatorController {
|
||||||
constructor(private mongoService: MongoService) { }
|
constructor(private prismaService: PrismaService, private eventService: EventsService, private mongoService: MongoService, private urlHandler: UrlHandler) { }
|
||||||
|
|
||||||
@Post('event/set')
|
@Post('event/set')
|
||||||
async setEvent(@Body() body: any) { }
|
async setEvent(@Body() body: eventSetValidator) {
|
||||||
|
const user = await this.prismaService.users.findFirst({ where: { uu_id: body.usersUUID }, include: { people: true } });
|
||||||
|
if (!user) { throw new NotFoundException('User not found') }
|
||||||
|
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: body.event.token } })
|
||||||
|
const person = user.people[0]
|
||||||
|
const people2userType = await this.prismaService.employees.findFirstOrThrow({ where: { uu_id: person.uu_id, staff: { user_type_uu_id: userType.uu_id } } })
|
||||||
|
if (!people2userType) { throw new NotFoundException('User type not found') }
|
||||||
|
if (userType.type_token == tokens.employeeTypeToken) { await this.eventService.setEventsEmployees({ event: body.event, userUUID: body.usersUUID }) }
|
||||||
|
else if (userType.type_token == tokens.occupantTypeToken) { await this.eventService.setEventsOccupants({ event: body.event, userUUID: body.usersUUID }) }
|
||||||
|
else { throw new NotFoundException('User type not found') }
|
||||||
|
return body.event;
|
||||||
|
}
|
||||||
|
|
||||||
@Post('event/get')
|
@Post('event/get')
|
||||||
async getEvent(@Body() body: any) {
|
async getEvent(@Body() body: eventGetValidator) {
|
||||||
// Get all events from backend statics & Get users registered event from mongo service
|
const { typeToken, usersUUID } = body
|
||||||
|
const userType = await this.prismaService.user_types.findFirstOrThrow({ where: { token: typeToken } })
|
||||||
|
if (userType.type_token == tokens.employeeTypeToken) {
|
||||||
|
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) || [];
|
||||||
|
for (const event of allEvents) { if (selectedEventsKeys.includes(event.key)) { event.isSelected = true } else { event.isSelected = false } }
|
||||||
|
return { events: allEvents }
|
||||||
|
}
|
||||||
|
else if (userType.type_token == tokens.occupantTypeToken) {
|
||||||
|
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) || [];
|
||||||
|
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') }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('page/set')
|
@Post('page/set')
|
||||||
async setPage(@Body() body: any) { }
|
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') }
|
||||||
|
}
|
||||||
|
|
||||||
@Post('page/get')
|
@Post('page/get')
|
||||||
async getPage(@Body() body: any) {
|
async getPage(@Body() body: { usersUUID: string, token: string, url?: string, skip?: number, limit?: number }) {
|
||||||
// Get all pages from Frontend & Get users registered page from mongo service
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@ import { MenusService } from '@/src/navigator/menus/services.service';
|
||||||
import { NavigatorController } from '@/src/navigator/navigator.controller';
|
import { NavigatorController } from '@/src/navigator/navigator.controller';
|
||||||
import { EventsService } from './events/events.service';
|
import { EventsService } from './events/events.service';
|
||||||
import { PrismaService } from '@/src/prisma.service';
|
import { PrismaService } from '@/src/prisma.service';
|
||||||
|
import { UrlHandler } from '@/src/utils/navigator/urlHandler';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [NavigatorController],
|
controllers: [NavigatorController],
|
||||||
imports: [MongoModule],
|
imports: [MongoModule],
|
||||||
providers: [MenusService, EventsService, PrismaService],
|
providers: [MenusService, EventsService, PrismaService, UrlHandler],
|
||||||
exports: [MenusService, EventsService, PrismaService]
|
exports: [MenusService, EventsService, PrismaService]
|
||||||
})
|
})
|
||||||
export class NavigatorModule {
|
export class NavigatorModule {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,18 @@ export class Navigator {
|
||||||
|
|
||||||
constructor(private redisHandler: RedisHandlers) { }
|
constructor(private redisHandler: RedisHandlers) { }
|
||||||
|
|
||||||
|
async getAllInfos(mainService: any) {
|
||||||
|
const mainServiceMapper = mainService?.mapper
|
||||||
|
if (!mainServiceMapper) { throw new ForbiddenException(`Mapper in ${mainService.constructor.name} is missing or null`) }
|
||||||
|
const allInfos = Object.entries(mainServiceMapper).map(([key, value]) => {
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return allInfos
|
||||||
|
}
|
||||||
|
|
||||||
async getInfos(mainService: any, userToken: string) {
|
async getInfos(mainService: any, userToken: string) {
|
||||||
// Get asked service by userToken
|
// Get asked service by userToken
|
||||||
const mainServiceMapper = mainService?.mapper
|
const mainServiceMapper = mainService?.mapper
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { createHash } from 'crypto';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UrlHandler {
|
export class UrlHandler {
|
||||||
private createSecureKeyWithoutLib(url: string): string {
|
private createSecureKeyWithoutLib(url: string): string {
|
||||||
const subString = createHash('sha256').update(url).digest().toString('base64').substring(0, 16)
|
const subString = createHash('sha256').update(url).digest().toString('base64').substring(0, 48)
|
||||||
return subString.replace(/=/g, 'E').replace(/-/g, 'M').replace(/_/g, 'N').replace(/\+/g, 'P').replace(/\//g, 'Q')
|
return subString.replace(/=/g, 'E').replace(/-/g, 'M').replace(/_/g, 'N').replace(/\+/g, 'P').replace(/\//g, 'Q')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13,7 +13,6 @@ export class UrlHandler {
|
||||||
return this.createSecureKeyWithoutLib(url);
|
return this.createSecureKeyWithoutLib(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async getEvents(events: Events, mapper: Mapper) {
|
async getEvents(events: Events, mapper: Mapper) {
|
||||||
for (const keyUrl of Object.keys(mapper)) {
|
for (const keyUrl of Object.keys(mapper)) {
|
||||||
const splittedMapper = keyUrl.split(':')
|
const splittedMapper = keyUrl.split(':')
|
||||||
|
|
|
||||||
|
|
@ -224,15 +224,15 @@ export class RedisHandlers {
|
||||||
}
|
}
|
||||||
|
|
||||||
async renewTtlLoginFromRedis(req: Request): Promise<any> {
|
async renewTtlLoginFromRedis(req: Request): Promise<any> {
|
||||||
const mergedKey = this.mergeLoginKey(req);
|
const loginToken = await this.getLoginFromRedis(req);
|
||||||
const value = await this.cacheService.get(mergedKey);
|
if (!loginToken) { throw new ForbiddenException('Login token not found') }
|
||||||
return this.cacheService.set_with_ttl(mergedKey, value, 86400);
|
return this.cacheService.set_with_ttl(loginToken.key, loginToken.value, 60 * 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
async renewTtlSelectFromRedis(req: Request): Promise<any> {
|
async renewTtlSelectFromRedis(req: Request): Promise<any> {
|
||||||
const mergedKey = this.mergeSelectKey(req);
|
const selectToken = await this.getSelectFromRedis(req);
|
||||||
const value = await this.cacheService.get(mergedKey);
|
if (!selectToken) { throw new ForbiddenException('Select token not found') }
|
||||||
return this.cacheService.set_with_ttl(mergedKey, value, 60 * 30);
|
return this.cacheService.set_with_ttl(selectToken.key, selectToken.value, 60 * 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setLoginToRedis(token: AuthToken, userUUID: string): Promise<any> {
|
async setLoginToRedis(token: AuthToken, userUUID: string): Promise<any> {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"next-intl": "^4.3.4",
|
"next-intl": "^4.3.4",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
|
"undici": "^7.13.0",
|
||||||
"zod": "^4.0.10"
|
"zod": "^4.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -2318,6 +2319,15 @@
|
||||||
"node": ">=14.17"
|
"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": {
|
"node_modules/undici-types": {
|
||||||
"version": "6.21.0",
|
"version": "6.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"reset-sync": "rm ./.next/server/app/[locale]/sync.lock"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|
@ -19,6 +20,7 @@
|
||||||
"next-intl": "^4.3.4",
|
"next-intl": "^4.3.4",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
|
"undici": "^7.13.0",
|
||||||
"zod": "^4.0.10"
|
"zod": "^4.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import { getSelectToken } from '@/fetchers/token/select';
|
||||||
export default async function DashboardPage() {
|
export default async function DashboardPage() {
|
||||||
const pageUrl = "/office/dashboard";
|
const pageUrl = "/office/dashboard";
|
||||||
const selectToken = await getSelectToken();
|
const selectToken = await getSelectToken();
|
||||||
|
try {
|
||||||
const RenderPage = renderPage(selectToken, pageUrl, dashboardPages);
|
const RenderPage = renderPage(selectToken, pageUrl, dashboardPages);
|
||||||
if (RenderPage) {
|
if (RenderPage) {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div>Dashboard Page</div>
|
<div>Dashboard Page</div>
|
||||||
<div className='flex align-center justify-center h-screen w-screen mt-10 text-2xl'>
|
<div className='flex align-center justify-center h-screen w-screen mt-10 text-2xl'>
|
||||||
|
|
@ -18,6 +18,7 @@ export default async function DashboardPage() {
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
} catch (error) { console.log(error) }
|
||||||
return <>
|
return <>
|
||||||
<div>Dashboard Page</div>
|
<div>Dashboard Page</div>
|
||||||
<div>You are not allowed to reach any page under {pageUrl}. Please contact your administrator.</div>
|
<div>You are not allowed to reach any page under {pageUrl}. Please contact your administrator.</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { Inter } from 'next/font/google';
|
import { Inter } from 'next/font/google';
|
||||||
import { notFound } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
import { Locale, locales } from "@/i18n/locales";
|
import { Locale, locales } from "@/i18n/locales";
|
||||||
import { routing } from "@/i18n/routing";
|
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
import '../globals.css';
|
import '../globals.css';
|
||||||
|
|
||||||
|
|
@ -19,41 +18,26 @@ export function generateStaticParams() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({ params }: Omit<Props, 'children'>) {
|
export async function generateMetadata({ params }: Omit<Props, 'children'>) {
|
||||||
// Properly await params before accessing properties
|
|
||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
const t = await getTranslations({ locale, namespace: 'LocaleLayout' });
|
const t = await getTranslations({ locale, namespace: 'LocaleLayout' });
|
||||||
|
return { title: t('title') };
|
||||||
return {
|
|
||||||
title: t('title')
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function LocaleLayout({ children, params }: Props) {
|
export default async function LocaleLayout({ children, params }: Props) {
|
||||||
// Properly await params before accessing properties
|
|
||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
|
|
||||||
// Validate that the incoming locale is valid
|
|
||||||
if (!locales.includes(locale as Locale)) {
|
if (!locales.includes(locale as Locale)) {
|
||||||
notFound();
|
redirect('/' + locales[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load messages for all child components
|
|
||||||
const messages = (await import(`@/i18n/${locale}.json`)).default;
|
const messages = (await import(`@/i18n/${locale}.json`)).default;
|
||||||
|
|
||||||
// Enable static rendering
|
|
||||||
// Note: unstable_setRequestLocale is removed as it's causing TypeScript errors
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<html lang={locale}>
|
<html lang={locale}>
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<NextIntlClientProvider
|
<NextIntlClientProvider locale={locale} messages={messages} timeZone="Europe/Istanbul">
|
||||||
locale={locale}
|
|
||||||
messages={messages}
|
|
||||||
timeZone="Europe/Istanbul" // Configure a default timezone for Turkey
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
'use server';
|
'use server';
|
||||||
import HomePage from '@/app/home-page';
|
import HomePage from '@/app/home-page';
|
||||||
|
import { sendChunksToNest } from '@/lib/init-sync';
|
||||||
|
|
||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
|
sendChunksToNest();
|
||||||
return <HomePage />;
|
return <HomePage />;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
'use server'
|
||||||
|
import { redirect } from '@/i18n/navigation';
|
||||||
|
|
||||||
|
const RedirectHome = async () => {
|
||||||
|
return redirect({ locale: "en", href: "/" })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RedirectHome
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { employeeMapper } from '@/pages/office/mapper';
|
||||||
|
import { occupantMapper } from '@/pages/venue/mapper';
|
||||||
|
import { Page } from '@/pages/types/page';
|
||||||
|
|
||||||
|
function chunkifyObject<T>(obj: Record<string, T>, chunkSize: number): Record<string, T>[] {
|
||||||
|
const keys = Object.keys(obj);
|
||||||
|
const chunks: Record<string, T>[] = [];
|
||||||
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
||||||
|
const chunk: Record<string, T> = {};
|
||||||
|
keys.slice(i, i + chunkSize).forEach((key) => {
|
||||||
|
chunk[key] = obj[key];
|
||||||
|
});
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sendChunksToNest() {
|
||||||
|
const sendObject: Page = { ...employeeMapper, ...occupantMapper };
|
||||||
|
const lockPath = path.join(__dirname, 'sync.lock');
|
||||||
|
|
||||||
|
if (fs.existsSync(lockPath)) {
|
||||||
|
console.log('🔁 Zaten sync edilmiş, işlem atlandı.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunks = chunkifyObject(sendObject, 50);
|
||||||
|
const totalChunks = chunks.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < totalChunks; i++) {
|
||||||
|
const chunk = chunks[i];
|
||||||
|
|
||||||
|
// 👇 Bu şekilde index bilgisiyle beraber nested body oluşturuyoruz
|
||||||
|
const payload = {
|
||||||
|
chunkIndex: i + 1,
|
||||||
|
chunkCount: totalChunks,
|
||||||
|
data: chunk,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:8001/navigator/page/configure', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
console.log(`✅ [${payload.chunkIndex}/${payload.chunkCount}] Chunk gönderildi. Kayıt sayısı: ${result.count}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ [${i + 1}/${totalChunks}] Chunk gönderimi sırasında hata:`, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(lockPath, 'done');
|
||||||
|
console.log('🎉 Tüm chunklar gönderildi ve lock dosyası oluşturuldu.');
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
function renderPage(selectToken: any, pageUrl: string, dashboardPages: any) {
|
function renderPage(selectToken: any, pageUrl: string, fromTokenPages: any) {
|
||||||
const subPageKey = selectToken.pages[pageUrl];
|
const subPageKey = selectToken.pages[pageUrl];
|
||||||
if (Object.keys(dashboardPages).includes(subPageKey)) {
|
if (Object.keys(fromTokenPages).includes(subPageKey)) {
|
||||||
const subPage = dashboardPages[subPageKey as keyof typeof dashboardPages];
|
const subPage = fromTokenPages[subPageKey as keyof typeof fromTokenPages];
|
||||||
if (subPage) { if (subPage.page) { return subPage.page } }
|
if (subPage) { if (subPage.page) { return subPage.page } }
|
||||||
} return null;
|
} return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
const DashboardPtnZblJTri0DnlQaUOikQx: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>DashboardPtnZblJTri0DnlQaUOikQx</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DashboardPtnZblJTri0DnlQaUOikQx;
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
const DashboardU0QncONSk22PFxZ5xefmgx: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>DashboardU0QncONSk22PFxZ5xefmgx</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DashboardU0QncONSk22PFxZ5xefmgx;
|
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
import { Page } from "@/pages/types/page";
|
import { Page } from "@/pages/types/page";
|
||||||
import DashboardU0QncONSk22PFxZ5xefmgx from "./U0QncONSk22PFxZ5xefmgx";
|
import DashboardPtnZblJTri0DnlQaUOikQx from "./PtnZblJTri0DnlQaUOikQx";
|
||||||
|
|
||||||
const dashboardPages: Page = {
|
const dashboardPages: Page = {
|
||||||
"qY56XMEr08wJkNvOR6EYQZKMVdTQEfHdLXGzzxcKU24E:U0QncONSk22PFxZ5xefmgx": {
|
"qY56XMEr08wJkNvOR6EYQZKMVdTQEfHdLXGzzxcKU24E:PtnZblJTri0DnlQaUOikQx": {
|
||||||
name: "DashboardU0QncONSk22PFxZ5xefmgx",
|
name: "DashboardPtnZblJTri0DnlQaUOikQx",
|
||||||
key: "U0QncONSk22PFxZ5xefmgx",
|
key: "PtnZblJTri0DnlQaUOikQx",
|
||||||
url: "/venue/dashboard",
|
url: "/office/dashboard",
|
||||||
page: DashboardU0QncONSk22PFxZ5xefmgx,
|
page: DashboardPtnZblJTri0DnlQaUOikQx,
|
||||||
description: "Dashboard",
|
description: "Dashboard",
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
|
typeToken: "L9wBdwV9OlxsLAgh",
|
||||||
params: {},
|
params: {},
|
||||||
events: ["Aevent", "Aevent", "Aevent"],
|
events: ["Aevent", "Aevent", "Aevent"],
|
||||||
tokens: ["TOKEN", "TOKEN", "TOKEN", "TOKEN"]
|
includeTokens: ['*'],
|
||||||
|
excludeTokens: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import {dashboardPages} from "./dashboard/mapper";
|
||||||
|
export const employeeMapper = {
|
||||||
|
...dashboardPages
|
||||||
|
}
|
||||||
|
|
@ -6,9 +6,11 @@ export interface Page {
|
||||||
page: React.FC;
|
page: React.FC;
|
||||||
description: string;
|
description: string;
|
||||||
isDefault: boolean;
|
isDefault: boolean;
|
||||||
|
typeToken: string;
|
||||||
params: Record<string, boolean>;
|
params: Record<string, boolean>;
|
||||||
events?: string[];
|
events?: string[];
|
||||||
tokens?: string[];
|
includeTokens?: string[];
|
||||||
|
excludeTokens?: string[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
const DashboardIdTch3qS9aJXkvqXodAxxx: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>DashboardIdTch3qS9aJXkvqXodAxxx</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DashboardIdTch3qS9aJXkvqXodAxxx;
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
const DashboardhES1KfaPRZeadmmjdryShA: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>DashboardhES1KfaPRZeadmmjdryShA</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DashboardhES1KfaPRZeadmmjdryShA;
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
import { Page } from "@/pages/types/page";
|
import { Page } from "@/pages/types/page";
|
||||||
import DashboardIdTch3qS9aJXkvqXodAxxx from "./IdTch3qS9aJXkvqXodAxxx";
|
import DashboardhES1KfaPRZeadmmjdryShA from "./hES1KfaPRZeadmmjdryShA";
|
||||||
|
|
||||||
const dashboardPages: Page = {
|
const dashboardPages: Page = {
|
||||||
"IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE:IdTch3qS9aJXkvqXodAxxx": {
|
"IbGpchaw3muiY7y9rnV0EJYoPy5XoOOrITT9JlfIbqwE:hES1KfaPRZeadmmjdryShA": {
|
||||||
name: "DashboardIdTch3qS9aJXkvqXodAxxx",
|
name: "DashboardhES1KfaPRZeadmmjdryShA",
|
||||||
key: "IdTch3qS9aJXkvqXodAxxx",
|
key: "hES1KfaPRZeadmmjdryShA",
|
||||||
url: "/venue/dashboard",
|
url: "/venue/dashboard",
|
||||||
page: DashboardIdTch3qS9aJXkvqXodAxxx,
|
page: DashboardhES1KfaPRZeadmmjdryShA,
|
||||||
description: "Dashboard",
|
description: "Dashboard",
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
|
typeToken: "j0adQOsJBR0xq24d",
|
||||||
params: {},
|
params: {},
|
||||||
events: ["Aevent", "Aevent", "Aevent"],
|
events: [],
|
||||||
tokens: ["TOKEN", "TOKEN", "TOKEN", "TOKEN"]
|
includeTokens: ["*"],
|
||||||
|
excludeTokens: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { dashboardPages } from "./dashboard/mapper";
|
||||||
|
|
||||||
|
export const occupantMapper = {
|
||||||
|
...dashboardPages,
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue