feat(app): add environment import/export and sidebar footer info
- add environment import/export API endpoints and client integration - add environment export actions and toolbar import/export buttons in UI - move theme switcher to sidebar bottom and show root package version - switch snippet card menu icon to cog for consistent options affordance
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "liqa-server",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "nest build",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import {
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUUID,
|
||||
} from "class-validator";
|
||||
import { EnvironmentUrls } from "../environment.entity";
|
||||
|
||||
export class EnvironmentExportDto {
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsIn(["environment"])
|
||||
kind?: "environment";
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
id?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsObject()
|
||||
urls: EnvironmentUrls;
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||
import { EnvironmentService } from "./environment.service";
|
||||
import { CreateEnvironmentDto } from "./dto/create-environment.dto";
|
||||
import { UpdateEnvironmentDto } from "./dto/update-environment.dto";
|
||||
import { EnvironmentExportDto } from "./dto/environment-export.dto";
|
||||
import { PaginationQueryDto } from "../common/dto/pagination.dto";
|
||||
import { EnvironmentOrderBy } from "./environment.service";
|
||||
|
||||
@@ -30,6 +31,13 @@ export class EnvironmentController {
|
||||
return this.environmentService.create(dto);
|
||||
}
|
||||
|
||||
@Post("import")
|
||||
@ApiOperation({ summary: "Import an environment (upsert by id or name)" })
|
||||
@ApiResponse({ status: 201, description: "Environment imported" })
|
||||
async importEnvironment(@Body() dto: EnvironmentExportDto) {
|
||||
return this.environmentService.importEnvironment(dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: "List all environments (paginated)" })
|
||||
@ApiResponse({ status: 200, description: "Paginated environments" })
|
||||
@@ -37,6 +45,15 @@ export class EnvironmentController {
|
||||
return this.environmentService.findAll(query);
|
||||
}
|
||||
|
||||
@Get(":id/export")
|
||||
@ApiOperation({ summary: "Export an environment as a plain object" })
|
||||
@ApiResponse({ status: 200, description: "Environment export payload" })
|
||||
@ApiResponse({ status: 404, description: "Environment not found" })
|
||||
async exportEnvironment(@Param("id", ParseUUIDPipe) id: string) {
|
||||
const env = await this.environmentService.findOne(id);
|
||||
return this.environmentService.exportEnvironment(env);
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@ApiOperation({ summary: "Get environment by ID" })
|
||||
@ApiResponse({ status: 200, description: "Environment record" })
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Repository } from "typeorm";
|
||||
import { EnvironmentEntity } from "./environment.entity";
|
||||
import { CreateEnvironmentDto } from "./dto/create-environment.dto";
|
||||
import { UpdateEnvironmentDto } from "./dto/update-environment.dto";
|
||||
import { EnvironmentExportDto } from "./dto/environment-export.dto";
|
||||
import {
|
||||
PaginationQueryDto,
|
||||
PaginatedResult,
|
||||
@@ -64,4 +65,32 @@ export class EnvironmentService {
|
||||
await this.findOne(id);
|
||||
await this.repo.delete(id);
|
||||
}
|
||||
|
||||
exportEnvironment(env: EnvironmentEntity): EnvironmentExportDto {
|
||||
return {
|
||||
kind: "environment",
|
||||
id: env.id,
|
||||
name: env.name,
|
||||
urls: env.urls,
|
||||
};
|
||||
}
|
||||
|
||||
async importEnvironment(dto: EnvironmentExportDto): Promise<EnvironmentEntity> {
|
||||
if (dto.id) {
|
||||
const existing = await this.repo.findOneBy({ id: dto.id });
|
||||
if (existing) {
|
||||
Object.assign(existing, { name: dto.name, urls: dto.urls });
|
||||
return this.repo.save(existing);
|
||||
}
|
||||
return this.repo.save(
|
||||
this.repo.create({ id: dto.id, name: dto.name, urls: dto.urls }),
|
||||
);
|
||||
}
|
||||
const byName = await this.repo.findOneBy({ name: dto.name });
|
||||
if (byName) {
|
||||
Object.assign(byName, { urls: dto.urls });
|
||||
return this.repo.save(byName);
|
||||
}
|
||||
return this.repo.save(this.repo.create({ name: dto.name, urls: dto.urls }));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user