96 switch from azure table storage to sqlite #100
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:cov": "jest --coverage",
|
||||
"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": {
|
||||
"@azure/storage-blob": "^12.27.0",
|
||||
@@ -32,7 +36,7 @@
|
||||
"@noahspan/noahspan-modules": "^1.1.5",
|
||||
"@schematics/angular": "^17.3.7",
|
||||
"@types/multer": "^1.4.12",
|
||||
"dotenv": "^16.4.7",
|
||||
"dotenv": "^16.6.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1",
|
||||
"sqlite3": "^5.1.7",
|
||||
|
||||
@@ -8,6 +8,8 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { AuthGuard, AuthModule, UserModule } from '@noahspan/noahspan-modules';
|
||||
import configuration from './config/configuration';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { dataSourceOptions } from './config/typeorm-cli.config';
|
||||
import { TrackModule } from './track/track.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -23,20 +25,14 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
},
|
||||
}),
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
load: [configuration]
|
||||
}),
|
||||
FeatureFlagModule,
|
||||
LogModule,
|
||||
PilotModule,
|
||||
TypeOrmModule.forRootAsync({
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
type: 'sqlite',
|
||||
database: configService.get<string>('dbPath'),
|
||||
entities: [__dirname + "/**/*.entity{.ts,.js}"],
|
||||
synchronize: false
|
||||
})
|
||||
}),
|
||||
TrackModule,
|
||||
TypeOrmModule.forRoot(dataSourceOptions),
|
||||
UserModule.registerAsync({
|
||||
inject: [ConfigService],
|
||||
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 () => ({
|
||||
azureStorageConnectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
||||
dbPath: process.env.DB_PATH,
|
||||
clientId: process.env.CLIENT_ID,
|
||||
clientSecret: process.env.CLIENT_SECRET,
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
const blockBlobClient = await this.getBlobClient(`${rowKey}/${file.originalname}`);
|
||||
const blockBlobClient = await this.getBlobClient(`${logId}/${file.originalname}`);
|
||||
const fileUrl = blockBlobClient.url;
|
||||
|
||||
await blockBlobClient.uploadData(file.buffer);
|
||||
|
||||
@@ -7,20 +7,17 @@ import {
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
StreamableFile,
|
||||
UploadedFile,
|
||||
UseGuards,
|
||||
UseInterceptors
|
||||
} from '@nestjs/common';
|
||||
import { LogDto } from './log.dto';
|
||||
import { Log } from './log.entity';
|
||||
import { LogEntity } from './log.entity';
|
||||
import { LogService } from './log.service';
|
||||
import { CustomError } from '../error/customError';
|
||||
import { AuthGuard } from '@noahspan/noahspan-modules';
|
||||
import { LogInterceptor } from './interceptors/log.interceptor';
|
||||
import { FileService } from '../file/file.service';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { DeleteResult, InsertResult, UpdateResult } from 'typeorm';
|
||||
|
||||
@Controller('logs')
|
||||
export class LogController {
|
||||
@@ -30,14 +27,13 @@ export class LogController {
|
||||
) {}
|
||||
|
||||
|
||||
@Get(':partitionKey/:rowKey')
|
||||
@Get(':id')
|
||||
@UseInterceptors(new LogInterceptor())
|
||||
async find(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
): Promise<Log> {
|
||||
@Param('id') id: string,
|
||||
): Promise<LogEntity> {
|
||||
try {
|
||||
return await this.logService.find(partitionKey, rowKey);
|
||||
return await this.logService.find(id);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
@@ -47,7 +43,7 @@ export class LogController {
|
||||
|
||||
@Get()
|
||||
@UseInterceptors(new LogInterceptor())
|
||||
async findAll(): Promise<Log[]> {
|
||||
async findAll(): Promise<LogEntity[]> {
|
||||
try {
|
||||
return await this.logService.findAll();
|
||||
} catch (error) {
|
||||
@@ -57,35 +53,26 @@ export class LogController {
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
// @UseGuards(AuthGuard)
|
||||
@Post()
|
||||
async create(@Body() logDto: LogDto): Promise<Log> {
|
||||
async create(@Body() logDto: LogDto): Promise<InsertResult> {
|
||||
try {
|
||||
const log = new Log();
|
||||
|
||||
Object.assign(log, logDto);
|
||||
|
||||
return await this.logService.create(log);
|
||||
return await this.logService.create(logDto);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
console.log(error)
|
||||
throw new HttpException(customError.message, customError.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Put(':partitionKey/:rowKey')
|
||||
// @UseGuards(AuthGuard)
|
||||
@Put(':id')
|
||||
async update(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string,
|
||||
@Param('id') id: string,
|
||||
@Body() logDto: LogDto
|
||||
): Promise<Log> {
|
||||
): Promise<UpdateResult> {
|
||||
try {
|
||||
const log = new Log();
|
||||
|
||||
Object.assign(log, logDto);
|
||||
|
||||
return await this.logService.update(partitionKey, rowKey, log);
|
||||
return await this.logService.update(id, logDto);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
@@ -93,52 +80,13 @@ export class LogController {
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Delete(':partitionKey/:rowKey')
|
||||
// @UseGuards(AuthGuard)
|
||||
@Delete(':id')
|
||||
async delete(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
): Promise<void> {
|
||||
@Param('id') id: string,
|
||||
): Promise<DeleteResult> {
|
||||
try {
|
||||
return await this.logService.delete(partitionKey, rowKey);
|
||||
} 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)
|
||||
return await this.logService.delete(id);
|
||||
} catch (error) {
|
||||
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 {
|
||||
pilotId: string;
|
||||
pilotName: string;
|
||||
date: string;
|
||||
date: Date;
|
||||
aircraftMakeModel: string;
|
||||
aircraftIdentity: string;
|
||||
routeFrom: string;
|
||||
routeTo: string;
|
||||
durationOfFlight: number;
|
||||
singleEngineLand: string;
|
||||
simulatorAtd: number;
|
||||
landingsDay: number;
|
||||
landingsNight: number;
|
||||
instrumentActual: number;
|
||||
instrumentSimulated: number;
|
||||
instrumentApproaches: number;
|
||||
instrumentHolds: number;
|
||||
instrumentNavTrack: number;
|
||||
groundTrainingReceived: number;
|
||||
flightTrainingReceived: number;
|
||||
crossCountry: number;
|
||||
night: number;
|
||||
solo: number;
|
||||
pilotInCommand: number;
|
||||
tracks: string[];
|
||||
notes: string;
|
||||
durationOfFlight?: number;
|
||||
singleEngineLand?: number;
|
||||
simulatorAtd?: number;
|
||||
landingsDay?: number;
|
||||
landingsNight?: number;
|
||||
instrumentActual?: number;
|
||||
instrumentSimulated?: number;
|
||||
instrumentApproaches?: number;
|
||||
instrumentHolds?: number;
|
||||
instrumentNavTrack?: number;
|
||||
groundTrainingReceived?: number;
|
||||
flightTrainingReceived?: number;
|
||||
crossCountry?: number;
|
||||
night?: number;
|
||||
solo?: number;
|
||||
pilotInCommand?: number;
|
||||
notes?: string;
|
||||
pilot?: PilotEntity;
|
||||
tracks?: TrackEntity[];
|
||||
}
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
export class Log {
|
||||
partitionKey: string;
|
||||
rowKey: string;
|
||||
pilotId: string;
|
||||
pilotName: string;
|
||||
date: string;
|
||||
aircraftMakeModel: string;
|
||||
aircraftIdentity: string;
|
||||
routeFrom: string;
|
||||
routeTo: string;
|
||||
durationOfFlight: number | null;
|
||||
singleEngineLand: number | null;
|
||||
simulatorAtd?: number | null;
|
||||
landingsDay?: number | null;
|
||||
landingsNight?: number | null;
|
||||
groundTrainingReceived?: number;
|
||||
flightTrainingReceived?: number;
|
||||
crossCountry?: number | null;
|
||||
night?: number | null;
|
||||
solo?: number | null;
|
||||
pilotInCommand?: number | null;
|
||||
instrumentActual?: number | null;
|
||||
instrumentSimulated?: number | null;
|
||||
instrumentApproaches?: number | null;
|
||||
instrumentHolds?: number | null;
|
||||
instrumentNavTrack?: number | null;
|
||||
tracks?: string[];
|
||||
notes?: string;
|
||||
}
|
||||
// export class Log {
|
||||
// partitionKey: string;
|
||||
// rowKey: string;
|
||||
// pilotId: string;
|
||||
// pilotName: string;
|
||||
// date: string;
|
||||
// aircraftMakeModel: string;
|
||||
// aircraftIdentity: string;
|
||||
// routeFrom: string;
|
||||
// routeTo: string;
|
||||
// durationOfFlight: number | null;
|
||||
// singleEngineLand: number | null;
|
||||
// simulatorAtd?: number | null;
|
||||
// landingsDay?: number | null;
|
||||
// landingsNight?: number | null;
|
||||
// groundTrainingReceived?: number;
|
||||
// flightTrainingReceived?: number;
|
||||
// crossCountry?: number | null;
|
||||
// night?: number | null;
|
||||
// solo?: number | null;
|
||||
// pilotInCommand?: number | null;
|
||||
// instrumentActual?: number | null;
|
||||
// instrumentSimulated?: number | null;
|
||||
// instrumentApproaches?: number | null;
|
||||
// instrumentHolds?: number | null;
|
||||
// instrumentNavTrack?: number | null;
|
||||
// tracks?: string[];
|
||||
// notes?: string;
|
||||
// }
|
||||
|
||||
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' })
|
||||
export class LogEntity {
|
||||
@@ -54,53 +55,56 @@ export class LogEntity {
|
||||
@Column()
|
||||
durationOfFlight: number;
|
||||
|
||||
@Column()
|
||||
singleEngineLand: number;
|
||||
@Column({ nullable: true })
|
||||
singleEngineLand: number | null;
|
||||
|
||||
@Column()
|
||||
simulatorAtd: number;
|
||||
@Column({ nullable: true })
|
||||
simulatorAtd: number | null;
|
||||
|
||||
@Column()
|
||||
landingsDay: number;
|
||||
@Column({ nullable: true })
|
||||
landingsDay: number | null;
|
||||
|
||||
@Column()
|
||||
landingsNight: number;
|
||||
@Column({ nullable: true })
|
||||
landingsNight: number | null;
|
||||
|
||||
@Column()
|
||||
groundTrainingReceived: number;
|
||||
@Column({ nullable: true })
|
||||
groundTrainingReceived: number | null;
|
||||
|
||||
@Column()
|
||||
flightTrainingReceived: number;
|
||||
@Column({ nullable: true })
|
||||
flightTrainingReceived: number | null;
|
||||
|
||||
@Column()
|
||||
crossCountry: number;
|
||||
@Column({ nullable: true })
|
||||
crossCountry: number | null;
|
||||
|
||||
@Column()
|
||||
night: number;
|
||||
@Column({ nullable: true })
|
||||
night: number | null;
|
||||
|
||||
@Column()
|
||||
solo: number;
|
||||
@Column({ nullable: true })
|
||||
solo: number | null;
|
||||
|
||||
@Column()
|
||||
pilotInCommand: number;
|
||||
@Column({ nullable: true })
|
||||
pilotInCommand: number | null;
|
||||
|
||||
@Column()
|
||||
instrumentActual: number;
|
||||
@Column({ nullable: true })
|
||||
instrumentActual: number | null;
|
||||
|
||||
@Column()
|
||||
instrumentSimulated: number;
|
||||
@Column({ nullable: true })
|
||||
instrumentSimulated: number | null;
|
||||
|
||||
@Column()
|
||||
instrumentApproaches: number;
|
||||
@Column({ nullable: true })
|
||||
instrumentApproaches: number | null;
|
||||
|
||||
@Column()
|
||||
instrumentHolds: number;
|
||||
@Column({ nullable: true })
|
||||
instrumentHolds: number | null;
|
||||
|
||||
@Column()
|
||||
instrumentNavTrack: number;
|
||||
@Column({ nullable: true })
|
||||
instrumentNavTrack: number | null;
|
||||
|
||||
@Column()
|
||||
notes: string;
|
||||
@Column({ nullable: true })
|
||||
notes: string | null;
|
||||
|
||||
@OneToMany(() => TrackEntity, (track: TrackEntity) => track.log, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
tracks: TrackEntity[]
|
||||
|
||||
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.logs)
|
||||
@JoinColumn({ name: 'pilotId' })
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { LogController } from './log.controller';
|
||||
import { LogService } from './log.service';
|
||||
import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||
import { Log } from './log.entity';
|
||||
// import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||
import { LogEntity } from './log.entity';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { FileService } from '../file/file.service';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PilotModule } from 'src/pilot/pilot.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
AzureTableStorageModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
return {
|
||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
};
|
||||
},
|
||||
inject: [ConfigService]
|
||||
}),
|
||||
AzureTableStorageModule.forFeature(Log, {
|
||||
createTableIfNotExists: false,
|
||||
table: 'logs'
|
||||
}),
|
||||
// AzureTableStorageModule.forRootAsync({
|
||||
// imports: [ConfigModule],
|
||||
// useFactory: async (configService: ConfigService) => {
|
||||
// return {
|
||||
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
// };
|
||||
// },
|
||||
// inject: [ConfigService]
|
||||
// }),
|
||||
// AzureTableStorageModule.forFeature(Log, {
|
||||
// createTableIfNotExists: false,
|
||||
// table: 'logs'
|
||||
// }),
|
||||
PilotModule,
|
||||
TypeOrmModule.forFeature([LogEntity])
|
||||
],
|
||||
controllers: [LogController],
|
||||
exports: [LogService],
|
||||
providers: [
|
||||
ConfigService,
|
||||
FileService,
|
||||
|
||||
@@ -1,34 +1,58 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository, Repository } from '@noahspan/azure-database';
|
||||
import { Log } from './log.entity';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { LogEntity } from './log.entity';
|
||||
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()
|
||||
export class LogService {
|
||||
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> {
|
||||
return await this.logRepository.find(partitionKey, rowKey);
|
||||
async find(id: string): Promise<LogEntity> {
|
||||
const logEntity: LogEntity = await this.logRepository.findOne({
|
||||
where: { id: id },
|
||||
relations: ['pilot', 'tracks']
|
||||
});
|
||||
console.log(logEntity);
|
||||
return logEntity;
|
||||
}
|
||||
|
||||
async findAll(): Promise<Log[]> {
|
||||
return await this.logRepository.findAll();
|
||||
async findAll(): Promise<LogEntity[]> {
|
||||
return await this.logRepository.find();
|
||||
}
|
||||
|
||||
async create(log: Log): Promise<Log> {
|
||||
log.partitionKey = 'log';
|
||||
log.rowKey = uuidv4();
|
||||
async create(logDto: LogDto): Promise<InsertResult> {
|
||||
try{
|
||||
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> {
|
||||
return await this.logRepository.update(partitionKey, rowKey, log);
|
||||
async update(id: string, log: LogDto): Promise<UpdateResult> {
|
||||
return await this.logRepository.update(id, log);
|
||||
}
|
||||
|
||||
async delete(partitionKey: string, rowKey: string): Promise<void> {
|
||||
await this.logRepository.delete(partitionKey, rowKey);
|
||||
async delete(id: string): Promise<DeleteResult> {
|
||||
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,
|
||||
} from '@nestjs/common';
|
||||
import { PilotDto } from './pilot.dto';
|
||||
import { Pilot } from './pilot.entity';
|
||||
import { PilotEntity } from './pilot.entity';
|
||||
import { PilotService } from './pilot.service';
|
||||
import { CustomError } from '../error/customError';
|
||||
import { AuthGuard } from '@noahspan/noahspan-modules'
|
||||
import { PilotInterceptor } from './interceptors/pilot.interceptor';
|
||||
|
||||
@Controller('pilots')
|
||||
@UseInterceptors(new PilotInterceptor())
|
||||
// @UseInterceptors(new PilotInterceptor())
|
||||
export class PilotController {
|
||||
constructor(private readonly pilotService: PilotService) {}
|
||||
|
||||
@Get(':partitionKey/:rowKey')
|
||||
async find(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
) {
|
||||
@Get(':id')
|
||||
async find(@Param('id') id: string) {
|
||||
try {
|
||||
return await this.pilotService.find(partitionKey, rowKey);
|
||||
return await this.pilotService.find(id);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
@@ -47,30 +44,11 @@ export class PilotController {
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
// @UseGuards(AuthGuard)
|
||||
@Post()
|
||||
async create(@Body() pilotDto: PilotDto) {
|
||||
try {
|
||||
let pilot = new Pilot();
|
||||
|
||||
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);
|
||||
return await this.pilotService.create(pilotDto);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
@@ -78,34 +56,14 @@ export class PilotController {
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Put(':partitionKey/:rowKey')
|
||||
// @UseGuards(AuthGuard)
|
||||
@Put(':id')
|
||||
async update(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string,
|
||||
@Param('id') id: string,
|
||||
@Body() pilotDto: PilotDto
|
||||
) {
|
||||
try {
|
||||
let pilot = new Pilot();
|
||||
|
||||
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);
|
||||
return await this.pilotService.update(id, pilotDto);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
@@ -113,14 +71,13 @@ export class PilotController {
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Delete(':partitionKey/:rowKey')
|
||||
// @UseGuards(AuthGuard)
|
||||
@Delete(':id')
|
||||
async delete(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
try {
|
||||
return await this.pilotService.delete(partitionKey, rowKey);
|
||||
return await this.pilotService.delete(id);
|
||||
} catch (error) {
|
||||
const customError = error as CustomError;
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { Certificate } from "./certificate/certificate.entity";
|
||||
import { Endorsement } from "./endorsement/endorsement.entity";
|
||||
import { LogEntity } from "src/log/log.entity";
|
||||
|
||||
export class PilotDto {
|
||||
partitionKey: string;
|
||||
rowKey: string;
|
||||
id: string;
|
||||
name: string;
|
||||
address: string;
|
||||
city: string;
|
||||
@@ -12,8 +8,4 @@ export class PilotDto {
|
||||
postalCode: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
medicalClass?: string;
|
||||
medicalExpiration?: string;
|
||||
certificates: Certificate;
|
||||
endorsements: Endorsement
|
||||
}
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PilotController } from './pilot.controller';
|
||||
import { PilotService } from './pilot.service';
|
||||
import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||
import { Pilot } from './pilot.entity';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { Log } from 'src/log/log.entity';
|
||||
// import { AzureTableStorageModule } from '@noahspan/azure-database';
|
||||
import { PilotEntity } from './pilot.entity';
|
||||
// import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
// import { Log } from 'src/log/log.entity';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
AzureTableStorageModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
return {
|
||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
};
|
||||
},
|
||||
inject: [ConfigService]
|
||||
}),
|
||||
AzureTableStorageModule.forFeature(Log, {
|
||||
createTableIfNotExists: false,
|
||||
table: 'logs'
|
||||
}),
|
||||
AzureTableStorageModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
return {
|
||||
connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
};
|
||||
},
|
||||
inject: [ConfigService]
|
||||
}),
|
||||
AzureTableStorageModule.forFeature(Pilot, {
|
||||
createTableIfNotExists: false,
|
||||
table: 'pilots'
|
||||
})
|
||||
// AzureTableStorageModule.forRootAsync({
|
||||
// imports: [ConfigModule],
|
||||
// useFactory: async (configService: ConfigService) => {
|
||||
// return {
|
||||
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
// };
|
||||
// },
|
||||
// inject: [ConfigService]
|
||||
// }),
|
||||
// AzureTableStorageModule.forFeature(Log, {
|
||||
// createTableIfNotExists: false,
|
||||
// table: 'logs'
|
||||
// }),
|
||||
// AzureTableStorageModule.forRootAsync({
|
||||
// imports: [ConfigModule],
|
||||
// useFactory: async (configService: ConfigService) => {
|
||||
// return {
|
||||
// connectionString: configService.get<string>('azureStorageConnectionString')
|
||||
// };
|
||||
// },
|
||||
// inject: [ConfigService]
|
||||
// }),
|
||||
// AzureTableStorageModule.forFeature(PilotEntity, {
|
||||
// createTableIfNotExists: false,
|
||||
// table: 'pilots'
|
||||
// }),
|
||||
TypeOrmModule.forFeature([PilotEntity])
|
||||
],
|
||||
controllers: [PilotController],
|
||||
exports: [PilotService],
|
||||
providers: [PilotService]
|
||||
})
|
||||
export class PilotModule {}
|
||||
|
||||
@@ -1,54 +1,46 @@
|
||||
import { InjectRepository, Repository } from '@noahspan/azure-database';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Pilot } from './pilot.entity';
|
||||
import { Log } from 'src/log/log.entity';
|
||||
import { LogService } from 'src/log/log.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PilotEntity } from './pilot.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DeleteResult, InsertResult, Repository, UpdateResult } from 'typeorm';
|
||||
import { PilotDto } from './pilot.dto';
|
||||
import { CustomError } from 'src/error/customError';
|
||||
|
||||
@Injectable()
|
||||
export class PilotService {
|
||||
constructor(
|
||||
@InjectRepository(Pilot) private readonly pilotRepository: Repository<Pilot>,
|
||||
@InjectRepository(Log) private readonly logRepository: Repository<Log>
|
||||
@InjectRepository(PilotEntity) private readonly pilotRepository: Repository<PilotEntity>
|
||||
) {}
|
||||
|
||||
async find(partitionKey: string, rowKey: string): Promise<Pilot> {
|
||||
return await this.pilotRepository.find(partitionKey, rowKey);
|
||||
async find(id: string): Promise<PilotEntity> {
|
||||
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[]> {
|
||||
return await this.pilotRepository.findAll();
|
||||
async findAll(): Promise<PilotEntity[]> {
|
||||
return await this.pilotRepository.find();
|
||||
}
|
||||
|
||||
async create(pilot: Pilot): Promise<Pilot> {
|
||||
// try {
|
||||
// return await this.pilotRepository.create(pilot);
|
||||
// } catch (error) {
|
||||
// throw new Error(error);
|
||||
// }
|
||||
return await this.pilotRepository.create(pilot);
|
||||
async create(pilot: PilotDto): Promise<InsertResult> {
|
||||
return await this.pilotRepository.insert(pilot);
|
||||
}
|
||||
|
||||
async update(
|
||||
partitionKey: string,
|
||||
rowKey: string,
|
||||
pilot: Pilot
|
||||
): Promise<Pilot> {
|
||||
return await this.pilotRepository.update(partitionKey, rowKey, pilot);
|
||||
id: string,
|
||||
pilot: PilotDto
|
||||
): Promise<UpdateResult> {
|
||||
return await this.pilotRepository.update(id, pilot);
|
||||
}
|
||||
|
||||
async delete(partitionKey: string, rowKey: string): Promise<void> {
|
||||
const pilotLogs: Log[] = await this.logRepository.findAll({
|
||||
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
|
||||
async delete(id: string): Promise<DeleteResult> {
|
||||
return await this.pilotRepository.delete({ id });
|
||||
}
|
||||
}
|
||||
|
||||
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": {
|
||||
"@azure/msal-browser": "^4.0.1",
|
||||
"@azure/msal-react": "^3.0.1",
|
||||
"@azure/msal-react": "3.0.1",
|
||||
"@noahspan/noahspan-components": "^1.9.1",
|
||||
"axios": "^1.7.2",
|
||||
"dotenv": "^16.4.7",
|
||||
"leaflet": "^1.9.4",
|
||||
"react": "19.0.0-rc.1",
|
||||
"react-dom": "19.0.0-rc.1",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"react-leaflet": "^4",
|
||||
"react-leaflet-kml": "^2.1.2",
|
||||
"react-router-dom": "^6.23.0",
|
||||
"swiper": "^11.2.6"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FormMode } from '../../enums/formMode';
|
||||
|
||||
export interface ILogFormProps {
|
||||
entryId?: string;
|
||||
logId?: string;
|
||||
isDrawerOpen: boolean;
|
||||
mode: FormMode;
|
||||
onOpenClose: (mode: FormMode) => void;
|
||||
|
||||
@@ -5,5 +5,5 @@ export interface ILogFormState {
|
||||
isDisabled: boolean;
|
||||
isLoading: boolean;
|
||||
pilotOptions: { label: string; value: string }[];
|
||||
selectedEntryPilotName: string;
|
||||
selectedPilotName: string;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import { FormMode } from '../../enums/formMode';
|
||||
import { usePilots } from '../../hooks/pilots/UsePilots';
|
||||
|
||||
const LogForm: React.FC<ILogFormProps> = ({
|
||||
entryId,
|
||||
logId,
|
||||
isDrawerOpen,
|
||||
mode,
|
||||
onOpenClose
|
||||
@@ -39,7 +39,6 @@ const LogForm: React.FC<ILogFormProps> = ({
|
||||
const isAuthenticated = useIsAuthenticated();
|
||||
const defaultValues = {
|
||||
pilotId: '',
|
||||
pilotName: '',
|
||||
date: null,
|
||||
aircraftMakeModel: '',
|
||||
aircraftIdentity: '',
|
||||
@@ -79,14 +78,14 @@ const LogForm: React.FC<ILogFormProps> = ({
|
||||
|
||||
const accessToken: string = await getAccessToken();
|
||||
|
||||
if (!entryId) {
|
||||
if (!logId) {
|
||||
await httpClient.post(`api/logs`, data, {
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await httpClient.put(`api/logs/log/${entryId}`, data, {
|
||||
await httpClient.put(`api/logs/${logId}`, data, {
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
@@ -120,21 +119,13 @@ const LogForm: React.FC<ILogFormProps> = ({
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/logs/log/${entryId}`,
|
||||
`api/logs/${logId}`,
|
||||
config
|
||||
);
|
||||
const entry = response.data;
|
||||
const log = response.data;
|
||||
|
||||
// if (mode !== FormMode.ADD) {
|
||||
// const pilot = pilots?.find((pilot) => pilot.id === entry.pilotId);
|
||||
// console.log(pilot.name)
|
||||
// dispatch({
|
||||
// type: 'SET_SELECTED_ENTRY_PILOT_NAME',
|
||||
// payload: pilot.name
|
||||
// });
|
||||
// }
|
||||
|
||||
methods.reset(entry);
|
||||
log.pilotId = log.pilot.id
|
||||
methods.reset(log);
|
||||
} catch (error) {
|
||||
const axiosError = error as AxiosError;
|
||||
|
||||
@@ -144,10 +135,10 @@ const LogForm: React.FC<ILogFormProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (entryId && isDrawerOpen) {
|
||||
if (logId && isDrawerOpen) {
|
||||
getEntry();
|
||||
}
|
||||
}, [entryId]);
|
||||
}, [logId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (pilots && FormMode.ADD) {
|
||||
@@ -214,10 +205,6 @@ const LogForm: React.FC<ILogFormProps> = ({
|
||||
(pilot) => (pilot.id = event.target.value)
|
||||
);
|
||||
|
||||
if (pilot) {
|
||||
methods.setValue('pilotName', pilot.name);
|
||||
}
|
||||
|
||||
methods.setValue('pilotId', event.target.value);
|
||||
}}
|
||||
options={
|
||||
|
||||
@@ -6,14 +6,14 @@ type Action =
|
||||
| { type: 'SET_IS_DISABLED'; payload: boolean }
|
||||
| { type: 'SET_IS_LOADING'; payload: boolean }
|
||||
| { 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 = {
|
||||
alert: undefined,
|
||||
isDisabled: false,
|
||||
isLoading: true,
|
||||
pilotOptions: [],
|
||||
selectedEntryPilotName: ''
|
||||
selectedPilotName: ''
|
||||
};
|
||||
|
||||
export const reducer = (
|
||||
@@ -45,10 +45,10 @@ export const reducer = (
|
||||
pilotOptions: action.payload
|
||||
};
|
||||
}
|
||||
case 'SET_SELECTED_ENTRY_PILOT_NAME': {
|
||||
case 'SET_SELECTED_PILOT_NAME': {
|
||||
return {
|
||||
...state,
|
||||
selectedEntryPilotName: action.payload
|
||||
selectedPilotName: action.payload
|
||||
};
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -29,7 +29,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
||||
|
||||
const getLog = async (): Promise<ILogbookEntry> => {
|
||||
const logResponse: AxiosResponse = await httpClient.get(
|
||||
`api/logs/log/${selectedRowKey}`,
|
||||
`api/logs/${selectedRowKey}`,
|
||||
await getConfig()
|
||||
);
|
||||
const logData: ILogbookEntry = logResponse.data;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import { ColumnDef } from "@noahspan/noahspan-components";
|
||||
|
||||
export interface ILogbookEntry {
|
||||
partitionKey: string;
|
||||
rowKey: string;
|
||||
id: string;
|
||||
pilotId: string;
|
||||
pilotName: string;
|
||||
|
||||
@@ -13,6 +13,6 @@ export interface ILogbookState {
|
||||
isFormOpen: boolean;
|
||||
isLoading: boolean;
|
||||
isTracksOpen: boolean;
|
||||
selectedEntryId: string | undefined;
|
||||
selectedLogId: string | undefined;
|
||||
tracksMode: FormMode;
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ const Logbook: React.FC<unknown> = () => {
|
||||
},
|
||||
cell: (info: any) => (
|
||||
<ActionMenu
|
||||
id={info.row.original.rowKey}
|
||||
onDelete={onDeleteEntry}
|
||||
onOpenCloseForm={onOpenCloseEntryForm}
|
||||
id={info.row.original.id}
|
||||
onDelete={onDeleteLog}
|
||||
onOpenCloseForm={onOpenCloseLogForm}
|
||||
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) {
|
||||
case FormMode.ADD:
|
||||
case FormMode.EDIT:
|
||||
case FormMode.VIEW:
|
||||
dispatch({
|
||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM',
|
||||
type: 'SET_OPEN_CLOSE_LOG_FORM',
|
||||
payload: {
|
||||
formMode: mode,
|
||||
selectedEntryId: entryId,
|
||||
selectedLogId: logId,
|
||||
isFormOpen: true
|
||||
}
|
||||
});
|
||||
@@ -111,10 +111,10 @@ const Logbook: React.FC<unknown> = () => {
|
||||
break;
|
||||
case FormMode.CANCEL:
|
||||
dispatch({
|
||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM',
|
||||
type: 'SET_OPEN_CLOSE_LOG_FORM',
|
||||
payload: {
|
||||
formMode: mode,
|
||||
selectedEntryId: undefined,
|
||||
selectedLogId: undefined,
|
||||
isFormOpen: false
|
||||
}
|
||||
});
|
||||
@@ -151,10 +151,10 @@ const Logbook: React.FC<unknown> = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const onDeleteEntry = (entryId: string) => {
|
||||
const onDeleteLog = (logId: string) => {
|
||||
dispatch({
|
||||
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}` } }
|
||||
: {};
|
||||
|
||||
await httpClient.delete(`api/logs/log/${state.selectedEntryId}`, config);
|
||||
await httpClient.delete(`api/logs/${state.selectedLogId}`, config);
|
||||
|
||||
dispatch({
|
||||
type: 'SET_DELETE',
|
||||
payload: { isConfirmationDialogOpen: false, selectedEntryId: undefined }
|
||||
payload: { isConfirmationDialogOpen: false, selectedLogId: undefined }
|
||||
});
|
||||
await getLogbookEntries();
|
||||
} catch (error) {
|
||||
@@ -189,7 +189,7 @@ const Logbook: React.FC<unknown> = () => {
|
||||
const onConfirmationDialogCancel = () => {
|
||||
dispatch({
|
||||
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}>
|
||||
{isAuthenticated &&
|
||||
<Button
|
||||
onClick={() => onOpenCloseEntryForm(FormMode.ADD)}
|
||||
onClick={() => onOpenCloseLogForm(FormMode.ADD)}
|
||||
startIcon={<Icon iconName={IconName.PLUS} />}
|
||||
variant="contained"
|
||||
data-testid="pilot-add-button"
|
||||
@@ -261,7 +261,7 @@ const Logbook: React.FC<unknown> = () => {
|
||||
<Table columns={state.columns} data={state.entries} />
|
||||
)}
|
||||
{!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>
|
||||
)}
|
||||
@@ -278,10 +278,10 @@ const Logbook: React.FC<unknown> = () => {
|
||||
</Grid>
|
||||
{state.isFormOpen && (
|
||||
<LogForm
|
||||
entryId={state.selectedEntryId}
|
||||
logId={state.selectedLogId}
|
||||
isDrawerOpen={state.isFormOpen}
|
||||
mode={state.formMode}
|
||||
onOpenClose={(mode) => onOpenCloseEntryForm(mode)}
|
||||
onOpenClose={(mode) => onOpenCloseLogForm(mode)}
|
||||
/>
|
||||
)}
|
||||
{state.isConfirmDialogOpen && (
|
||||
@@ -299,7 +299,7 @@ const Logbook: React.FC<unknown> = () => {
|
||||
isDrawerOpen={state.isTracksOpen}
|
||||
mode={state.tracksMode}
|
||||
onOpenClose={(mode) => onOpenCloseTracks(mode)}
|
||||
selectedRowKey={state.selectedEntryId}
|
||||
selectedRowKey={state.selectedLogId}
|
||||
/>
|
||||
}
|
||||
</Box>
|
||||
|
||||
@@ -10,7 +10,7 @@ type Action =
|
||||
type: 'SET_DELETE';
|
||||
payload: {
|
||||
isConfirmationDialogOpen: boolean;
|
||||
selectedEntryId: string | undefined;
|
||||
selectedLogId: string | undefined;
|
||||
};
|
||||
}
|
||||
| { type: 'SET_ENTRIES'; payload: ILogbookEntry[] }
|
||||
@@ -19,10 +19,10 @@ type Action =
|
||||
| { type: 'SET_IS_CONFIRMATION_DIALOG_LOADING'; payload: boolean }
|
||||
| { type: 'SET_IS_LOADING'; payload: boolean }
|
||||
| {
|
||||
type: 'SET_OPEN_CLOSE_ENTRY_FORM';
|
||||
type: 'SET_OPEN_CLOSE_LOG_FORM';
|
||||
payload: {
|
||||
formMode: FormMode;
|
||||
selectedEntryId: string | undefined;
|
||||
selectedLogId: string | undefined;
|
||||
isFormOpen: boolean;
|
||||
};
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export const initialState: ILogbookState = {
|
||||
isFormOpen: false,
|
||||
isLoading: false,
|
||||
isTracksOpen: false,
|
||||
selectedEntryId: undefined,
|
||||
selectedLogId: undefined,
|
||||
tracksMode: FormMode.CANCEL
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ export const reducer = (
|
||||
return {
|
||||
...state,
|
||||
isConfirmDialogOpen: action.payload.isConfirmationDialogOpen,
|
||||
selectedEntryId: action.payload.selectedEntryId
|
||||
selectedLogId: action.payload.selectedLogId
|
||||
};
|
||||
}
|
||||
case 'SET_ENTRIES': {
|
||||
@@ -90,12 +90,12 @@ export const reducer = (
|
||||
isLoading: action.payload
|
||||
};
|
||||
}
|
||||
case 'SET_OPEN_CLOSE_ENTRY_FORM': {
|
||||
case 'SET_OPEN_CLOSE_LOG_FORM': {
|
||||
return {
|
||||
...state,
|
||||
formMode: action.payload.formMode,
|
||||
isFormOpen: action.payload.isFormOpen,
|
||||
selectedEntryId: action.payload.selectedEntryId
|
||||
selectedLogId: action.payload.selectedLogId
|
||||
};
|
||||
}
|
||||
case 'SET_OPEN_CLOSE_TRACKS': {
|
||||
@@ -103,7 +103,7 @@ export const reducer = (
|
||||
...state,
|
||||
tracksMode: action.payload.tracksMode,
|
||||
isTracksOpen: action.payload.isTracksOpen,
|
||||
selectedEntryId: action.payload.selectedRowKey
|
||||
selectedLogId: action.payload.selectedRowKey
|
||||
}
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -36,16 +36,12 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
const [isPeoplePickerLoading, setIsPeoplePickerLoading] =
|
||||
useState<boolean>(false);
|
||||
const [selectedPerson, setSelectedPerson] = useState<Person>({
|
||||
userPrincipalName: '',
|
||||
displayName: ''
|
||||
});
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const { getAccessToken } = useAccessToken();
|
||||
const isAuthenticated = useIsAuthenticated();
|
||||
const defaultValues = {
|
||||
partitionKey: 'pilot',
|
||||
rowKey: 'noah@noahspannbauer.com',
|
||||
id: '',
|
||||
name: '',
|
||||
address: '',
|
||||
city: '',
|
||||
@@ -53,10 +49,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
postalCode: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
medicalClass: '',
|
||||
medicalExpiration: '',
|
||||
certificates: [],
|
||||
endorsements: []
|
||||
};
|
||||
const methods = useForm({
|
||||
defaultValues: defaultValues
|
||||
@@ -100,7 +92,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
value: Person,
|
||||
_reason: string
|
||||
) => {
|
||||
methods.setValue('id', value.userPrincipalName!.toString());
|
||||
methods.setValue('name', value.displayName!.toString());
|
||||
setSelectedPerson(value);
|
||||
};
|
||||
@@ -159,16 +150,12 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/pilots/pilot/${pilotId}`,
|
||||
`api/pilots/${pilotId}`,
|
||||
config
|
||||
);
|
||||
const pilot = response.data;
|
||||
|
||||
pilot.certificates = JSON.parse(pilot.certificates);
|
||||
pilot.endorsements = JSON.parse(pilot.endorsements)
|
||||
|
||||
setSelectedPerson({
|
||||
userPrincipalName: pilot.id,
|
||||
displayName: pilot.name
|
||||
});
|
||||
methods.reset(pilot);
|
||||
@@ -380,7 +367,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
</Grid>
|
||||
</>
|
||||
}
|
||||
{isAuthenticated &&
|
||||
{/* {isAuthenticated &&
|
||||
<Grid size={12}>
|
||||
<PilotFormMedical
|
||||
isDisabled={isDisabled}
|
||||
@@ -392,7 +379,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
</Grid>
|
||||
<Grid size={12}>
|
||||
<PilotFormEndorsements isDisabled={isDisabled} mode={mode} />
|
||||
</Grid>
|
||||
</Grid> */}
|
||||
<Grid display="flex" gap={2} justifyContent="right" size={12}>
|
||||
<Button
|
||||
disabled={
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
export interface Pilot {
|
||||
partitionKey: string;
|
||||
rowKey: string;
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
@@ -36,7 +36,7 @@ const Pilots: React.FC<unknown> = () => {
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/pilots`
|
||||
);
|
||||
|
||||
console.log(response);
|
||||
if (response.data.length > 0) {
|
||||
dispatch({ type: 'SET_PILOTS', payload: response.data });
|
||||
|
||||
@@ -136,13 +136,14 @@ const Pilots: React.FC<unknown> = () => {
|
||||
},
|
||||
{
|
||||
header: 'Actions',
|
||||
cell: (info: any) => (
|
||||
<ActionMenu
|
||||
id={info.row.original.rowKey}
|
||||
cell: (info: any) => {
|
||||
console.log(info)
|
||||
return <ActionMenu
|
||||
id={info.row.original.id}
|
||||
onDelete={onDeleteEntry}
|
||||
onOpenCloseForm={onOpenClosePilotForm}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# azurite:
|
||||
# container_name: azurite-flying
|
||||
# image: mcr.microsoft.com/azure-storage/azurite
|
||||
# ports:
|
||||
# - '10000:10000'
|
||||
# - '10001:10001'
|
||||
# - '10002:10002'
|
||||
# command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck'
|
||||
# volumes:
|
||||
# - ./azurite-flying:/data
|
||||
azurite:
|
||||
container_name: azurite-flying
|
||||
image: mcr.microsoft.com/azure-storage/azurite
|
||||
ports:
|
||||
- '10000:10000'
|
||||
- '10001:10001'
|
||||
- '10002:10002'
|
||||
command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck'
|
||||
volumes:
|
||||
- ./azurite-flying:/data
|
||||
|
||||
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": {
|
||||
"**/*": "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