96 switch from azure table storage to sqlite #99
64
api/migrations/1754234179211-initial_migration.ts
Normal file
64
api/migrations/1754234179211-initial_migration.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class InitialMigration1754234179211 implements MigrationInterface {
|
||||||
|
name = 'InitialMigration1754234179211'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "certificates" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "number" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "endorsements" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "medical" ("id" varchar PRIMARY KEY NOT NULL, "class" varchar NOT NULL, "expirationDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "pilots" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "address" varchar NOT NULL, "city" varchar NOT NULL, "state" varchar NOT NULL, "postalCode" varchar NOT NULL, "email" varchar NOT NULL, "phone" varchar NOT NULL)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "logs" ("id" varchar PRIMARY KEY NOT NULL, "date" datetime NOT NULL, "aircraftMakeModel" varchar NOT NULL, "aircraftIdentity" varchar NOT NULL, "routeFrom" varchar NOT NULL, "routeTo" varchar NOT NULL, "durationOfFlight" integer NOT NULL, "singleEngineLand" integer, "simulatorAtd" integer, "landingsDay" integer, "landingsNight" integer, "groundTrainingReceived" integer, "flightTrainingReceived" integer, "crossCountry" integer, "night" integer, "solo" integer, "pilotInCommand" integer, "instrumentActual" integer, "instrumentSimulated" integer, "instrumentApproaches" integer, "instrumentHolds" integer, "instrumentNavTrack" integer, "notes" varchar, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "tracks" ("id" varchar PRIMARY KEY NOT NULL, "url" varchar NOT NULL, "order" integer NOT NULL, "logId" varchar)`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_certificates" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "number" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar, CONSTRAINT "FK_05a68997dc2d27dfcc642a4cf51" FOREIGN KEY ("pilotId") REFERENCES "pilots" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_certificates"("id", "type", "number", "issueDate", "pilotId") SELECT "id", "type", "number", "issueDate", "pilotId" FROM "certificates"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "certificates"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_certificates" RENAME TO "certificates"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_endorsements" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar, CONSTRAINT "FK_96a69a0bfbdeccce6bffe34002d" FOREIGN KEY ("pilotId") REFERENCES "pilots" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_endorsements"("id", "type", "issueDate", "pilotId") SELECT "id", "type", "issueDate", "pilotId" FROM "endorsements"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "endorsements"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_endorsements" RENAME TO "endorsements"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_medical" ("id" varchar PRIMARY KEY NOT NULL, "class" varchar NOT NULL, "expirationDate" datetime NOT NULL, "pilotId" varchar, CONSTRAINT "FK_cb1f5d88fa2b105cc77513e9082" FOREIGN KEY ("pilotId") REFERENCES "pilots" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_medical"("id", "class", "expirationDate", "pilotId") SELECT "id", "class", "expirationDate", "pilotId" FROM "medical"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "medical"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_medical" RENAME TO "medical"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_logs" ("id" varchar PRIMARY KEY NOT NULL, "date" datetime NOT NULL, "aircraftMakeModel" varchar NOT NULL, "aircraftIdentity" varchar NOT NULL, "routeFrom" varchar NOT NULL, "routeTo" varchar NOT NULL, "durationOfFlight" integer NOT NULL, "singleEngineLand" integer, "simulatorAtd" integer, "landingsDay" integer, "landingsNight" integer, "groundTrainingReceived" integer, "flightTrainingReceived" integer, "crossCountry" integer, "night" integer, "solo" integer, "pilotInCommand" integer, "instrumentActual" integer, "instrumentSimulated" integer, "instrumentApproaches" integer, "instrumentHolds" integer, "instrumentNavTrack" integer, "notes" varchar, "pilotId" varchar, CONSTRAINT "FK_19598551658f7625a82c7f029c8" FOREIGN KEY ("pilotId") REFERENCES "pilots" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_logs"("id", "date", "aircraftMakeModel", "aircraftIdentity", "routeFrom", "routeTo", "durationOfFlight", "singleEngineLand", "simulatorAtd", "landingsDay", "landingsNight", "groundTrainingReceived", "flightTrainingReceived", "crossCountry", "night", "solo", "pilotInCommand", "instrumentActual", "instrumentSimulated", "instrumentApproaches", "instrumentHolds", "instrumentNavTrack", "notes", "pilotId") SELECT "id", "date", "aircraftMakeModel", "aircraftIdentity", "routeFrom", "routeTo", "durationOfFlight", "singleEngineLand", "simulatorAtd", "landingsDay", "landingsNight", "groundTrainingReceived", "flightTrainingReceived", "crossCountry", "night", "solo", "pilotInCommand", "instrumentActual", "instrumentSimulated", "instrumentApproaches", "instrumentHolds", "instrumentNavTrack", "notes", "pilotId" FROM "logs"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "logs"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_logs" RENAME TO "logs"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "temporary_tracks" ("id" varchar PRIMARY KEY NOT NULL, "url" varchar NOT NULL, "order" integer NOT NULL, "logId" varchar, CONSTRAINT "FK_71881df31cfff2362e39accc4b2" FOREIGN KEY ("logId") REFERENCES "logs" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "temporary_tracks"("id", "url", "order", "logId") SELECT "id", "url", "order", "logId" FROM "tracks"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "tracks"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_tracks" RENAME TO "tracks"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "tracks" RENAME TO "temporary_tracks"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "tracks" ("id" varchar PRIMARY KEY NOT NULL, "url" varchar NOT NULL, "order" integer NOT NULL, "logId" varchar)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "tracks"("id", "url", "order", "logId") SELECT "id", "url", "order", "logId" FROM "temporary_tracks"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_tracks"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "logs" RENAME TO "temporary_logs"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "logs" ("id" varchar PRIMARY KEY NOT NULL, "date" datetime NOT NULL, "aircraftMakeModel" varchar NOT NULL, "aircraftIdentity" varchar NOT NULL, "routeFrom" varchar NOT NULL, "routeTo" varchar NOT NULL, "durationOfFlight" integer NOT NULL, "singleEngineLand" integer, "simulatorAtd" integer, "landingsDay" integer, "landingsNight" integer, "groundTrainingReceived" integer, "flightTrainingReceived" integer, "crossCountry" integer, "night" integer, "solo" integer, "pilotInCommand" integer, "instrumentActual" integer, "instrumentSimulated" integer, "instrumentApproaches" integer, "instrumentHolds" integer, "instrumentNavTrack" integer, "notes" varchar, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "logs"("id", "date", "aircraftMakeModel", "aircraftIdentity", "routeFrom", "routeTo", "durationOfFlight", "singleEngineLand", "simulatorAtd", "landingsDay", "landingsNight", "groundTrainingReceived", "flightTrainingReceived", "crossCountry", "night", "solo", "pilotInCommand", "instrumentActual", "instrumentSimulated", "instrumentApproaches", "instrumentHolds", "instrumentNavTrack", "notes", "pilotId") SELECT "id", "date", "aircraftMakeModel", "aircraftIdentity", "routeFrom", "routeTo", "durationOfFlight", "singleEngineLand", "simulatorAtd", "landingsDay", "landingsNight", "groundTrainingReceived", "flightTrainingReceived", "crossCountry", "night", "solo", "pilotInCommand", "instrumentActual", "instrumentSimulated", "instrumentApproaches", "instrumentHolds", "instrumentNavTrack", "notes", "pilotId" FROM "temporary_logs"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_logs"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "medical" RENAME TO "temporary_medical"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "medical" ("id" varchar PRIMARY KEY NOT NULL, "class" varchar NOT NULL, "expirationDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "medical"("id", "class", "expirationDate", "pilotId") SELECT "id", "class", "expirationDate", "pilotId" FROM "temporary_medical"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_medical"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "endorsements" RENAME TO "temporary_endorsements"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "endorsements" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "endorsements"("id", "type", "issueDate", "pilotId") SELECT "id", "type", "issueDate", "pilotId" FROM "temporary_endorsements"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_endorsements"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "certificates" RENAME TO "temporary_certificates"`);
|
||||||
|
await queryRunner.query(`CREATE TABLE "certificates" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar NOT NULL, "number" varchar NOT NULL, "issueDate" datetime NOT NULL, "pilotId" varchar)`);
|
||||||
|
await queryRunner.query(`INSERT INTO "certificates"("id", "type", "number", "issueDate", "pilotId") SELECT "id", "type", "number", "issueDate", "pilotId" FROM "temporary_certificates"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_certificates"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "tracks"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "logs"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "pilots"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "medical"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "endorsements"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "certificates"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,7 +16,11 @@
|
|||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
|
"typeorm": "npm run build && npx typeorm -d dist/config/typeorm-cli.config.js",
|
||||||
|
"migration:generate": "npm run typeorm -- migration:generate",
|
||||||
|
"migration:run": "npm run typeorm -- migration:run",
|
||||||
|
"migration:revert": "npm run typeorm -- migration:revert"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/storage-blob": "^12.27.0",
|
"@azure/storage-blob": "^12.27.0",
|
||||||
@@ -32,7 +36,7 @@
|
|||||||
"@noahspan/noahspan-modules": "^1.1.5",
|
"@noahspan/noahspan-modules": "^1.1.5",
|
||||||
"@schematics/angular": "^17.3.7",
|
"@schematics/angular": "^17.3.7",
|
||||||
"@types/multer": "^1.4.12",
|
"@types/multer": "^1.4.12",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.6.1",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"sqlite3": "^5.1.7",
|
"sqlite3": "^5.1.7",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
|||||||
import { AuthGuard, AuthModule, UserModule } from '@noahspan/noahspan-modules';
|
import { AuthGuard, AuthModule, UserModule } from '@noahspan/noahspan-modules';
|
||||||
import configuration from './config/configuration';
|
import configuration from './config/configuration';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { dataSourceOptions } from './config/typeorm-cli.config';
|
||||||
|
import { TrackModule } from './track/track.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -23,20 +25,14 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
|
isGlobal: true,
|
||||||
load: [configuration]
|
load: [configuration]
|
||||||
}),
|
}),
|
||||||
FeatureFlagModule,
|
FeatureFlagModule,
|
||||||
LogModule,
|
LogModule,
|
||||||
PilotModule,
|
PilotModule,
|
||||||
TypeOrmModule.forRootAsync({
|
TrackModule,
|
||||||
inject: [ConfigService],
|
TypeOrmModule.forRoot(dataSourceOptions),
|
||||||
useFactory: (configService: ConfigService) => ({
|
|
||||||
type: 'sqlite',
|
|
||||||
database: configService.get<string>('dbPath'),
|
|
||||||
entities: [__dirname + "/**/*.entity{.ts,.js}"],
|
|
||||||
synchronize: false
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
UserModule.registerAsync({
|
UserModule.registerAsync({
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
imports: [ConfigModule],
|
imports: [ConfigModule],
|
||||||
|
|||||||
0
api/src/certificate/certificate.controller.ts
Normal file
0
api/src/certificate/certificate.controller.ts
Normal file
0
api/src/certificate/certificate.dto.ts
Normal file
0
api/src/certificate/certificate.dto.ts
Normal file
0
api/src/certificate/certificate.module.ts
Normal file
0
api/src/certificate/certificate.module.ts
Normal file
0
api/src/certificate/certificate.service.ts
Normal file
0
api/src/certificate/certificate.service.ts
Normal file
@@ -1,6 +1,5 @@
|
|||||||
export default () => ({
|
export default () => ({
|
||||||
azureStorageConnectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
azureStorageConnectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
||||||
dbPath: process.env.DB_PATH,
|
|
||||||
clientId: process.env.CLIENT_ID,
|
clientId: process.env.CLIENT_ID,
|
||||||
clientSecret: process.env.CLIENT_SECRET,
|
clientSecret: process.env.CLIENT_SECRET,
|
||||||
tenantId: process.env.TENANT_ID
|
tenantId: process.env.TENANT_ID
|
||||||
|
|||||||
20
api/src/config/typeorm-cli.config.ts
Normal file
20
api/src/config/typeorm-cli.config.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||||
|
import { config } from 'dotenv';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import configuration from './configuration';
|
||||||
|
|
||||||
|
config();
|
||||||
|
|
||||||
|
const configService = new ConfigService();
|
||||||
|
|
||||||
|
export const dataSourceOptions: DataSourceOptions = {
|
||||||
|
type: 'sqlite',
|
||||||
|
database: configService.get<string>('DB_PATH'),
|
||||||
|
entities: ['dist/**/*.entity.js'],
|
||||||
|
migrations: ['dist/migrations/*.js'],
|
||||||
|
synchronize: configService.get<boolean>('DB_SYNC')
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataSource = new DataSource(dataSourceOptions);
|
||||||
|
|
||||||
|
export default dataSource;
|
||||||
65
api/src/endorsement/endorsement.controller.ts
Normal file
65
api/src/endorsement/endorsement.controller.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { Body, Controller, Delete, Get, HttpException, Param, Post, Put } from "@nestjs/common";
|
||||||
|
import { EndorsementService } from "./endorsement.service";
|
||||||
|
import { CustomError } from "@noahspan/noahspan-modules";
|
||||||
|
import { EndorsementDto } from "./endorsement.dto";
|
||||||
|
|
||||||
|
|
||||||
|
@Controller('endorsements')
|
||||||
|
export class EndorsementController {
|
||||||
|
constructor(private readonly endorsementService: EndorsementService) {}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
async find(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.endorsementService.find(id);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
async findAll() {
|
||||||
|
try {
|
||||||
|
return await this.endorsementService.findAll();
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
async create(@Body() endorsementDto: EndorsementDto) {
|
||||||
|
try {
|
||||||
|
return await this.endorsementService.create(endorsementDto);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
async update(@Param('id') id: string, @Body() endorsementDto: EndorsementDto) {
|
||||||
|
try {
|
||||||
|
return await this.endorsementService.update(id, endorsementDto);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
async delete(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.endorsementService.delete(id);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
api/src/endorsement/endorsement.dto.ts
Normal file
3
api/src/endorsement/endorsement.dto.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export class EndorsementDto {
|
||||||
|
|
||||||
|
}
|
||||||
0
api/src/endorsement/endorsement.module.ts
Normal file
0
api/src/endorsement/endorsement.module.ts
Normal file
32
api/src/endorsement/endorsement.service.ts
Normal file
32
api/src/endorsement/endorsement.service.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { EndorsementEntity } from "./endorsement.entity";
|
||||||
|
import { DeleteResult, InsertResult, Repository, UpdateResult } from 'typeorm';
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { EndorsementDto } from "./endorsement.dto";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EndorsementService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(EndorsementEntity) private readonly endorsementRepository: Repository<EndorsementEntity>
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async find(id: string): Promise<EndorsementEntity> {
|
||||||
|
return await this.endorsementRepository.findOneBy({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(): Promise<EndorsementEntity[]> {
|
||||||
|
return await this.endorsementRepository.find();
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(endorsement: EndorsementDto): Promise<InsertResult> {
|
||||||
|
return await this.endorsementRepository.insert(endorsement);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, endorsement: EndorsementDto): Promise<UpdateResult> {
|
||||||
|
return await this.endorsementRepository.update(id, endorsement);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: string): Promise<DeleteResult> {
|
||||||
|
return await this.endorsementRepository.delete({ id });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,10 +37,11 @@ import { ConfigService } from '@nestjs/config';
|
|||||||
return blockBlobClient;
|
return blockBlobClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadFile(file: Express.Multer.File, containerName: string, rowKey: string): Promise<string> {
|
async uploadFile(file: Express.Multer.File, containerName: string, logId: string): Promise<string> {
|
||||||
|
console.log(file)
|
||||||
this.containerName = containerName;
|
this.containerName = containerName;
|
||||||
|
|
||||||
const blockBlobClient = await this.getBlobClient(`${rowKey}/${file.originalname}`);
|
const blockBlobClient = await this.getBlobClient(`${logId}/${file.originalname}`);
|
||||||
const fileUrl = blockBlobClient.url;
|
const fileUrl = blockBlobClient.url;
|
||||||
|
|
||||||
await blockBlobClient.uploadData(file.buffer);
|
await blockBlobClient.uploadData(file.buffer);
|
||||||
|
|||||||
@@ -7,20 +7,17 @@ import {
|
|||||||
Param,
|
Param,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
|
||||||
StreamableFile,
|
|
||||||
UploadedFile,
|
|
||||||
UseGuards,
|
UseGuards,
|
||||||
UseInterceptors
|
UseInterceptors
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { LogDto } from './log.dto';
|
import { LogDto } from './log.dto';
|
||||||
import { Log } from './log.entity';
|
import { LogEntity } from './log.entity';
|
||||||
import { LogService } from './log.service';
|
import { LogService } from './log.service';
|
||||||
import { CustomError } from '../error/customError';
|
import { CustomError } from '../error/customError';
|
||||||
import { AuthGuard } from '@noahspan/noahspan-modules';
|
import { AuthGuard } from '@noahspan/noahspan-modules';
|
||||||
import { LogInterceptor } from './interceptors/log.interceptor';
|
import { LogInterceptor } from './interceptors/log.interceptor';
|
||||||
import { FileService } from '../file/file.service';
|
import { FileService } from '../file/file.service';
|
||||||
import { FileInterceptor } from '@nestjs/platform-express';
|
import { DeleteResult, InsertResult, UpdateResult } from 'typeorm';
|
||||||
|
|
||||||
@Controller('logs')
|
@Controller('logs')
|
||||||
export class LogController {
|
export class LogController {
|
||||||
@@ -30,14 +27,13 @@ export class LogController {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
@Get(':partitionKey/:rowKey')
|
@Get(':id')
|
||||||
@UseInterceptors(new LogInterceptor())
|
@UseInterceptors(new LogInterceptor())
|
||||||
async find(
|
async find(
|
||||||
@Param('partitionKey') partitionKey: string,
|
@Param('id') id: string,
|
||||||
@Param('rowKey') rowKey: string
|
): Promise<LogEntity> {
|
||||||
): Promise<Log> {
|
|
||||||
try {
|
try {
|
||||||
return await this.logService.find(partitionKey, rowKey);
|
return await this.logService.find(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -47,7 +43,7 @@ export class LogController {
|
|||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@UseInterceptors(new LogInterceptor())
|
@UseInterceptors(new LogInterceptor())
|
||||||
async findAll(): Promise<Log[]> {
|
async findAll(): Promise<LogEntity[]> {
|
||||||
try {
|
try {
|
||||||
return await this.logService.findAll();
|
return await this.logService.findAll();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -57,35 +53,26 @@ export class LogController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async create(@Body() logDto: LogDto): Promise<Log> {
|
async create(@Body() logDto: LogDto): Promise<InsertResult> {
|
||||||
try {
|
try {
|
||||||
const log = new Log();
|
return await this.logService.create(logDto);
|
||||||
|
|
||||||
Object.assign(log, logDto);
|
|
||||||
|
|
||||||
return await this.logService.create(log);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
console.log(error)
|
||||||
throw new HttpException(customError.message, customError.statusCode);
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Put(':partitionKey/:rowKey')
|
@Put(':id')
|
||||||
async update(
|
async update(
|
||||||
@Param('partitionKey') partitionKey: string,
|
@Param('id') id: string,
|
||||||
@Param('rowKey') rowKey: string,
|
|
||||||
@Body() logDto: LogDto
|
@Body() logDto: LogDto
|
||||||
): Promise<Log> {
|
): Promise<UpdateResult> {
|
||||||
try {
|
try {
|
||||||
const log = new Log();
|
return await this.logService.update(id, logDto);
|
||||||
|
|
||||||
Object.assign(log, logDto);
|
|
||||||
|
|
||||||
return await this.logService.update(partitionKey, rowKey, log);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -93,52 +80,13 @@ export class LogController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Delete(':partitionKey/:rowKey')
|
@Delete(':id')
|
||||||
async delete(
|
async delete(
|
||||||
@Param('partitionKey') partitionKey: string,
|
@Param('id') id: string,
|
||||||
@Param('rowKey') rowKey: string
|
): Promise<DeleteResult> {
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
return await this.logService.delete(partitionKey, rowKey);
|
return await this.logService.delete(id);
|
||||||
} catch (error) {
|
|
||||||
const customError = error as CustomError;
|
|
||||||
|
|
||||||
throw new HttpException(customError.message, customError.statusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
|
||||||
@Post(':partitionKey/:rowKey/track')
|
|
||||||
@UseInterceptors(FileInterceptor('file'))
|
|
||||||
async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) {
|
|
||||||
try {
|
|
||||||
const containerName = 'tracks';
|
|
||||||
const url = await this.fileService.uploadFile(file, containerName, rowKey);
|
|
||||||
|
|
||||||
return { url }
|
|
||||||
} catch (error) {
|
|
||||||
const customError = error as CustomError;
|
|
||||||
|
|
||||||
throw new HttpException(customError.message, customError.statusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get(':partitionKey/:rowKey/track')
|
|
||||||
async downloadTrack(@Param('rowKey') rowKey: string, @Query('fileName') fileName: string): Promise<string> {
|
|
||||||
const containerName = 'tracks';
|
|
||||||
const downloadedFile: string = await this.fileService.downloadFile(containerName, rowKey, fileName)
|
|
||||||
|
|
||||||
return downloadedFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
|
||||||
@Delete(':partitionKey/:rowKey/track')
|
|
||||||
async deleteTrack(@Param('rowKey') rowKey: string, @Query('fileName') fileName: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const containerName = 'tracks';
|
|
||||||
|
|
||||||
return await this.fileService.deleteFile(containerName, rowKey, fileName)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
|
import { PilotEntity } from "src/pilot/pilot.entity";
|
||||||
|
import { TrackEntity } from "src/track/track.entity";
|
||||||
|
|
||||||
export class LogDto {
|
export class LogDto {
|
||||||
pilotId: string;
|
pilotId: string;
|
||||||
pilotName: string;
|
date: Date;
|
||||||
date: string;
|
|
||||||
aircraftMakeModel: string;
|
aircraftMakeModel: string;
|
||||||
aircraftIdentity: string;
|
aircraftIdentity: string;
|
||||||
routeFrom: string;
|
routeFrom: string;
|
||||||
routeTo: string;
|
routeTo: string;
|
||||||
durationOfFlight: number;
|
durationOfFlight?: number;
|
||||||
singleEngineLand: string;
|
singleEngineLand?: number;
|
||||||
simulatorAtd: number;
|
simulatorAtd?: number;
|
||||||
landingsDay: number;
|
landingsDay?: number;
|
||||||
landingsNight: number;
|
landingsNight?: number;
|
||||||
instrumentActual: number;
|
instrumentActual?: number;
|
||||||
instrumentSimulated: number;
|
instrumentSimulated?: number;
|
||||||
instrumentApproaches: number;
|
instrumentApproaches?: number;
|
||||||
instrumentHolds: number;
|
instrumentHolds?: number;
|
||||||
instrumentNavTrack: number;
|
instrumentNavTrack?: number;
|
||||||
groundTrainingReceived: number;
|
groundTrainingReceived?: number;
|
||||||
flightTrainingReceived: number;
|
flightTrainingReceived?: number;
|
||||||
crossCountry: number;
|
crossCountry?: number;
|
||||||
night: number;
|
night?: number;
|
||||||
solo: number;
|
solo?: number;
|
||||||
pilotInCommand: number;
|
pilotInCommand?: number;
|
||||||
tracks: string[];
|
notes?: string;
|
||||||
notes: string;
|
pilot?: PilotEntity;
|
||||||
|
tracks?: TrackEntity[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
export class Log {
|
// export class Log {
|
||||||
partitionKey: string;
|
// partitionKey: string;
|
||||||
rowKey: string;
|
// rowKey: string;
|
||||||
pilotId: string;
|
// pilotId: string;
|
||||||
pilotName: string;
|
// pilotName: string;
|
||||||
date: string;
|
// date: string;
|
||||||
aircraftMakeModel: string;
|
// aircraftMakeModel: string;
|
||||||
aircraftIdentity: string;
|
// aircraftIdentity: string;
|
||||||
routeFrom: string;
|
// routeFrom: string;
|
||||||
routeTo: string;
|
// routeTo: string;
|
||||||
durationOfFlight: number | null;
|
// durationOfFlight: number | null;
|
||||||
singleEngineLand: number | null;
|
// singleEngineLand: number | null;
|
||||||
simulatorAtd?: number | null;
|
// simulatorAtd?: number | null;
|
||||||
landingsDay?: number | null;
|
// landingsDay?: number | null;
|
||||||
landingsNight?: number | null;
|
// landingsNight?: number | null;
|
||||||
groundTrainingReceived?: number;
|
// groundTrainingReceived?: number;
|
||||||
flightTrainingReceived?: number;
|
// flightTrainingReceived?: number;
|
||||||
crossCountry?: number | null;
|
// crossCountry?: number | null;
|
||||||
night?: number | null;
|
// night?: number | null;
|
||||||
solo?: number | null;
|
// solo?: number | null;
|
||||||
pilotInCommand?: number | null;
|
// pilotInCommand?: number | null;
|
||||||
instrumentActual?: number | null;
|
// instrumentActual?: number | null;
|
||||||
instrumentSimulated?: number | null;
|
// instrumentSimulated?: number | null;
|
||||||
instrumentApproaches?: number | null;
|
// instrumentApproaches?: number | null;
|
||||||
instrumentHolds?: number | null;
|
// instrumentHolds?: number | null;
|
||||||
instrumentNavTrack?: number | null;
|
// instrumentNavTrack?: number | null;
|
||||||
tracks?: string[];
|
// tracks?: string[];
|
||||||
notes?: string;
|
// notes?: string;
|
||||||
}
|
// }
|
||||||
|
|
||||||
import { PilotEntity } from 'src/pilot/pilot.entity';
|
import { PilotEntity } from 'src/pilot/pilot.entity';
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
import { TrackEntity } from 'src/track/track.entity';
|
||||||
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, OneToMany } from 'typeorm';
|
||||||
|
|
||||||
@Entity({ name: 'logs' })
|
@Entity({ name: 'logs' })
|
||||||
export class LogEntity {
|
export class LogEntity {
|
||||||
@@ -54,53 +55,56 @@ export class LogEntity {
|
|||||||
@Column()
|
@Column()
|
||||||
durationOfFlight: number;
|
durationOfFlight: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
singleEngineLand: number;
|
singleEngineLand: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
simulatorAtd: number;
|
simulatorAtd: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
landingsDay: number;
|
landingsDay: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
landingsNight: number;
|
landingsNight: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
groundTrainingReceived: number;
|
groundTrainingReceived: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
flightTrainingReceived: number;
|
flightTrainingReceived: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
crossCountry: number;
|
crossCountry: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
night: number;
|
night: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
solo: number;
|
solo: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
pilotInCommand: number;
|
pilotInCommand: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
instrumentActual: number;
|
instrumentActual: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
instrumentSimulated: number;
|
instrumentSimulated: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
instrumentApproaches: number;
|
instrumentApproaches: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
instrumentHolds: number;
|
instrumentHolds: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
instrumentNavTrack: number;
|
instrumentNavTrack: number | null;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
notes: string;
|
notes: string | null;
|
||||||
|
|
||||||
|
@OneToMany(() => TrackEntity, (track: TrackEntity) => track.log, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||||
|
tracks: TrackEntity[]
|
||||||
|
|
||||||
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.logs)
|
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.logs)
|
||||||
@JoinColumn({ name: 'pilotId' })
|
@JoinColumn({ name: 'pilotId' })
|
||||||
|
|||||||
@@ -1,28 +1,33 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { LogController } from './log.controller';
|
import { LogController } from './log.controller';
|
||||||
import { LogService } from './log.service';
|
import { LogService } from './log.service';
|
||||||
import { AzureTableStorageModule } from '@noahspan/azure-database';
|
// import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||||
import { Log } from './log.entity';
|
import { LogEntity } from './log.entity';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { FileService } from '../file/file.service';
|
import { FileService } from '../file/file.service';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { PilotModule } from 'src/pilot/pilot.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
AzureTableStorageModule.forRootAsync({
|
// AzureTableStorageModule.forRootAsync({
|
||||||
imports: [ConfigModule],
|
// imports: [ConfigModule],
|
||||||
useFactory: async (configService: ConfigService) => {
|
// useFactory: async (configService: ConfigService) => {
|
||||||
return {
|
// return {
|
||||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||||
};
|
// };
|
||||||
},
|
// },
|
||||||
inject: [ConfigService]
|
// inject: [ConfigService]
|
||||||
}),
|
// }),
|
||||||
AzureTableStorageModule.forFeature(Log, {
|
// AzureTableStorageModule.forFeature(Log, {
|
||||||
createTableIfNotExists: false,
|
// createTableIfNotExists: false,
|
||||||
table: 'logs'
|
// table: 'logs'
|
||||||
}),
|
// }),
|
||||||
|
PilotModule,
|
||||||
|
TypeOrmModule.forFeature([LogEntity])
|
||||||
],
|
],
|
||||||
controllers: [LogController],
|
controllers: [LogController],
|
||||||
|
exports: [LogService],
|
||||||
providers: [
|
providers: [
|
||||||
ConfigService,
|
ConfigService,
|
||||||
FileService,
|
FileService,
|
||||||
|
|||||||
@@ -1,34 +1,58 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository, Repository } from '@noahspan/azure-database';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Log } from './log.entity';
|
import { LogEntity } from './log.entity';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { DeleteResult, InsertResult, Repository, UpdateResult } from 'typeorm';
|
||||||
|
import { LogDto } from './log.dto';
|
||||||
|
import { PilotService } from 'src/pilot/pilot.service';
|
||||||
|
import { PilotEntity } from 'src/pilot/pilot.entity';
|
||||||
|
import { CustomError } from 'src/error/customError';
|
||||||
|
import { TrackService } from 'src/track/track.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LogService {
|
export class LogService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Log) private readonly logRepository: Repository<Log>
|
@InjectRepository(LogEntity) private readonly logRepository: Repository<LogEntity>,
|
||||||
|
private readonly pilotService: PilotService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async find(partitionKey: string, rowKey: string): Promise<Log> {
|
async find(id: string): Promise<LogEntity> {
|
||||||
return await this.logRepository.find(partitionKey, rowKey);
|
const logEntity: LogEntity = await this.logRepository.findOne({
|
||||||
|
where: { id: id },
|
||||||
|
relations: ['pilot', 'tracks']
|
||||||
|
});
|
||||||
|
console.log(logEntity);
|
||||||
|
return logEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<Log[]> {
|
async findAll(): Promise<LogEntity[]> {
|
||||||
return await this.logRepository.findAll();
|
return await this.logRepository.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(log: Log): Promise<Log> {
|
async create(logDto: LogDto): Promise<InsertResult> {
|
||||||
log.partitionKey = 'log';
|
try{
|
||||||
log.rowKey = uuidv4();
|
const pilotEntity: PilotEntity = await this.pilotService.find(logDto.pilotId);
|
||||||
|
|
||||||
return await this.logRepository.create(log);
|
if (pilotEntity) {
|
||||||
|
const { pilotId, ...newLogDto } = logDto;
|
||||||
|
const log = this.logRepository.create({
|
||||||
|
...newLogDto,
|
||||||
|
pilot: pilotEntity
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.logRepository.insert(log);
|
||||||
|
} else {
|
||||||
|
throw new CustomError('Pilot not found', 'Not found', 404);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(partitionKey: string, rowKey: string, log: Log): Promise<Log> {
|
async update(id: string, log: LogDto): Promise<UpdateResult> {
|
||||||
return await this.logRepository.update(partitionKey, rowKey, log);
|
return await this.logRepository.update(id, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(partitionKey: string, rowKey: string): Promise<void> {
|
async delete(id: string): Promise<DeleteResult> {
|
||||||
await this.logRepository.delete(partitionKey, rowKey);
|
return await this.logRepository.delete({ id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
71
api/src/medical/medical.controller.ts
Normal file
71
api/src/medical/medical.controller.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { Body, Controller, Delete, Get, HttpException, Param, Post, Put, UseGuards } from "@nestjs/common";
|
||||||
|
import { MedicalService } from "./medical.service";
|
||||||
|
import { CustomError } from "src/error/customError";
|
||||||
|
import { MedicalDto } from "./medical.dto";
|
||||||
|
import { AuthGuard } from "@noahspan/noahspan-modules";
|
||||||
|
|
||||||
|
|
||||||
|
@Controller('medical')
|
||||||
|
export class MedicalController {
|
||||||
|
constructor(private readonly medicalService: MedicalService) {}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Get(':id')
|
||||||
|
async find(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.medicalService.find(id)
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Get()
|
||||||
|
async findAll() {
|
||||||
|
try {
|
||||||
|
return await this.medicalService.findAll();
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Post()
|
||||||
|
async create(@Body() medicalDto: MedicalDto) {
|
||||||
|
try {
|
||||||
|
return await this.medicalService.create(medicalDto);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Put(':id')
|
||||||
|
async update(@Param('id') id: string, @Body() medicalDto: MedicalDto) {
|
||||||
|
try {
|
||||||
|
return await this.medicalService.update(id, medicalDto);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Delete(':id')
|
||||||
|
async delete(@Param('id') id: string) {
|
||||||
|
try {
|
||||||
|
return await this.medicalService.delete(id);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
api/src/medical/medical.dto.ts
Normal file
6
api/src/medical/medical.dto.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export class MedicalDto {
|
||||||
|
id: string;
|
||||||
|
class: string;
|
||||||
|
expirationDate: string;
|
||||||
|
pilotId: string;
|
||||||
|
}
|
||||||
0
api/src/medical/medical.module.ts
Normal file
0
api/src/medical/medical.module.ts
Normal file
33
api/src/medical/medical.service.ts
Normal file
33
api/src/medical/medical.service.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
import { MedicalEntity } from "./medical.entity";
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { DeleteResult, InsertResult, Repository, UpdateResult } from 'typeorm';
|
||||||
|
import { MedicalDto } from "./medical.dto";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MedicalService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(MedicalEntity) private readonly medicalRepository: Repository<MedicalEntity>
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async find(id: string): Promise<MedicalEntity> {
|
||||||
|
return await this.medicalRepository.findOneBy({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(): Promise<MedicalEntity[]> {
|
||||||
|
return await this.medicalRepository.find();
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(medical: MedicalDto): Promise<InsertResult> {
|
||||||
|
return await this.medicalRepository.insert(medical)
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, medical: MedicalDto): Promise<UpdateResult> {
|
||||||
|
return await this.medicalRepository.update(id, medical);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: string): Promise<DeleteResult> {
|
||||||
|
return await this.medicalRepository.delete({ id });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,24 +11,21 @@ import {
|
|||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { PilotDto } from './pilot.dto';
|
import { PilotDto } from './pilot.dto';
|
||||||
import { Pilot } from './pilot.entity';
|
import { PilotEntity } from './pilot.entity';
|
||||||
import { PilotService } from './pilot.service';
|
import { PilotService } from './pilot.service';
|
||||||
import { CustomError } from '../error/customError';
|
import { CustomError } from '../error/customError';
|
||||||
import { AuthGuard } from '@noahspan/noahspan-modules'
|
import { AuthGuard } from '@noahspan/noahspan-modules'
|
||||||
import { PilotInterceptor } from './interceptors/pilot.interceptor';
|
import { PilotInterceptor } from './interceptors/pilot.interceptor';
|
||||||
|
|
||||||
@Controller('pilots')
|
@Controller('pilots')
|
||||||
@UseInterceptors(new PilotInterceptor())
|
// @UseInterceptors(new PilotInterceptor())
|
||||||
export class PilotController {
|
export class PilotController {
|
||||||
constructor(private readonly pilotService: PilotService) {}
|
constructor(private readonly pilotService: PilotService) {}
|
||||||
|
|
||||||
@Get(':partitionKey/:rowKey')
|
@Get(':id')
|
||||||
async find(
|
async find(@Param('id') id: string) {
|
||||||
@Param('partitionKey') partitionKey: string,
|
|
||||||
@Param('rowKey') rowKey: string
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
return await this.pilotService.find(partitionKey, rowKey);
|
return await this.pilotService.find(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -47,30 +44,11 @@ export class PilotController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async create(@Body() pilotDto: PilotDto) {
|
async create(@Body() pilotDto: PilotDto) {
|
||||||
try {
|
try {
|
||||||
let pilot = new Pilot();
|
return await this.pilotService.create(pilotDto);
|
||||||
|
|
||||||
pilot = {
|
|
||||||
partitionKey: pilotDto.partitionKey,
|
|
||||||
rowKey: pilotDto.rowKey,
|
|
||||||
id: pilotDto.id,
|
|
||||||
name: pilotDto.name,
|
|
||||||
address: pilotDto.address,
|
|
||||||
city: pilotDto.city,
|
|
||||||
state: pilotDto.state,
|
|
||||||
postalCode: pilotDto.postalCode,
|
|
||||||
email: pilotDto.email,
|
|
||||||
phone: pilotDto.phone,
|
|
||||||
medicalClass: pilotDto.medicalClass,
|
|
||||||
medicalExpiration: pilotDto.medicalExpiration,
|
|
||||||
certificates: JSON.stringify(pilotDto.certificates),
|
|
||||||
endorsements: JSON.stringify(pilotDto.endorsements)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.pilotService.create(pilot);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -78,34 +56,14 @@ export class PilotController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Put(':partitionKey/:rowKey')
|
@Put(':id')
|
||||||
async update(
|
async update(
|
||||||
@Param('partitionKey') partitionKey: string,
|
@Param('id') id: string,
|
||||||
@Param('rowKey') rowKey: string,
|
|
||||||
@Body() pilotDto: PilotDto
|
@Body() pilotDto: PilotDto
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
let pilot = new Pilot();
|
return await this.pilotService.update(id, pilotDto);
|
||||||
|
|
||||||
pilot = {
|
|
||||||
partitionKey: pilotDto.partitionKey,
|
|
||||||
rowKey: pilotDto.rowKey,
|
|
||||||
id: pilotDto.id,
|
|
||||||
name: pilotDto.name,
|
|
||||||
address: pilotDto.address,
|
|
||||||
city: pilotDto.city,
|
|
||||||
state: pilotDto.state,
|
|
||||||
postalCode: pilotDto.postalCode,
|
|
||||||
email: pilotDto.email,
|
|
||||||
phone: pilotDto.phone,
|
|
||||||
medicalClass: pilotDto.medicalClass,
|
|
||||||
medicalExpiration: pilotDto.medicalExpiration,
|
|
||||||
certificates: JSON.stringify(pilotDto.certificates),
|
|
||||||
endorsements: JSON.stringify(pilotDto.endorsements)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.pilotService.update(partitionKey, rowKey, pilot);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -113,14 +71,13 @@ export class PilotController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
// @UseGuards(AuthGuard)
|
||||||
@Delete(':partitionKey/:rowKey')
|
@Delete(':id')
|
||||||
async delete(
|
async delete(
|
||||||
@Param('partitionKey') partitionKey: string,
|
@Param('id') id: string,
|
||||||
@Param('rowKey') rowKey: string
|
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
return await this.pilotService.delete(partitionKey, rowKey);
|
return await this.pilotService.delete(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { Certificate } from "./certificate/certificate.entity";
|
import { LogEntity } from "src/log/log.entity";
|
||||||
import { Endorsement } from "./endorsement/endorsement.entity";
|
|
||||||
|
|
||||||
export class PilotDto {
|
export class PilotDto {
|
||||||
partitionKey: string;
|
|
||||||
rowKey: string;
|
|
||||||
id: string;
|
|
||||||
name: string;
|
name: string;
|
||||||
address: string;
|
address: string;
|
||||||
city: string;
|
city: string;
|
||||||
@@ -12,8 +8,4 @@ export class PilotDto {
|
|||||||
postalCode: string;
|
postalCode: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
medicalClass?: string;
|
|
||||||
medicalExpiration?: string;
|
|
||||||
certificates: Certificate;
|
|
||||||
endorsements: Endorsement
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,44 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { PilotController } from './pilot.controller';
|
import { PilotController } from './pilot.controller';
|
||||||
import { PilotService } from './pilot.service';
|
import { PilotService } from './pilot.service';
|
||||||
import { AzureTableStorageModule } from '@noahspan/azure-database';
|
// import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||||
import { Pilot } from './pilot.entity';
|
import { PilotEntity } from './pilot.entity';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
// import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { Log } from 'src/log/log.entity';
|
// import { Log } from 'src/log/log.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
AzureTableStorageModule.forRootAsync({
|
// AzureTableStorageModule.forRootAsync({
|
||||||
imports: [ConfigModule],
|
// imports: [ConfigModule],
|
||||||
useFactory: async (configService: ConfigService) => {
|
// useFactory: async (configService: ConfigService) => {
|
||||||
return {
|
// return {
|
||||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||||
};
|
// };
|
||||||
},
|
// },
|
||||||
inject: [ConfigService]
|
// inject: [ConfigService]
|
||||||
}),
|
// }),
|
||||||
AzureTableStorageModule.forFeature(Log, {
|
// AzureTableStorageModule.forFeature(Log, {
|
||||||
createTableIfNotExists: false,
|
// createTableIfNotExists: false,
|
||||||
table: 'logs'
|
// table: 'logs'
|
||||||
}),
|
// }),
|
||||||
AzureTableStorageModule.forRootAsync({
|
// AzureTableStorageModule.forRootAsync({
|
||||||
imports: [ConfigModule],
|
// imports: [ConfigModule],
|
||||||
useFactory: async (configService: ConfigService) => {
|
// useFactory: async (configService: ConfigService) => {
|
||||||
return {
|
// return {
|
||||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||||
};
|
// };
|
||||||
},
|
// },
|
||||||
inject: [ConfigService]
|
// inject: [ConfigService]
|
||||||
}),
|
// }),
|
||||||
AzureTableStorageModule.forFeature(Pilot, {
|
// AzureTableStorageModule.forFeature(PilotEntity, {
|
||||||
createTableIfNotExists: false,
|
// createTableIfNotExists: false,
|
||||||
table: 'pilots'
|
// table: 'pilots'
|
||||||
})
|
// }),
|
||||||
|
TypeOrmModule.forFeature([PilotEntity])
|
||||||
],
|
],
|
||||||
controllers: [PilotController],
|
controllers: [PilotController],
|
||||||
|
exports: [PilotService],
|
||||||
providers: [PilotService]
|
providers: [PilotService]
|
||||||
})
|
})
|
||||||
export class PilotModule {}
|
export class PilotModule {}
|
||||||
|
|||||||
@@ -1,54 +1,46 @@
|
|||||||
import { InjectRepository, Repository } from '@noahspan/azure-database';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { PilotEntity } from './pilot.entity';
|
||||||
import { Pilot } from './pilot.entity';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Log } from 'src/log/log.entity';
|
import { DeleteResult, InsertResult, Repository, UpdateResult } from 'typeorm';
|
||||||
import { LogService } from 'src/log/log.service';
|
import { PilotDto } from './pilot.dto';
|
||||||
|
import { CustomError } from 'src/error/customError';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PilotService {
|
export class PilotService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Pilot) private readonly pilotRepository: Repository<Pilot>,
|
@InjectRepository(PilotEntity) private readonly pilotRepository: Repository<PilotEntity>
|
||||||
@InjectRepository(Log) private readonly logRepository: Repository<Log>
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async find(partitionKey: string, rowKey: string): Promise<Pilot> {
|
async find(id: string): Promise<PilotEntity> {
|
||||||
return await this.pilotRepository.find(partitionKey, rowKey);
|
try {
|
||||||
|
const pilotEntity = await this.pilotRepository.findOneBy({ id });
|
||||||
|
|
||||||
|
if (pilotEntity) {
|
||||||
|
return pilotEntity
|
||||||
|
} else {
|
||||||
|
throw new CustomError('Pilot not found', 'Not found', 404)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<Pilot[]> {
|
async findAll(): Promise<PilotEntity[]> {
|
||||||
return await this.pilotRepository.findAll();
|
return await this.pilotRepository.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(pilot: Pilot): Promise<Pilot> {
|
async create(pilot: PilotDto): Promise<InsertResult> {
|
||||||
// try {
|
return await this.pilotRepository.insert(pilot);
|
||||||
// return await this.pilotRepository.create(pilot);
|
|
||||||
// } catch (error) {
|
|
||||||
// throw new Error(error);
|
|
||||||
// }
|
|
||||||
return await this.pilotRepository.create(pilot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(
|
async update(
|
||||||
partitionKey: string,
|
id: string,
|
||||||
rowKey: string,
|
pilot: PilotDto
|
||||||
pilot: Pilot
|
): Promise<UpdateResult> {
|
||||||
): Promise<Pilot> {
|
return await this.pilotRepository.update(id, pilot);
|
||||||
return await this.pilotRepository.update(partitionKey, rowKey, pilot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(partitionKey: string, rowKey: string): Promise<void> {
|
async delete(id: string): Promise<DeleteResult> {
|
||||||
const pilotLogs: Log[] = await this.logRepository.findAll({
|
return await this.pilotRepository.delete({ id });
|
||||||
queryOptions: {
|
|
||||||
filter: `pilotId eq '${rowKey}'`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const pilotLog of pilotLogs) {
|
|
||||||
await this.logRepository.delete(pilotLog.partitionKey, pilotLog.rowKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.pilotRepository.delete(partitionKey, rowKey);
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
133
api/src/track/track.controller.ts
Normal file
133
api/src/track/track.controller.ts
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
HttpException,
|
||||||
|
Param,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Query,
|
||||||
|
UploadedFile,
|
||||||
|
UseGuards,
|
||||||
|
UseInterceptors
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@noahspan/noahspan-modules';
|
||||||
|
import { CustomError } from '../error/customError';
|
||||||
|
import { FileInterceptor } from '@nestjs/platform-express';
|
||||||
|
import { FileService } from '../file/file.service';
|
||||||
|
import { TrackService } from './track.service';
|
||||||
|
import { TrackEntity } from './track.entity';
|
||||||
|
import { TrackDto } from './track.dto';
|
||||||
|
import { DeleteResult, InsertResult, UpdateResult } from 'typeorm';
|
||||||
|
|
||||||
|
@Controller('tracks')
|
||||||
|
export class TrackController {
|
||||||
|
constructor(
|
||||||
|
private readonly fileService: FileService,
|
||||||
|
private readonly trackService: TrackService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
// @Get('id')
|
||||||
|
// async fin(@Param('id') id: string): Promise<TrackEntity> {
|
||||||
|
// try {
|
||||||
|
// return await this.trackService.find(id);
|
||||||
|
// } catch (error) {
|
||||||
|
// const customError = error as CustomError;
|
||||||
|
|
||||||
|
// throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Get()
|
||||||
|
// async findAdd(): Promise<TrackEntity[]> {
|
||||||
|
// try {
|
||||||
|
// return await this.trackService.findAll();
|
||||||
|
// } catch (error) {
|
||||||
|
// const customError = error as CustomError;
|
||||||
|
|
||||||
|
// throw new HttpException(customError.message, customError.statusCode)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Post(':logId/:order')
|
||||||
|
async create(@Param('logId') logId: string, @Param('order') order: number, @UploadedFile() file: Express.Multer.File): Promise<InsertResult> {
|
||||||
|
try {
|
||||||
|
console.log(file)
|
||||||
|
return await this.trackService.create(logId, order, file);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Put(':id')
|
||||||
|
// async update(@Param('id') id: string, @Body() trackDto: TrackDto): Promise<UpdateResult> {
|
||||||
|
// try {
|
||||||
|
// return await this.trackService.update(id, trackDto);
|
||||||
|
// } catch (error) {
|
||||||
|
// const customError = error as CustomError;
|
||||||
|
|
||||||
|
// throw new HttpException(customError.message, customError.statusCode)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
async delete(@Param('id') id: string): Promise<DeleteResult> {
|
||||||
|
try {
|
||||||
|
return await this.trackService.delete(id);
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Post(':partitionKey/:rowKey/track')
|
||||||
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
|
async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) {
|
||||||
|
try {
|
||||||
|
const containerName = 'tracks';
|
||||||
|
const url = await this.fileService.uploadFile(file, containerName, rowKey);
|
||||||
|
|
||||||
|
return { url }
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':partitionKey/:rowKey/track')
|
||||||
|
async downloadTrack(@Param('rowKey') rowKey: string, @Query('fileName') fileName: string): Promise<string> {
|
||||||
|
const containerName = 'tracks';
|
||||||
|
const downloadedFile: string = await this.fileService.downloadFile(containerName, rowKey, fileName)
|
||||||
|
|
||||||
|
return downloadedFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Delete(':partitionKey/:rowKey/track')
|
||||||
|
async deleteTrack(@Param('rowKey') rowKey: string, @Query('fileName') fileName: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const containerName = 'tracks';
|
||||||
|
|
||||||
|
return await this.fileService.deleteFile(containerName, rowKey, fileName)
|
||||||
|
} catch (error) {
|
||||||
|
const customError = error as CustomError;
|
||||||
|
|
||||||
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
5
api/src/track/track.dto.ts
Normal file
5
api/src/track/track.dto.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class TrackDto {
|
||||||
|
logId: string;
|
||||||
|
order: number;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
18
api/src/track/track.entity.ts
Normal file
18
api/src/track/track.entity.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { LogEntity } from 'src/log/log.entity';
|
||||||
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tracks' })
|
||||||
|
export class TrackEntity {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
url: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
order: number;
|
||||||
|
|
||||||
|
@ManyToOne(() => LogEntity, (log: LogEntity) => log.tracks)
|
||||||
|
@JoinColumn({ name: 'logId' })
|
||||||
|
log: LogEntity;
|
||||||
|
}
|
||||||
20
api/src/track/track.module.ts
Normal file
20
api/src/track/track.module.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
|
import { TrackEntity } from "./track.entity";
|
||||||
|
import { TrackController } from "./track.controller";
|
||||||
|
import { FileService } from "../file/file.service";
|
||||||
|
import { TrackService } from './track.service';
|
||||||
|
import { LogModule } from 'src/log/log.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
LogModule,
|
||||||
|
TypeOrmModule.forFeature([TrackEntity])
|
||||||
|
],
|
||||||
|
controllers: [TrackController],
|
||||||
|
providers: [
|
||||||
|
FileService,
|
||||||
|
TrackService
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TrackModule {}
|
||||||
88
api/src/track/track.service.ts
Normal file
88
api/src/track/track.service.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { DeleteResult, InsertResult, Repository, UpdateResult } from "typeorm";
|
||||||
|
import { TrackDto } from "./track.dto";
|
||||||
|
import { TrackEntity } from "./track.entity";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { LogService } from "src/log/log.service";
|
||||||
|
import { LogEntity } from "src/log/log.entity";
|
||||||
|
import { CustomError } from "src/error/customError";
|
||||||
|
import { FileService } from "src/file/file.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TrackService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(TrackEntity) private readonly trackRepository: Repository<TrackEntity>,
|
||||||
|
private readonly fileService: FileService,
|
||||||
|
private readonly logService: LogService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
// async find(id: string): Promise<TrackEntity> {
|
||||||
|
// return await this.trackRepository.findOneBy({ id });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async findAll(logId: string): Promise<TrackEntity[]> {
|
||||||
|
// try {
|
||||||
|
// await this.trackRepository.findOneBy({ })
|
||||||
|
// } catch (error) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
async create(logId: string, order: number, file: Express.Multer.File): Promise<InsertResult> {
|
||||||
|
try {
|
||||||
|
const logEntity: LogEntity = await this.logService.find(logId);
|
||||||
|
|
||||||
|
if (logEntity) {
|
||||||
|
const containerName = 'tracks';
|
||||||
|
const url = await this.fileService.uploadFile(file, containerName, logId);
|
||||||
|
const track = this.trackRepository.create({
|
||||||
|
log: logEntity,
|
||||||
|
order: order,
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
|
||||||
|
return await this.trackRepository.insert(track);
|
||||||
|
} else {
|
||||||
|
throw new CustomError('Log not found', 'Not found', 404)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async update(id: string, track: TrackDto): Promise<UpdateResult> {
|
||||||
|
// return await this.trackRepository.update(id, track);
|
||||||
|
// }
|
||||||
|
|
||||||
|
async delete(id: string): Promise<DeleteResult> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return await this.trackRepository.delete({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// async createTrack()
|
||||||
|
|
||||||
|
// async downloadTrack(): Promise<string> {
|
||||||
|
// const containerName = 'tracks';
|
||||||
|
// const downloadedFile: string = await this.fileService.downloadFile(containerName, rowKey, fileName);
|
||||||
|
|
||||||
|
// return downloadedFile;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async deleteTrack(): Promsie<void> {
|
||||||
|
// try {
|
||||||
|
// const containerName = 'tracks';
|
||||||
|
|
||||||
|
// return await this.fileService.deleteFile(containerName, rowKey, fileName)
|
||||||
|
// } catch (error) {
|
||||||
|
// const customError = error as CustomError;
|
||||||
|
|
||||||
|
// throw customError;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -12,15 +12,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/msal-browser": "^4.0.1",
|
"@azure/msal-browser": "^4.0.1",
|
||||||
"@azure/msal-react": "^3.0.1",
|
"@azure/msal-react": "3.0.1",
|
||||||
"@noahspan/noahspan-components": "^1.9.1",
|
"@noahspan/noahspan-components": "^1.9.1",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"react": "19.0.0-rc.1",
|
"react": "^18",
|
||||||
"react-dom": "19.0.0-rc.1",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.51.4",
|
"react-hook-form": "^7.51.4",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^4",
|
||||||
"react-leaflet-kml": "^2.1.2",
|
"react-leaflet-kml": "^2.1.2",
|
||||||
"react-router-dom": "^6.23.0",
|
"react-router-dom": "^6.23.0",
|
||||||
"swiper": "^11.2.6"
|
"swiper": "^11.2.6"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
|
|
||||||
export interface ILogFormProps {
|
export interface ILogFormProps {
|
||||||
entryId?: string;
|
logId?: string;
|
||||||
isDrawerOpen: boolean;
|
isDrawerOpen: boolean;
|
||||||
mode: FormMode;
|
mode: FormMode;
|
||||||
onOpenClose: (mode: FormMode) => void;
|
onOpenClose: (mode: FormMode) => void;
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ export interface ILogFormState {
|
|||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
pilotOptions: { label: string; value: string }[];
|
pilotOptions: { label: string; value: string }[];
|
||||||
selectedEntryPilotName: string;
|
selectedPilotName: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { FormMode } from '../../enums/formMode';
|
|||||||
import { usePilots } from '../../hooks/pilots/UsePilots';
|
import { usePilots } from '../../hooks/pilots/UsePilots';
|
||||||
|
|
||||||
const LogForm: React.FC<ILogFormProps> = ({
|
const LogForm: React.FC<ILogFormProps> = ({
|
||||||
entryId,
|
logId,
|
||||||
isDrawerOpen,
|
isDrawerOpen,
|
||||||
mode,
|
mode,
|
||||||
onOpenClose
|
onOpenClose
|
||||||
@@ -39,7 +39,6 @@ const LogForm: React.FC<ILogFormProps> = ({
|
|||||||
const isAuthenticated = useIsAuthenticated();
|
const isAuthenticated = useIsAuthenticated();
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
pilotId: '',
|
pilotId: '',
|
||||||
pilotName: '',
|
|
||||||
date: null,
|
date: null,
|
||||||
aircraftMakeModel: '',
|
aircraftMakeModel: '',
|
||||||
aircraftIdentity: '',
|
aircraftIdentity: '',
|
||||||
@@ -79,14 +78,14 @@ const LogForm: React.FC<ILogFormProps> = ({
|
|||||||
|
|
||||||
const accessToken: string = await getAccessToken();
|
const accessToken: string = await getAccessToken();
|
||||||
|
|
||||||
if (!entryId) {
|
if (!logId) {
|
||||||
await httpClient.post(`api/logs`, data, {
|
await httpClient.post(`api/logs`, data, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: accessToken
|
Authorization: accessToken
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await httpClient.put(`api/logs/log/${entryId}`, data, {
|
await httpClient.put(`api/logs/${logId}`, data, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: accessToken
|
Authorization: accessToken
|
||||||
}
|
}
|
||||||
@@ -120,21 +119,13 @@ const LogForm: React.FC<ILogFormProps> = ({
|
|||||||
? { headers: { Authorization: await getAccessToken() } }
|
? { headers: { Authorization: await getAccessToken() } }
|
||||||
: {};
|
: {};
|
||||||
const response: AxiosResponse = await httpClient.get(
|
const response: AxiosResponse = await httpClient.get(
|
||||||
`api/logs/log/${entryId}`,
|
`api/logs/${logId}`,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
const entry = response.data;
|
const log = response.data;
|
||||||
|
|
||||||
// if (mode !== FormMode.ADD) {
|
log.pilotId = log.pilot.id
|
||||||
// const pilot = pilots?.find((pilot) => pilot.id === entry.pilotId);
|
methods.reset(log);
|
||||||
// console.log(pilot.name)
|
|
||||||
// dispatch({
|
|
||||||
// type: 'SET_SELECTED_ENTRY_PILOT_NAME',
|
|
||||||
// payload: pilot.name
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
methods.reset(entry);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const axiosError = error as AxiosError;
|
const axiosError = error as AxiosError;
|
||||||
|
|
||||||
@@ -144,10 +135,10 @@ const LogForm: React.FC<ILogFormProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (entryId && isDrawerOpen) {
|
if (logId && isDrawerOpen) {
|
||||||
getEntry();
|
getEntry();
|
||||||
}
|
}
|
||||||
}, [entryId]);
|
}, [logId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (pilots && FormMode.ADD) {
|
if (pilots && FormMode.ADD) {
|
||||||
@@ -214,10 +205,6 @@ const LogForm: React.FC<ILogFormProps> = ({
|
|||||||
(pilot) => (pilot.id = event.target.value)
|
(pilot) => (pilot.id = event.target.value)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pilot) {
|
|
||||||
methods.setValue('pilotName', pilot.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
methods.setValue('pilotId', event.target.value);
|
methods.setValue('pilotId', event.target.value);
|
||||||
}}
|
}}
|
||||||
options={
|
options={
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ type Action =
|
|||||||
| { type: 'SET_IS_DISABLED'; payload: boolean }
|
| { type: 'SET_IS_DISABLED'; payload: boolean }
|
||||||
| { type: 'SET_IS_LOADING'; payload: boolean }
|
| { type: 'SET_IS_LOADING'; payload: boolean }
|
||||||
| { type: 'SET_PILOT_OPTIONS'; payload: { label: string; value: string }[] }
|
| { type: 'SET_PILOT_OPTIONS'; payload: { label: string; value: string }[] }
|
||||||
| { type: 'SET_SELECTED_ENTRY_PILOT_NAME'; payload: string };
|
| { type: 'SET_SELECTED_PILOT_NAME'; payload: string };
|
||||||
|
|
||||||
export const initialState: ILogFormState = {
|
export const initialState: ILogFormState = {
|
||||||
alert: undefined,
|
alert: undefined,
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
pilotOptions: [],
|
pilotOptions: [],
|
||||||
selectedEntryPilotName: ''
|
selectedPilotName: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
export const reducer = (
|
export const reducer = (
|
||||||
@@ -45,10 +45,10 @@ export const reducer = (
|
|||||||
pilotOptions: action.payload
|
pilotOptions: action.payload
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SET_SELECTED_ENTRY_PILOT_NAME': {
|
case 'SET_SELECTED_PILOT_NAME': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
selectedEntryPilotName: action.payload
|
selectedPilotName: action.payload
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
|
|
||||||
const getLog = async (): Promise<ILogbookEntry> => {
|
const getLog = async (): Promise<ILogbookEntry> => {
|
||||||
const logResponse: AxiosResponse = await httpClient.get(
|
const logResponse: AxiosResponse = await httpClient.get(
|
||||||
`api/logs/log/${selectedRowKey}`,
|
`api/logs/${selectedRowKey}`,
|
||||||
await getConfig()
|
await getConfig()
|
||||||
);
|
);
|
||||||
const logData: ILogbookEntry = logResponse.data;
|
const logData: ILogbookEntry = logResponse.data;
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import { ColumnDef } from "@noahspan/noahspan-components";
|
|
||||||
|
|
||||||
export interface ILogbookEntry {
|
export interface ILogbookEntry {
|
||||||
partitionKey: string;
|
|
||||||
rowKey: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
pilotId: string;
|
pilotId: string;
|
||||||
pilotName: string;
|
pilotName: string;
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ export interface ILogbookState {
|
|||||||
isFormOpen: boolean;
|
isFormOpen: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
isTracksOpen: boolean;
|
isTracksOpen: boolean;
|
||||||
selectedEntryId: string | undefined;
|
selectedLogId: string | undefined;
|
||||||
tracksMode: FormMode;
|
tracksMode: FormMode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
},
|
},
|
||||||
cell: (info: any) => (
|
cell: (info: any) => (
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
id={info.row.original.rowKey}
|
id={info.row.original.id}
|
||||||
onDelete={onDeleteEntry}
|
onDelete={onDeleteLog}
|
||||||
onOpenCloseForm={onOpenCloseEntryForm}
|
onOpenCloseForm={onOpenCloseLogForm}
|
||||||
onOpenCloseTracks={onOpenCloseTracks}
|
onOpenCloseTracks={onOpenCloseTracks}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -94,16 +94,16 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpenCloseEntryForm = (mode: FormMode, entryId?: string) => {
|
const onOpenCloseLogForm = (mode: FormMode, logId?: string) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FormMode.ADD:
|
case FormMode.ADD:
|
||||||
case FormMode.EDIT:
|
case FormMode.EDIT:
|
||||||
case FormMode.VIEW:
|
case FormMode.VIEW:
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM',
|
type: 'SET_OPEN_CLOSE_LOG_FORM',
|
||||||
payload: {
|
payload: {
|
||||||
formMode: mode,
|
formMode: mode,
|
||||||
selectedEntryId: entryId,
|
selectedLogId: logId,
|
||||||
isFormOpen: true
|
isFormOpen: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -111,10 +111,10 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
break;
|
break;
|
||||||
case FormMode.CANCEL:
|
case FormMode.CANCEL:
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM',
|
type: 'SET_OPEN_CLOSE_LOG_FORM',
|
||||||
payload: {
|
payload: {
|
||||||
formMode: mode,
|
formMode: mode,
|
||||||
selectedEntryId: undefined,
|
selectedLogId: undefined,
|
||||||
isFormOpen: false
|
isFormOpen: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -151,10 +151,10 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDeleteEntry = (entryId: string) => {
|
const onDeleteLog = (logId: string) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_DELETE',
|
type: 'SET_DELETE',
|
||||||
payload: { isConfirmationDialogOpen: true, selectedEntryId: entryId }
|
payload: { isConfirmationDialogOpen: true, selectedLogId: logId }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
? { headers: { Authorization: `${token}` } }
|
? { headers: { Authorization: `${token}` } }
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
await httpClient.delete(`api/logs/log/${state.selectedEntryId}`, config);
|
await httpClient.delete(`api/logs/${state.selectedLogId}`, config);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_DELETE',
|
type: 'SET_DELETE',
|
||||||
payload: { isConfirmationDialogOpen: false, selectedEntryId: undefined }
|
payload: { isConfirmationDialogOpen: false, selectedLogId: undefined }
|
||||||
});
|
});
|
||||||
await getLogbookEntries();
|
await getLogbookEntries();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -189,7 +189,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
const onConfirmationDialogCancel = () => {
|
const onConfirmationDialogCancel = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_DELETE',
|
type: 'SET_DELETE',
|
||||||
payload: { isConfirmationDialogOpen: false, selectedEntryId: undefined }
|
payload: { isConfirmationDialogOpen: false, selectedLogId: undefined }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
<Grid display="flex" justifyContent="right" size={isMedium ? 1 : 6}>
|
<Grid display="flex" justifyContent="right" size={isMedium ? 1 : 6}>
|
||||||
{isAuthenticated &&
|
{isAuthenticated &&
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onOpenCloseEntryForm(FormMode.ADD)}
|
onClick={() => onOpenCloseLogForm(FormMode.ADD)}
|
||||||
startIcon={<Icon iconName={IconName.PLUS} />}
|
startIcon={<Icon iconName={IconName.PLUS} />}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
data-testid="pilot-add-button"
|
data-testid="pilot-add-button"
|
||||||
@@ -261,7 +261,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
<Table columns={state.columns} data={state.entries} />
|
<Table columns={state.columns} data={state.entries} />
|
||||||
)}
|
)}
|
||||||
{!isMedium && state.entries.length > 0 &&
|
{!isMedium && state.entries.length > 0 &&
|
||||||
<LogbookCard logs={state.entries} onDelete={onDeleteEntry} mode='logbook' onOpenCloseForm={onOpenCloseEntryForm} />
|
<LogbookCard logs={state.entries} onDelete={onDeleteLog} mode='logbook' onOpenCloseForm={onOpenCloseLogForm} />
|
||||||
}
|
}
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
@@ -278,10 +278,10 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
{state.isFormOpen && (
|
{state.isFormOpen && (
|
||||||
<LogForm
|
<LogForm
|
||||||
entryId={state.selectedEntryId}
|
logId={state.selectedLogId}
|
||||||
isDrawerOpen={state.isFormOpen}
|
isDrawerOpen={state.isFormOpen}
|
||||||
mode={state.formMode}
|
mode={state.formMode}
|
||||||
onOpenClose={(mode) => onOpenCloseEntryForm(mode)}
|
onOpenClose={(mode) => onOpenCloseLogForm(mode)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{state.isConfirmDialogOpen && (
|
{state.isConfirmDialogOpen && (
|
||||||
@@ -299,7 +299,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
isDrawerOpen={state.isTracksOpen}
|
isDrawerOpen={state.isTracksOpen}
|
||||||
mode={state.tracksMode}
|
mode={state.tracksMode}
|
||||||
onOpenClose={(mode) => onOpenCloseTracks(mode)}
|
onOpenClose={(mode) => onOpenCloseTracks(mode)}
|
||||||
selectedRowKey={state.selectedEntryId}
|
selectedRowKey={state.selectedLogId}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ type Action =
|
|||||||
type: 'SET_DELETE';
|
type: 'SET_DELETE';
|
||||||
payload: {
|
payload: {
|
||||||
isConfirmationDialogOpen: boolean;
|
isConfirmationDialogOpen: boolean;
|
||||||
selectedEntryId: string | undefined;
|
selectedLogId: string | undefined;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| { type: 'SET_ENTRIES'; payload: ILogbookEntry[] }
|
| { type: 'SET_ENTRIES'; payload: ILogbookEntry[] }
|
||||||
@@ -19,10 +19,10 @@ type Action =
|
|||||||
| { type: 'SET_IS_CONFIRMATION_DIALOG_LOADING'; payload: boolean }
|
| { type: 'SET_IS_CONFIRMATION_DIALOG_LOADING'; payload: boolean }
|
||||||
| { type: 'SET_IS_LOADING'; payload: boolean }
|
| { type: 'SET_IS_LOADING'; payload: boolean }
|
||||||
| {
|
| {
|
||||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM';
|
type: 'SET_OPEN_CLOSE_LOG_FORM';
|
||||||
payload: {
|
payload: {
|
||||||
formMode: FormMode;
|
formMode: FormMode;
|
||||||
selectedEntryId: string | undefined;
|
selectedLogId: string | undefined;
|
||||||
isFormOpen: boolean;
|
isFormOpen: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ export const initialState: ILogbookState = {
|
|||||||
isFormOpen: false,
|
isFormOpen: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isTracksOpen: false,
|
isTracksOpen: false,
|
||||||
selectedEntryId: undefined,
|
selectedLogId: undefined,
|
||||||
tracksMode: FormMode.CANCEL
|
tracksMode: FormMode.CANCEL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export const reducer = (
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isConfirmDialogOpen: action.payload.isConfirmationDialogOpen,
|
isConfirmDialogOpen: action.payload.isConfirmationDialogOpen,
|
||||||
selectedEntryId: action.payload.selectedEntryId
|
selectedLogId: action.payload.selectedLogId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SET_ENTRIES': {
|
case 'SET_ENTRIES': {
|
||||||
@@ -90,12 +90,12 @@ export const reducer = (
|
|||||||
isLoading: action.payload
|
isLoading: action.payload
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SET_OPEN_CLOSE_ENTRY_FORM': {
|
case 'SET_OPEN_CLOSE_LOG_FORM': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
formMode: action.payload.formMode,
|
formMode: action.payload.formMode,
|
||||||
isFormOpen: action.payload.isFormOpen,
|
isFormOpen: action.payload.isFormOpen,
|
||||||
selectedEntryId: action.payload.selectedEntryId
|
selectedLogId: action.payload.selectedLogId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SET_OPEN_CLOSE_TRACKS': {
|
case 'SET_OPEN_CLOSE_TRACKS': {
|
||||||
@@ -103,7 +103,7 @@ export const reducer = (
|
|||||||
...state,
|
...state,
|
||||||
tracksMode: action.payload.tracksMode,
|
tracksMode: action.payload.tracksMode,
|
||||||
isTracksOpen: action.payload.isTracksOpen,
|
isTracksOpen: action.payload.isTracksOpen,
|
||||||
selectedEntryId: action.payload.selectedRowKey
|
selectedLogId: action.payload.selectedRowKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@@ -36,16 +36,12 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
const [isPeoplePickerLoading, setIsPeoplePickerLoading] =
|
const [isPeoplePickerLoading, setIsPeoplePickerLoading] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const [selectedPerson, setSelectedPerson] = useState<Person>({
|
const [selectedPerson, setSelectedPerson] = useState<Person>({
|
||||||
userPrincipalName: '',
|
|
||||||
displayName: ''
|
displayName: ''
|
||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
const { getAccessToken } = useAccessToken();
|
const { getAccessToken } = useAccessToken();
|
||||||
const isAuthenticated = useIsAuthenticated();
|
const isAuthenticated = useIsAuthenticated();
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
partitionKey: 'pilot',
|
|
||||||
rowKey: 'noah@noahspannbauer.com',
|
|
||||||
id: '',
|
|
||||||
name: '',
|
name: '',
|
||||||
address: '',
|
address: '',
|
||||||
city: '',
|
city: '',
|
||||||
@@ -53,10 +49,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
postalCode: '',
|
postalCode: '',
|
||||||
email: '',
|
email: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
medicalClass: '',
|
|
||||||
medicalExpiration: '',
|
|
||||||
certificates: [],
|
|
||||||
endorsements: []
|
|
||||||
};
|
};
|
||||||
const methods = useForm({
|
const methods = useForm({
|
||||||
defaultValues: defaultValues
|
defaultValues: defaultValues
|
||||||
@@ -100,7 +92,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
value: Person,
|
value: Person,
|
||||||
_reason: string
|
_reason: string
|
||||||
) => {
|
) => {
|
||||||
methods.setValue('id', value.userPrincipalName!.toString());
|
|
||||||
methods.setValue('name', value.displayName!.toString());
|
methods.setValue('name', value.displayName!.toString());
|
||||||
setSelectedPerson(value);
|
setSelectedPerson(value);
|
||||||
};
|
};
|
||||||
@@ -159,16 +150,12 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
? { headers: { Authorization: await getAccessToken() } }
|
? { headers: { Authorization: await getAccessToken() } }
|
||||||
: {};
|
: {};
|
||||||
const response: AxiosResponse = await httpClient.get(
|
const response: AxiosResponse = await httpClient.get(
|
||||||
`api/pilots/pilot/${pilotId}`,
|
`api/pilots/${pilotId}`,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
const pilot = response.data;
|
const pilot = response.data;
|
||||||
|
|
||||||
pilot.certificates = JSON.parse(pilot.certificates);
|
|
||||||
pilot.endorsements = JSON.parse(pilot.endorsements)
|
|
||||||
|
|
||||||
setSelectedPerson({
|
setSelectedPerson({
|
||||||
userPrincipalName: pilot.id,
|
|
||||||
displayName: pilot.name
|
displayName: pilot.name
|
||||||
});
|
});
|
||||||
methods.reset(pilot);
|
methods.reset(pilot);
|
||||||
@@ -380,7 +367,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
{isAuthenticated &&
|
{/* {isAuthenticated &&
|
||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<PilotFormMedical
|
<PilotFormMedical
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
@@ -392,7 +379,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<PilotFormEndorsements isDisabled={isDisabled} mode={mode} />
|
<PilotFormEndorsements isDisabled={isDisabled} mode={mode} />
|
||||||
</Grid>
|
</Grid> */}
|
||||||
<Grid display="flex" gap={2} justifyContent="right" size={12}>
|
<Grid display="flex" gap={2} justifyContent="right" size={12}>
|
||||||
<Button
|
<Button
|
||||||
disabled={
|
disabled={
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
export interface Pilot {
|
export interface Pilot {
|
||||||
partitionKey: string;
|
|
||||||
rowKey: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
@@ -36,7 +36,7 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
const response: AxiosResponse = await httpClient.get(
|
const response: AxiosResponse = await httpClient.get(
|
||||||
`api/pilots`
|
`api/pilots`
|
||||||
);
|
);
|
||||||
|
console.log(response);
|
||||||
if (response.data.length > 0) {
|
if (response.data.length > 0) {
|
||||||
dispatch({ type: 'SET_PILOTS', payload: response.data });
|
dispatch({ type: 'SET_PILOTS', payload: response.data });
|
||||||
|
|
||||||
@@ -136,13 +136,14 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Actions',
|
header: 'Actions',
|
||||||
cell: (info: any) => (
|
cell: (info: any) => {
|
||||||
<ActionMenu
|
console.log(info)
|
||||||
id={info.row.original.rowKey}
|
return <ActionMenu
|
||||||
|
id={info.row.original.id}
|
||||||
onDelete={onDeleteEntry}
|
onDelete={onDeleteEntry}
|
||||||
onOpenCloseForm={onOpenClosePilotForm}
|
onOpenCloseForm={onOpenClosePilotForm}
|
||||||
/>
|
/>
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# azurite:
|
azurite:
|
||||||
# container_name: azurite-flying
|
container_name: azurite-flying
|
||||||
# image: mcr.microsoft.com/azure-storage/azurite
|
image: mcr.microsoft.com/azure-storage/azurite
|
||||||
# ports:
|
ports:
|
||||||
# - '10000:10000'
|
- '10000:10000'
|
||||||
# - '10001:10001'
|
- '10001:10001'
|
||||||
# - '10002:10002'
|
- '10002:10002'
|
||||||
# command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck'
|
command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck'
|
||||||
# volumes:
|
volumes:
|
||||||
# - ./azurite-flying:/data
|
- ./azurite-flying:/data
|
||||||
|
|
||||||
restore:
|
restore:
|
||||||
container_name: restore
|
container_name: restore
|
||||||
|
|||||||
21759
package-lock.json
generated
Normal file
21759
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -25,5 +25,10 @@
|
|||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"**/*": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\" --ignore-unknown"
|
"**/*": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\" --ignore-unknown"
|
||||||
}
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"api",
|
||||||
|
"app",
|
||||||
|
"tests"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
13428
pnpm-lock.yaml
generated
13428
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
|||||||
packages:
|
|
||||||
- 'api'
|
|
||||||
- 'app'
|
|
||||||
Reference in New Issue
Block a user