switching to sqlite
This commit is contained in:
44
.github/workflows/main.yaml
vendored
44
.github/workflows/main.yaml
vendored
@@ -19,17 +19,17 @@ jobs:
|
|||||||
version_number: ${{ github.run_id }}
|
version_number: ${{ github.run_id }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
deploy-api:
|
# deploy-api:
|
||||||
name: deploy-api
|
# name: deploy-api
|
||||||
needs:
|
# needs:
|
||||||
- changes
|
# - changes
|
||||||
- build-api
|
# - build-api
|
||||||
uses: ./.github/workflows/deploy.yaml
|
# uses: ./.github/workflows/deploy.yaml
|
||||||
with:
|
# with:
|
||||||
app_name: flying-api
|
# app_name: flying-api
|
||||||
environment_name: test
|
# environment_name: test
|
||||||
version_number: ${{ github.run_id }}
|
# version_number: ${{ github.run_id }}
|
||||||
secrets: inherit
|
# secrets: inherit
|
||||||
|
|
||||||
build-app:
|
build-app:
|
||||||
if: ${{ needs.changes.outputs.app == 'true' }}
|
if: ${{ needs.changes.outputs.app == 'true' }}
|
||||||
@@ -42,14 +42,14 @@ jobs:
|
|||||||
version_number: ${{ github.run_id }}
|
version_number: ${{ github.run_id }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
deploy-app:
|
# deploy-app:
|
||||||
name: deploy-app
|
# name: deploy-app
|
||||||
needs:
|
# needs:
|
||||||
- changes
|
# - changes
|
||||||
- build-app
|
# - build-app
|
||||||
uses: ./.github/workflows/deploy.yaml
|
# uses: ./.github/workflows/deploy.yaml
|
||||||
with:
|
# with:
|
||||||
app_name: flying-app
|
# app_name: flying-app
|
||||||
environment_name: test
|
# environment_name: test
|
||||||
version_number: ${{ github.run_id }}
|
# version_number: ${{ github.run_id }}
|
||||||
secrets: inherit
|
# secrets: inherit
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "api",
|
"name": "api",
|
||||||
"version": "1.4.0",
|
"version": "2.0.0-alpha",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import { ConfigService } from '@nestjs/config';
|
|||||||
}
|
}
|
||||||
|
|
||||||
async uploadFile(file: Express.Multer.File, containerName: string, logId: 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(`${logId}/${file.originalname}`);
|
const blockBlobClient = await this.getBlobClient(`${logId}/${file.originalname}`);
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
||||||
import { Observable, map } from 'rxjs';
|
import { Observable, map } from 'rxjs';
|
||||||
|
import { LogEntity } from '../log.entity';
|
||||||
|
|
||||||
export class LogInterceptor implements NestInterceptor {
|
export class LogInterceptor implements NestInterceptor {
|
||||||
intercept(context: ExecutionContext, handler: CallHandler): Observable<any> {
|
intercept(context: ExecutionContext, handler: CallHandler): Observable<any> {
|
||||||
const req = context.switchToHttp().getRequest();
|
const req = context.switchToHttp().getRequest();
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const token = authHeader && authHeader.split(' ')[1];
|
const token = authHeader && authHeader.split(' ')[1];
|
||||||
console.log(token)
|
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return handler.handle().pipe(
|
return handler.handle().pipe(
|
||||||
map((data) => {
|
map((data: LogEntity[]) => {
|
||||||
|
|
||||||
if (data.length) {
|
if (data.length) {
|
||||||
const logs = data.map((log) => {
|
const logs = data.map((log: LogEntity) => {
|
||||||
return {
|
return {
|
||||||
partitionKey: log.partitionKey,
|
id: log.id,
|
||||||
rowKey: log.rowKey,
|
pilot: {
|
||||||
pilotId: log.pilotId,
|
name: log.pilot.name
|
||||||
pilotName: log.pilotName,
|
},
|
||||||
date: log.date,
|
date: log.date,
|
||||||
aircraftMakeModel: log.aircraftMakeModel,
|
aircraftMakeModel: log.aircraftMakeModel,
|
||||||
routeFrom: log.routeFrom,
|
routeFrom: log.routeFrom,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { PilotEntity } from "src/pilot/pilot.entity";
|
import { PilotEntity } from "src/pilot/pilot.entity";
|
||||||
import { TrackEntity } from "src/track/track.entity";
|
|
||||||
|
|
||||||
export class LogDto {
|
export class LogDto {
|
||||||
pilotId: string;
|
pilotId: string;
|
||||||
@@ -26,5 +25,4 @@ export class LogDto {
|
|||||||
pilotInCommand?: number;
|
pilotInCommand?: number;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
pilot?: PilotEntity;
|
pilot?: PilotEntity;
|
||||||
tracks?: TrackEntity[];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ export class LogService {
|
|||||||
where: { id: id },
|
where: { id: id },
|
||||||
relations: ['pilot', 'tracks']
|
relations: ['pilot', 'tracks']
|
||||||
});
|
});
|
||||||
console.log(logEntity);
|
|
||||||
return logEntity;
|
return logEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<LogEntity[]> {
|
async findAll(): Promise<LogEntity[]> {
|
||||||
return await this.logRepository.find();
|
return await this.logRepository.find({
|
||||||
|
relations: ['pilot', 'tracks']
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(logDto: LogDto): Promise<InsertResult> {
|
async create(logDto: LogDto): Promise<InsertResult> {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class TrackController {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
// @Get('id')
|
// @Get('id')
|
||||||
// async fin(@Param('id') id: string): Promise<TrackEntity> {
|
// async find(@Param('id') id: string): Promise<TrackEntity> {
|
||||||
// try {
|
// try {
|
||||||
// return await this.trackService.find(id);
|
// return await this.trackService.find(id);
|
||||||
// } catch (error) {
|
// } catch (error) {
|
||||||
@@ -39,21 +39,22 @@ export class TrackController {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// @Get()
|
@Get(':logId')
|
||||||
// async findAdd(): Promise<TrackEntity[]> {
|
async findAll(@Param('logId') logId: string): Promise<TrackEntity[]> {
|
||||||
// try {
|
try {
|
||||||
// return await this.trackService.findAll();
|
return await this.trackService.findAll(logId);
|
||||||
// } catch (error) {
|
} catch (error) {
|
||||||
// const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
// throw new HttpException(customError.message, customError.statusCode)
|
throw new HttpException(customError.message, customError.statusCode);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Post(':logId/:order')
|
@Post(':logId/:order')
|
||||||
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
async create(@Param('logId') logId: string, @Param('order') order: number, @UploadedFile() file: Express.Multer.File): Promise<InsertResult> {
|
async create(@Param('logId') logId: string, @Param('order') order: number, @UploadedFile() file: Express.Multer.File): Promise<InsertResult> {
|
||||||
try {
|
try {
|
||||||
console.log(file)
|
|
||||||
return await this.trackService.create(logId, order, file);
|
return await this.trackService.create(logId, order, file);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
@@ -62,21 +63,12 @@ export class TrackController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Put(':id')
|
@UseGuards(AuthGuard)
|
||||||
// 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')
|
@Delete(':id')
|
||||||
async delete(@Param('id') id: string): Promise<DeleteResult> {
|
async delete(@Param('id') id: string, @Query('fileName') fileName: string, @Query('logId') logId: string): Promise<DeleteResult> {
|
||||||
try {
|
try {
|
||||||
return await this.trackService.delete(id);
|
|
||||||
|
return await this.trackService.delete(id, logId, fileName);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const customError = error as CustomError;
|
const customError = error as CustomError;
|
||||||
|
|
||||||
@@ -84,37 +76,10 @@ export class TrackController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
@Get(':logId/:fileName')
|
||||||
@Post(':partitionKey/:rowKey/track')
|
async downloadTrack(@Param('logId') logId: string, @Param('fileName') fileName: string): Promise<string> {
|
||||||
@UseInterceptors(FileInterceptor('file'))
|
|
||||||
async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) {
|
|
||||||
try {
|
try {
|
||||||
const containerName = 'tracks';
|
return await this.trackService.downloadTrackFile(logId, fileName);
|
||||||
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;
|
||||||
|
|
||||||
@@ -127,7 +92,3 @@ export class TrackController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,32 +10,51 @@ import { FileService } from "src/file/file.service";
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TrackService {
|
export class TrackService {
|
||||||
|
private readonly containerName: string = 'tracks'
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(TrackEntity) private readonly trackRepository: Repository<TrackEntity>,
|
@InjectRepository(TrackEntity) private readonly trackRepository: Repository<TrackEntity>,
|
||||||
private readonly fileService: FileService,
|
private readonly fileService: FileService,
|
||||||
private readonly logService: LogService
|
private readonly logService: LogService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// async find(id: string): Promise<TrackEntity> {
|
async find(id: string): Promise<TrackEntity> {
|
||||||
// return await this.trackRepository.findOneBy({ id });
|
try {
|
||||||
// }
|
return await this.trackRepository.findOneBy({ id });
|
||||||
|
} catch (error) {
|
||||||
|
throw new CustomError('Track not found', 'Not found', 404)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// async findAll(logId: string): Promise<TrackEntity[]> {
|
async findAll(logId: string): Promise<TrackEntity[]> {
|
||||||
// try {
|
try {
|
||||||
// await this.trackRepository.findOneBy({ })
|
const logEntity: LogEntity = await this.logService.find(logId);
|
||||||
// } catch (error) {
|
|
||||||
|
|
||||||
// }
|
if (logEntity) {
|
||||||
|
console.log(logEntity)
|
||||||
// }
|
const tracks = await this.trackRepository.find({
|
||||||
|
where: { log:
|
||||||
|
{
|
||||||
|
id: logEntity.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(tracks)
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
throw new CustomError('Tracks not found', 'Not found', 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async create(logId: string, order: number, file: Express.Multer.File): Promise<InsertResult> {
|
async create(logId: string, order: number, file: Express.Multer.File): Promise<InsertResult> {
|
||||||
try {
|
try {
|
||||||
const logEntity: LogEntity = await this.logService.find(logId);
|
const logEntity: LogEntity = await this.logService.find(logId);
|
||||||
|
|
||||||
if (logEntity) {
|
if (logEntity) {
|
||||||
const containerName = 'tracks';
|
const url = await this.fileService.uploadFile(file, this.containerName, logId);
|
||||||
const url = await this.fileService.uploadFile(file, containerName, logId);
|
|
||||||
const track = this.trackRepository.create({
|
const track = this.trackRepository.create({
|
||||||
log: logEntity,
|
log: logEntity,
|
||||||
order: order,
|
order: order,
|
||||||
@@ -52,37 +71,31 @@ export class TrackService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async update(id: string, track: TrackDto): Promise<UpdateResult> {
|
async update(id: string, track: TrackDto): Promise<UpdateResult> {
|
||||||
// return await this.trackRepository.update(id, track);
|
|
||||||
// }
|
|
||||||
|
|
||||||
async delete(id: string): Promise<DeleteResult> {
|
|
||||||
try {
|
try {
|
||||||
|
return await this.trackRepository.update(id, track);
|
||||||
} catch (error) {
|
} catch(error) {
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
return await this.trackRepository.delete({ id });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// async createTrack()
|
async delete(id: string, logId: string, fileName: string): Promise<DeleteResult> {
|
||||||
|
try {
|
||||||
|
await this.fileService.deleteFile(this.containerName, logId, fileName);
|
||||||
|
|
||||||
// async downloadTrack(): Promise<string> {
|
return await this.trackRepository.delete({ id });
|
||||||
// const containerName = 'tracks';
|
} catch (error) {
|
||||||
// const downloadedFile: string = await this.fileService.downloadFile(containerName, rowKey, fileName);
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return downloadedFile;
|
async downloadTrackFile(logId: string, fileName: string): Promise<string> {
|
||||||
// }
|
try {
|
||||||
|
const downloadedFile: string = await this.fileService.downloadFile(this.containerName, logId, fileName);
|
||||||
|
|
||||||
// async deleteTrack(): Promsie<void> {
|
return downloadedFile;
|
||||||
// try {
|
} catch (error) {
|
||||||
// const containerName = 'tracks';
|
throw error
|
||||||
|
}
|
||||||
// return await this.fileService.deleteFile(containerName, rowKey, fileName)
|
}
|
||||||
// } catch (error) {
|
|
||||||
// const customError = error as CustomError;
|
|
||||||
|
|
||||||
// throw customError;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "app",
|
"name": "app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.4.0",
|
"version": "2.0.0-alpha",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ const Flights = () => {
|
|||||||
const isMedium = useMediaQuery(theme.breakpoints.up('md'));
|
const isMedium = useMediaQuery(theme.breakpoints.up('md'));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(logs)
|
||||||
const flights: ILogbookEntry[] | undefined = logs?.filter((log: ILogbookEntry) => {
|
const flights: ILogbookEntry[] | undefined = logs?.filter((log: ILogbookEntry) => {
|
||||||
if (log.tracks && JSON.parse(log.tracks).length > 0) {
|
if (log.tracks && log.tracks.length > 0) {
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,24 +12,25 @@ import 'swiper/css';
|
|||||||
import './LogTrackMaps.css';
|
import './LogTrackMaps.css';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
|
||||||
const LogTrackMaps = ({ rowKey, trackUrls }: LogTrackMapsProps) => {
|
const LogTrackMaps = ({ logId, tracks }: LogTrackMapsProps) => {
|
||||||
const [tracks, setTracks] = useState<any[]>([])
|
const [kmls, setKmls] = useState<any[]>([])
|
||||||
const httpClient: AxiosInstance = useHttpClient();
|
const httpClient: AxiosInstance = useHttpClient();
|
||||||
const { getAccessToken } = useAccessToken();
|
const { getAccessToken } = useAccessToken();
|
||||||
const isAuthenticated = useIsAuthenticated();
|
const isAuthenticated = useIsAuthenticated();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(tracks)
|
||||||
const getTracks = async () => {
|
const getTracks = async () => {
|
||||||
const convertedTracks: any[] = []
|
const convertedTracks: any[] = []
|
||||||
|
|
||||||
for (const trackUrl of trackUrls) {
|
for (const track of tracks) {
|
||||||
const trackUrlSplit = trackUrl.split('/')
|
const trackUrlSplit = track.url.split('/')
|
||||||
const filename = trackUrlSplit[trackUrlSplit.length - 1];
|
const filename = trackUrlSplit[trackUrlSplit.length - 1];
|
||||||
const config = isAuthenticated
|
const config = isAuthenticated
|
||||||
? { headers: { Authorization: await getAccessToken() } }
|
? { headers: { Authorization: await getAccessToken() } }
|
||||||
: {};
|
: {};
|
||||||
const response: AxiosResponse = await httpClient.get(
|
const response: AxiosResponse = await httpClient.get(
|
||||||
`api/logs/log/${rowKey}/track?fileName=${filename}`,
|
`api/tracks/${logId}/${filename}`,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
const kml = new DOMParser().parseFromString(response.data, 'text/xml')
|
const kml = new DOMParser().parseFromString(response.data, 'text/xml')
|
||||||
@@ -37,11 +38,11 @@ const LogTrackMaps = ({ rowKey, trackUrls }: LogTrackMapsProps) => {
|
|||||||
convertedTracks.push(kml);
|
convertedTracks.push(kml);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTracks(convertedTracks)
|
setKmls(convertedTracks)
|
||||||
}
|
}
|
||||||
|
|
||||||
getTracks();
|
getTracks();
|
||||||
}, [trackUrls])
|
}, [tracks])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MapContainer
|
<MapContainer
|
||||||
@@ -54,8 +55,8 @@ const LogTrackMaps = ({ rowKey, trackUrls }: LogTrackMapsProps) => {
|
|||||||
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
/>
|
/>
|
||||||
{tracks.length > 0 && tracks.map((track) => (
|
{kmls.length > 0 && kmls.map((kml) => (
|
||||||
<ReactLeafletKml kml={track} />
|
<ReactLeafletKml kml={kml} />
|
||||||
))}
|
))}
|
||||||
</MapContainer>
|
</MapContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface LogTrackMapsProps {
|
export interface LogTrackMapsProps {
|
||||||
rowKey: string;
|
logId: string;
|
||||||
trackUrls: string[];
|
tracks: {id: string; order: number; url: string}[];
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ import ConfirmationDialog from "../confirmationDialog/ConfirmationDialog";
|
|||||||
import { initialState, reducer } from "./reducer";
|
import { initialState, reducer } from "./reducer";
|
||||||
import LogTrackMaps from "../logTrackMaps/LogTrackMaps";
|
import LogTrackMaps from "../logTrackMaps/LogTrackMaps";
|
||||||
|
|
||||||
const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTracksProps) => {
|
const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedLogId }: LogTracksProps) => {
|
||||||
const [state, dispatch] = useReducer(reducer, initialState)
|
const [state, dispatch] = useReducer(reducer, initialState)
|
||||||
const httpClient: AxiosInstance = useHttpClient();
|
const httpClient: AxiosInstance = useHttpClient();
|
||||||
const { getAccessToken } = useAccessToken();
|
const { getAccessToken } = useAccessToken();
|
||||||
@@ -27,50 +27,49 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLog = async (): Promise<ILogbookEntry> => {
|
// const getLog = async (): Promise<ILogbookEntry> => {
|
||||||
const logResponse: AxiosResponse = await httpClient.get(
|
// const logResponse: AxiosResponse = await httpClient.get(
|
||||||
`api/logs/${selectedRowKey}`,
|
// `api/tracks/${selectedLogId}`,
|
||||||
await getConfig()
|
// await getConfig()
|
||||||
);
|
// );
|
||||||
const logData: ILogbookEntry = logResponse.data;
|
// const logData: ILogbookEntry = logResponse.data;
|
||||||
|
|
||||||
return logData
|
// return logData
|
||||||
}
|
// }
|
||||||
|
|
||||||
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
// const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>, order: number) => {
|
||||||
try {
|
// try {
|
||||||
dispatch({ type: 'SET_IS_LOADING', payload: true})
|
// dispatch({ type: 'SET_IS_LOADING', payload: true})
|
||||||
|
|
||||||
const file = event.target.files![0]
|
// const file = event.target.files![0]
|
||||||
const formData = new FormData();
|
// const formData = new FormData();
|
||||||
const config = await getConfig();
|
// const config = await getConfig();
|
||||||
const formDataConfig = {
|
// const formDataConfig = {
|
||||||
headers: {
|
// headers: {
|
||||||
...config.headers,
|
// ...config.headers,
|
||||||
'Content-Type': 'multipart/form-data'
|
// 'Content-Type': 'multipart/form-data'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
formData.append('file', file);
|
// formData.append('file', file);
|
||||||
|
|
||||||
const uploadResponse: AxiosResponse = await httpClient.post(`api/logs/log/${selectedRowKey}/track`, formData, formDataConfig);
|
// const uploadResponse: AxiosResponse = await httpClient.post(`api/tracks/${selectedLogId}/${order}`, formData, formDataConfig);
|
||||||
const uploadUrl = uploadResponse.data.url;
|
// const uploadUrl = uploadResponse.data.url;
|
||||||
const log = await getLog();
|
// const tracks: string[] = log.tracks ? JSON.parse(log.tracks!) : [];
|
||||||
const tracks: string[] = log.tracks ? JSON.parse(log.tracks!) : [];
|
|
||||||
|
|
||||||
tracks.push(uploadUrl)
|
// tracks.push(uploadUrl)
|
||||||
log.tracks = JSON.stringify(tracks);
|
// log.tracks = JSON.stringify(tracks);
|
||||||
await httpClient.put(`api/logs/log/${selectedRowKey}`, log, config);
|
// await httpClient.put(`api/logs/log/${selectedRowKey}`, log, config);
|
||||||
|
|
||||||
const updatedLog = await getLog();
|
// const updatedLog = await getLog();
|
||||||
|
|
||||||
dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) })
|
// dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) })
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.log(error)
|
// console.log(error)
|
||||||
} finally {
|
// } finally {
|
||||||
dispatch({ type: 'SET_IS_LOADING', payload: false });
|
// dispatch({ type: 'SET_IS_LOADING', payload: false });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
onOpenClose(FormMode.CANCEL)
|
onOpenClose(FormMode.CANCEL)
|
||||||
@@ -80,41 +79,54 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
dispatch({ type: 'SET_ON_DELETE_TRACK', payload: { isConfirmDialogOpen: true, selectedTrack: { fileName: fileName, index: index }}})
|
dispatch({ type: 'SET_ON_DELETE_TRACK', payload: { isConfirmDialogOpen: true, selectedTrack: { fileName: fileName, index: index }}})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onConfirmDialogConfirm = async () => {
|
// const onConfirmDialogConfirm = async () => {
|
||||||
try {
|
// try {
|
||||||
const config = await getConfig();
|
// const config = await getConfig();
|
||||||
|
|
||||||
await httpClient.delete(`api/logs/log/${selectedRowKey}/track?fileName=${state.selectedTrack!.fileName}`, config);
|
// await httpClient.delete(`api/logs/log/${selectedRowKey}/track?fileName=${state.selectedTrack!.fileName}`, config);
|
||||||
|
|
||||||
const log = await getLog();
|
// const log = await getLog();
|
||||||
const tracks: string[] = JSON.parse(log.tracks!);
|
// const tracks: string[] = JSON.parse(log.tracks!);
|
||||||
|
|
||||||
tracks.splice(state.selectedTrack!.index, 1);
|
// tracks.splice(state.selectedTrack!.index, 1);
|
||||||
log.tracks = JSON.stringify(tracks);
|
// log.tracks = JSON.stringify(tracks);
|
||||||
await httpClient.put(`api/logs/log/${selectedRowKey}`, log, config);
|
// await httpClient.put(`api/logs/log/${selectedRowKey}`, log, config);
|
||||||
|
|
||||||
const updatedLog = await getLog();
|
// const updatedLog = await getLog();
|
||||||
|
|
||||||
dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) })
|
// dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) })
|
||||||
dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false })
|
// dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false })
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.log(error);
|
// console.log(error);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const onConfirmDialogCancel = async () => {
|
const onConfirmDialogCancel = async () => {
|
||||||
dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false })
|
dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const updateTracks = async () => {
|
// const updateTracks = async () => {
|
||||||
const log = await getLog();
|
// const log = await getLog();
|
||||||
|
|
||||||
dispatch({ type: 'SET_TRACKS', payload: JSON.parse(log.tracks!) });
|
// dispatch({ type: 'SET_TRACKS', payload: log.tracks! });
|
||||||
}
|
// }
|
||||||
|
|
||||||
updateTracks();
|
// updateTracks();
|
||||||
}, [])
|
// }, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isDrawerOpen) {
|
||||||
|
console.log(selectedLogId)
|
||||||
|
const getTracks = async () => {
|
||||||
|
const tracks = await httpClient.get(`api/tracks/${selectedLogId}`);
|
||||||
|
|
||||||
|
console.log(tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTracks();
|
||||||
|
}
|
||||||
|
}, [isDrawerOpen])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
@@ -149,7 +161,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
{!state.isLoading && state.tracks.length > 0 && state.tracks.map((track, index) => {
|
{!state.isLoading && state.tracks.length > 0 && state.tracks.map((track, index) => {
|
||||||
const trackSplit = track.split('/')
|
const trackSplit = track.url.split('/')
|
||||||
const filename = trackSplit[trackSplit.length - 1];
|
const filename = trackSplit[trackSplit.length - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -181,17 +193,17 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
variant='contained'
|
variant='contained'
|
||||||
>
|
>
|
||||||
Upload Track
|
Upload Track
|
||||||
<input hidden onChange={handleFileUpload} type='file' />
|
{/* <input hidden onChange={handleFileUpload} type='file' /> */}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
{mode === FormMode.VIEW &&
|
{mode === FormMode.VIEW &&
|
||||||
<LogTrackMaps rowKey={selectedRowKey!} trackUrls={state.tracks} />
|
<LogTrackMaps logId={selectedLogId!} tracks={state.tracks} />
|
||||||
}
|
}
|
||||||
</Grid>
|
</Grid>
|
||||||
{state.isConfirmDialogOpen && (
|
{/* {state.isConfirmDialogOpen && (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
contentText="Are you sure you want to delete this track?"
|
contentText="Are you sure you want to delete this track?"
|
||||||
isLoading={state.isConfirmDialogLoading}
|
isLoading={state.isConfirmDialogLoading}
|
||||||
@@ -200,7 +212,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
|||||||
onConfirm={onConfirmDialogConfirm}
|
onConfirm={onConfirmDialogConfirm}
|
||||||
title="Confirm Delete"
|
title="Confirm Delete"
|
||||||
/>
|
/>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ export interface LogTracksProps {
|
|||||||
isDrawerOpen: boolean;
|
isDrawerOpen: boolean;
|
||||||
mode: FormMode;
|
mode: FormMode;
|
||||||
onOpenClose: (mode: FormMode) => void;
|
onOpenClose: (mode: FormMode) => void;
|
||||||
selectedRowKey: string | undefined;
|
selectedLogId: string | undefined;
|
||||||
}
|
}
|
||||||
@@ -6,5 +6,5 @@ export interface LogTracksState {
|
|||||||
fileName: string,
|
fileName: string,
|
||||||
index: number
|
index: number
|
||||||
} | undefined;
|
} | undefined;
|
||||||
tracks: string[];
|
tracks: { id: string; order: number; url: string; }[];
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ type Action =
|
|||||||
| { type: 'SET_IS_CONFORM_DIALOG_LOADING'; payload: boolean }
|
| { type: 'SET_IS_CONFORM_DIALOG_LOADING'; payload: boolean }
|
||||||
| { type: 'SET_IS_LOADING'; payload: boolean }
|
| { type: 'SET_IS_LOADING'; payload: boolean }
|
||||||
| { type: 'SET_ON_DELETE_TRACK'; payload: { isConfirmDialogOpen: boolean, selectedTrack: { fileName: string, index: number } }}
|
| { type: 'SET_ON_DELETE_TRACK'; payload: { isConfirmDialogOpen: boolean, selectedTrack: { fileName: string, index: number } }}
|
||||||
| { type: 'SET_TRACKS'; payload: string[] };
|
| { type: 'SET_TRACKS'; payload: { id: string; order: number; url: string }[] };
|
||||||
|
|
||||||
export const initialState: LogTracksState = {
|
export const initialState: LogTracksState = {
|
||||||
isConfirmDialogOpen: false,
|
isConfirmDialogOpen: false,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
export interface ILogbookEntry {
|
export interface ILogbookEntry {
|
||||||
id: string;
|
id: string;
|
||||||
pilotId: string;
|
pilot: string;
|
||||||
pilotName: string;
|
|
||||||
date: string;
|
date: string;
|
||||||
aircraftMakeModel: string;
|
aircraftMakeModel: string;
|
||||||
aircraftIdentity: string;
|
aircraftIdentity: string;
|
||||||
@@ -23,6 +22,6 @@ export interface ILogbookEntry {
|
|||||||
night: number | null;
|
night: number | null;
|
||||||
solo: number | null;
|
solo: number | null;
|
||||||
pilotInCommand: number | null;
|
pilotInCommand: number | null;
|
||||||
tracks: string | undefined;
|
tracks: {id: string; order: number; url: string}[];
|
||||||
notes: string;
|
notes: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
accessorKey: 'tracks',
|
accessorKey: 'tracks',
|
||||||
header: 'Tracks',
|
header: 'Tracks',
|
||||||
cell: (info: any) => {
|
cell: (info: any) => {
|
||||||
if (info.row.original.tracks && JSON.parse(info.row.original.tracks).length > 0) {
|
if (info.row.original.tracks.length > 0) {
|
||||||
return (
|
return (
|
||||||
<IconButton onClick={() => onOpenCloseTracks(FormMode.VIEW, info.row.original.rowKey)}><Icon iconName={IconName.MAP_LOCATION_DOT} /></IconButton>
|
<IconButton onClick={() => onOpenCloseTracks(FormMode.VIEW, info.row.original.rowKey)}><Icon iconName={IconName.MAP_LOCATION_DOT} /></IconButton>
|
||||||
)
|
)
|
||||||
@@ -70,7 +70,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
: {};
|
: {};
|
||||||
const response: AxiosResponse = await httpClient.get(`api/logs`, config);
|
const response: AxiosResponse = await httpClient.get(`api/logs`, config);
|
||||||
const entries: ILogbookEntry[] = response.data;
|
const entries: ILogbookEntry[] = response.data;
|
||||||
|
console.log(entries)
|
||||||
entries.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
|
entries.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
|
||||||
|
|
||||||
if (response.data.length > 0) {
|
if (response.data.length > 0) {
|
||||||
@@ -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.selectedLogId}
|
selectedLogId={state.selectedLogId}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -19,14 +19,25 @@ const columnTotal = (info: HeaderContext<ILogbookEntry, unknown>): number => {
|
|||||||
|
|
||||||
const pilotName: ColumnDef<ILogbookEntry> = {
|
const pilotName: ColumnDef<ILogbookEntry> = {
|
||||||
id: 'pilotName',
|
id: 'pilotName',
|
||||||
accessorKey: 'pilotName',
|
accessorKey: 'pilot',
|
||||||
header: 'Pilot',
|
header: 'Pilot',
|
||||||
footer: 'PAGE TOTALS'
|
footer: 'PAGE TOTALS',
|
||||||
|
cell: (info: CellContext<ILogbookEntry, unknown>) => {
|
||||||
|
const pilot: any = info.getValue();
|
||||||
|
|
||||||
|
return pilot.name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const date: ColumnDef<ILogbookEntry> = {
|
const date: ColumnDef<ILogbookEntry> = {
|
||||||
id: 'date',
|
id: 'date',
|
||||||
accessorKey: 'date',
|
accessorKey: 'date',
|
||||||
header: 'Date'
|
header: 'Date',
|
||||||
|
cell: (info: CellContext<ILogbookEntry, unknown>) => {
|
||||||
|
const date = new Date(info.getValue() as string);
|
||||||
|
const formattedDate = `${date.getMonth()}/${date.getDate()}/${date.getFullYear()}`
|
||||||
|
|
||||||
|
return formattedDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const aircraftMakeModel: ColumnDef<ILogbookEntry> = {
|
const aircraftMakeModel: ColumnDef<ILogbookEntry> = {
|
||||||
id: 'aircraftMakeModel',
|
id: 'aircraftMakeModel',
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ const LogbookCard = ({ logs, mode, onDelete, onOpenCloseForm }: LogbookCardProps
|
|||||||
return (
|
return (
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{logs.map((log) => {
|
{logs.map((log) => {
|
||||||
console.log(log)
|
const date = new Date(log.date);
|
||||||
|
const formattedDate: string = `${date.getMonth()}/${date.getDate()}/${date.getFullYear()}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<Card key={log.rowKey}>
|
<Card key={log.id}>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
action={mode === 'logbook' ? <ActionMenu id={log.rowKey} onDelete={onDelete!} onOpenCloseForm={onOpenCloseForm!} /> : null}
|
action={mode === 'logbook' ? <ActionMenu id={log.id} onDelete={onDelete!} onOpenCloseForm={onOpenCloseForm!} /> : null}
|
||||||
subheader={log.pilotName}
|
title={formattedDate}
|
||||||
title={log.date}
|
|
||||||
slotProps={{
|
slotProps={{
|
||||||
subheader: {
|
subheader: {
|
||||||
fontSize: '16px'
|
fontSize: '16px'
|
||||||
@@ -27,11 +28,11 @@ const LogbookCard = ({ logs, mode, onDelete, onOpenCloseForm }: LogbookCardProps
|
|||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
{mode === 'flights' && log.tracks && JSON.parse(log.tracks).length > 0 &&
|
{mode === 'flights' && log.tracks && log.tracks.length > 0 &&
|
||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<LogTrackMaps
|
<LogTrackMaps
|
||||||
rowKey={log.rowKey}
|
logId={log.id}
|
||||||
trackUrls={JSON.parse(log.tracks)}
|
tracks={log.tracks}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
}
|
}
|
||||||
@@ -59,13 +60,13 @@ const LogbookCard = ({ logs, mode, onDelete, onOpenCloseForm }: LogbookCardProps
|
|||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<Typography variant="body1">{log.durationOfFlight}</Typography>
|
<Typography variant="body1">{log.durationOfFlight}</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
{mode === 'logbook' && log.tracks && JSON.parse(log.tracks).length > 0 &&
|
{mode === 'logbook' && log.tracks && log.tracks.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<Grid size={12}>
|
<Grid size={12}>
|
||||||
<Typography variant="subtitle2">Tracks</Typography>
|
<Typography variant="subtitle2">Tracks</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
{JSON.parse(log.tracks).map((track: string) => {
|
{log.tracks.map((track: { id: string; order: number; url: string}) => {
|
||||||
const trackSplit = track.split('/')
|
const trackSplit = track.url.split('/')
|
||||||
const filename = trackSplit[trackSplit.length - 1];
|
const filename = trackSplit[trackSplit.length - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user