update dmenu module

This commit is contained in:
morteza-mortezai
2025-12-16 16:31:53 +03:30
parent 36f09b816a
commit ea7160c1de
14 changed files with 146 additions and 76 deletions
+2 -2
View File
@@ -28,7 +28,7 @@ import { DanakServicesModule } from "./modules/danak-services/danak-services.mod
import { DashboardModule } from "./modules/dashboards/dashboard.module"; import { DashboardModule } from "./modules/dashboards/dashboard.module";
import { DiscountsModule } from "./modules/discounts/discounts.module"; import { DiscountsModule } from "./modules/discounts/discounts.module";
import { InvoicesModule } from "./modules/invoices/invoices.module"; import { InvoicesModule } from "./modules/invoices/invoices.module";
import { IconsModule } from "./modules/icons/icons.module"; import { DmenuModule } from "./modules/dmenu/dmenu.module";
import { LandingModule } from "./modules/landing/landing.module"; import { LandingModule } from "./modules/landing/landing.module";
import { LearningModule } from "./modules/learnings/learning.module"; import { LearningModule } from "./modules/learnings/learning.module";
import { LoggerModule } from "./modules/logger/logger.module"; import { LoggerModule } from "./modules/logger/logger.module";
@@ -86,7 +86,7 @@ import { WalletsModule } from "./modules/wallets/wallets.module";
DiscountsModule, DiscountsModule,
SupportPlansModule, SupportPlansModule,
AccessLogsModule, AccessLogsModule,
IconsModule, DmenuModule,
], ],
controllers: [], controllers: [],
}) })
+2 -2
View File
@@ -1,6 +1,6 @@
import { ConfigService } from "@nestjs/config"; import { ConfigService } from "@nestjs/config";
export function iconsConfig() { export function dmenuConfig() {
return { return {
inject: [ConfigService], inject: [ConfigService],
useFactory: async (configService: ConfigService) => { useFactory: async (configService: ConfigService) => {
@@ -13,7 +13,7 @@ export function iconsConfig() {
}; };
} }
export interface IIconsConfig { export interface IDmenuConfig {
baseUrl: string; baseUrl: string;
username: string; username: string;
password: string; password: string;
+1
View File
@@ -0,0 +1 @@
export const DMENU_CONFIG = "ICONS_CONFIG";
@@ -1,92 +1,102 @@
import { Body, Controller, Delete, Get, Param, Patch, Post } from "@nestjs/common"; import { Body, Controller, Delete, Get, Param, Patch, Post } from "@nestjs/common";
import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiTags } from "@nestjs/swagger"; import { ApiBearerAuth, ApiOperation, ApiParam, ApiTags } from "@nestjs/swagger";
import { CreateGroupDto } from "./DTO/create-group.dto"; import { ContactService } from "./providers/contact.service";
import { CreateIconDto } from "./DTO/create-icon.dto";
import { UpdateGroupDto } from "./DTO/update-group.dto";
import { UpdateIconDto } from "./DTO/update-icon.dto";
import { IconsService } from "./providers/icons.service"; import { IconsService } from "./providers/icons.service";
import { CreateIconDto } from "./DTO/create-icon.dto";
import { UpdateIconDto } from "./DTO/update-icon.dto";
import { CreateGroupDto } from "./DTO/create-group.dto";
import { UpdateGroupDto } from "./DTO/update-group.dto";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { PermissionsDec } from "../../common/decorators/permission.decorator"; import { PermissionsDec } from "../../common/decorators/permission.decorator";
import { PermissionEnum } from "../users/enums/permission.enum"; import { PermissionEnum } from "../users/enums/permission.enum";
@ApiTags("icons") @ApiTags("d-menu")
@Controller("admin/icons") @Controller("admin/dmenu")
@AuthGuards() @AuthGuards()
@PermissionsDec(PermissionEnum.ICONS) @PermissionsDec(PermissionEnum.DMENU)
@ApiBearerAuth() @ApiBearerAuth()
export class IconsController { export class DmenuController {
constructor(private readonly iconsService: IconsService) {} constructor(
private readonly iconsService: IconsService,
private readonly contactService: ContactService,
) {}
// Icon endpoints // Icon endpoints
@Post() @Post('icons')
@ApiOperation({ summary: "Create icon" }) @ApiOperation({ summary: "Create icon" })
@ApiBody({ type: CreateIconDto })
createIcon(@Body() dto: CreateIconDto) { createIcon(@Body() dto: CreateIconDto) {
return this.iconsService.createIcon(dto); return this.iconsService.createIcon(dto);
} }
@Get() @Get('icons')
@ApiOperation({ summary: "Get all icons" }) @ApiOperation({ summary: "Get all icons" })
findAllIcons() { findAllIcons() {
return this.iconsService.findAllIcons(); return this.iconsService.findAllIcons();
} }
// Group endpoints: place BEFORE `icons/:id` routes to avoid route conflicts
@Get(":id") @Post("icons/groups")
@ApiOperation({ summary: "Get icon by id" })
@ApiParam({ name: "id", required: true, type: String })
findOneIcon(@Param("id") id: string) {
return this.iconsService.findOneIcon(id);
}
@Patch(":id")
@ApiOperation({ summary: "Update icon" })
@ApiParam({ name: "id" })
@ApiBody({ type: UpdateIconDto })
updateIcon(@Param("id") id: string, @Body() dto: UpdateIconDto) {
return this.iconsService.updateIcon(id, dto);
}
@Delete(":id")
@ApiOperation({ summary: "Delete icon" })
@ApiParam({ name: "id" })
removeIcon(@Param("id") id: string) {
return this.iconsService.removeIcon(id);
}
// Group endpoints (must come before :id routes to avoid route conflicts)
@Post("groups")
@ApiOperation({ summary: "Create icon group" }) @ApiOperation({ summary: "Create icon group" })
@ApiBody({ type: CreateGroupDto })
createGroup(@Body() dto: CreateGroupDto) { createGroup(@Body() dto: CreateGroupDto) {
return this.iconsService.createGroup(dto); return this.iconsService.createGroup(dto);
} }
@Get("groups") @Get("icons/groups")
@ApiOperation({ summary: "Get all icon groups" }) @ApiOperation({ summary: "Get all icon groups" })
findAllGroups() { findAllGroups() {
return this.iconsService.findAllGroups(); return this.iconsService.findAllGroups();
} }
@Get("groups/:id") @Get("icons/groups/:id")
@ApiOperation({ summary: "Get icon group by id" }) @ApiOperation({ summary: "Get icon group by id" })
@ApiParam({ name: "id", required: true, type: String }) @ApiParam({ name: "id", required: true, type: String })
findOneGroup(@Param("id") id: string) { findOneGroup(@Param("id") id: string) {
return this.iconsService.findOneGroup(id); return this.iconsService.findOneGroup(id);
} }
@Patch("groups/:id") @Patch("icons/groups/:id")
@ApiOperation({ summary: "Update icon group" }) @ApiOperation({ summary: "Update icon group" })
@ApiParam({ name: "id" }) @ApiParam({ name: "id" })
@ApiBody({ type: UpdateGroupDto })
updateGroup(@Param("id") id: string, @Body() dto: UpdateGroupDto) { updateGroup(@Param("id") id: string, @Body() dto: UpdateGroupDto) {
return this.iconsService.updateGroup(id, dto); return this.iconsService.updateGroup(id, dto);
} }
@Delete("groups/:id") @Delete("icons/groups/:id")
@ApiOperation({ summary: "Delete icon group" }) @ApiOperation({ summary: "Delete icon group" })
@ApiParam({ name: "id" }) @ApiParam({ name: "id" })
removeGroup(@Param("id") id: string) { removeGroup(@Param("id") id: string) {
return this.iconsService.removeGroup(id); return this.iconsService.removeGroup(id);
} }
@Get("icons/:id")
@ApiOperation({ summary: "Get icon by id" })
@ApiParam({ name: "id", required: true, type: String })
findOneIcon(@Param("id") id: string) {
return this.iconsService.findOneIcon(id);
}
@Patch("icons/:id")
@ApiOperation({ summary: "Update icon" })
@ApiParam({ name: "id" })
updateIcon(@Param("id") id: string, @Body() dto: UpdateIconDto) {
return this.iconsService.updateIcon(id, dto);
}
@Delete("icons/:id")
@ApiOperation({ summary: "Delete icon" })
@ApiParam({ name: "id" })
removeIcon(@Param("id") id: string) {
return this.iconsService.removeIcon(id);
}
// contacts
@Get('contacts')
findAll() {
return this.contactService.findAll();
}
@Get("contacts/:id")
findOne(@Param("id") id: string) {
return this.contactService.findOne(+id);
}
} }
+22
View File
@@ -0,0 +1,22 @@
import { Module } from "@nestjs/common";
import { DMENU_CONFIG } from "./constants";
import { DmenuController } from "./dmenu.controller";
import { ContactService } from "./providers/contact.service";
import { IconsService } from "./providers/icons.service";
import { dmenuConfig } from "../../configs/icons.config";
@Module({
imports: [],
controllers: [DmenuController],
providers: [
IconsService,
ContactService,
{
provide: DMENU_CONFIG,
useFactory: dmenuConfig().useFactory,
inject: dmenuConfig().inject,
},
],
})
export class DmenuModule {}
@@ -0,0 +1,60 @@
import { HttpService } from "@nestjs/axios";
import { Injectable, Logger } from "@nestjs/common";
import { Inject } from "@nestjs/common";
import { AxiosError } from "axios";
import { catchError, firstValueFrom, throwError } from "rxjs";
import { IDmenuConfig } from "../../../configs/icons.config";
import { DMENU_CONFIG } from "../constants";
@Injectable()
export class ContactService {
private readonly logger = new Logger(ContactService.name);
constructor(
@Inject(DMENU_CONFIG) private readonly config: IDmenuConfig,
private readonly httpService: HttpService,
) {}
private getHeaders(): Record<string, string> {
const credentials = Buffer.from(`${this.config.username}:${this.config.password}`).toString("base64");
return {
"Content-Type": "application/json",
Authorization: `Basic ${credentials}`,
};
}
async findAll() {
try {
const { data } = await firstValueFrom(
this.httpService.get(`${this.config.baseUrl}/super-admin/contacts`, { headers: this.getHeaders() }).pipe(
catchError((err: AxiosError) => {
this.logger.error(`Failed to fetch contacts: ${err.message}`, err.stack);
return throwError(() => err);
}),
),
);
return data;
} catch (error: unknown) {
this.logger.error(`Error fetching contacts: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
async findOne(id: number) {
try {
const { data } = await firstValueFrom(
this.httpService.get(`${this.config.baseUrl}/super-admin/contacts/${id}`, { headers: this.getHeaders() }).pipe(
catchError((err: AxiosError) => {
this.logger.error(`Failed to fetch contact: ${err.message}`, err.stack);
return throwError(() => err);
}),
),
);
return data;
} catch (error: unknown) {
this.logger.error(`Error fetching contact: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
}
@@ -3,8 +3,8 @@ import { Inject, Injectable, Logger } from "@nestjs/common";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import { catchError, firstValueFrom, throwError } from "rxjs"; import { catchError, firstValueFrom, throwError } from "rxjs";
import { IIconsConfig } from "../../../configs/icons.config"; import { IDmenuConfig } from "../../../configs/icons.config";
import { ICONS_CONFIG } from "../constants"; import { DMENU_CONFIG } from "../constants";
import { CreateGroupDto } from "../DTO/create-group.dto"; import { CreateGroupDto } from "../DTO/create-group.dto";
import { CreateIconDto } from "../DTO/create-icon.dto"; import { CreateIconDto } from "../DTO/create-icon.dto";
import { UpdateGroupDto } from "../DTO/update-group.dto"; import { UpdateGroupDto } from "../DTO/update-group.dto";
@@ -15,7 +15,7 @@ export class IconsService {
private readonly logger = new Logger(IconsService.name); private readonly logger = new Logger(IconsService.name);
constructor( constructor(
@Inject(ICONS_CONFIG) private readonly config: IIconsConfig, @Inject(DMENU_CONFIG) private readonly config: IDmenuConfig,
private readonly httpService: HttpService, private readonly httpService: HttpService,
) {} ) {}
-2
View File
@@ -1,2 +0,0 @@
export const ICONS_CONFIG = "ICONS_CONFIG";
-21
View File
@@ -1,21 +0,0 @@
import { Module } from "@nestjs/common";
import { ICONS_CONFIG } from "./constants";
import { IconsController } from "./icons.controller";
import { IconsService } from "./providers/icons.service";
import { iconsConfig } from "../../configs/icons.config";
@Module({
imports: [],
controllers: [IconsController],
providers: [
IconsService,
{
provide: ICONS_CONFIG,
useFactory: iconsConfig().useFactory,
inject: iconsConfig().inject,
},
],
exports: [IconsService],
})
export class IconsModule {}
+2 -2
View File
@@ -20,5 +20,5 @@ export enum PermissionEnum {
PAYMENTS = "payments", PAYMENTS = "payments",
MANAGE_SSO_CLIENTS = "manage_sso_clients", MANAGE_SSO_CLIENTS = "manage_sso_clients",
SUPPORT_PLAN = "support_plan", SUPPORT_PLAN = "support_plan",
ICONS = "icons", DMENU = "dmenu",
} }