adding tracks

This commit is contained in:
2025-03-22 09:18:59 -05:00
parent 485671f163
commit 996994d5e9
5 changed files with 103 additions and 18 deletions

View File

@@ -105,7 +105,7 @@ export class LogController {
} }
} }
// @UseGuards(AuthGuard) @UseGuards(AuthGuard)
@Post(':partitionKey/:rowKey/track') @Post(':partitionKey/:rowKey/track')
@UseInterceptors(FileInterceptor('file')) @UseInterceptors(FileInterceptor('file'))
async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) { async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) {

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import { useEffect, useReducer, useState } from "react";
import { Button, Drawer, Grid, Icon, IconButton, IconName, TextField, theme, Typography, useMediaQuery } from "@noahspan/noahspan-components"; import { Button, Drawer, Grid, Icon, IconButton, IconName, TextField, theme, Typography, useMediaQuery } from "@noahspan/noahspan-components";
import { useHttpClient } from "../../hooks/httpClient/UseHttpClient"; import { useHttpClient } from "../../hooks/httpClient/UseHttpClient";
import { AxiosInstance, AxiosResponse } from "axios"; import { AxiosInstance, AxiosResponse } from "axios";
@@ -7,10 +7,11 @@ import { LogTracksProps } from "./LogTracksProps.interface";
import { FormMode } from "../../enums/formMode"; import { FormMode } from "../../enums/formMode";
import { useIsAuthenticated } from "@azure/msal-react"; import { useIsAuthenticated } from "@azure/msal-react";
import { ILogbookEntry } from "../logbook/ILogbookEntry"; import { ILogbookEntry } from "../logbook/ILogbookEntry";
import ConfirmationDialog from "../confirmationDialog/ConfirmationDialog";
import { initialState, reducer } from "./reducer";
const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTracksProps) => { const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTracksProps) => {
const [tracks, setTracks] = useState<string[]>([]); const [state, dispatch] = useReducer(reducer, initialState)
const [isLoading, setIsLoading] = useState<boolean>(false);
const httpClient: AxiosInstance = useHttpClient(); const httpClient: AxiosInstance = useHttpClient();
const { getAccessToken } = useAccessToken(); const { getAccessToken } = useAccessToken();
const isAuthenticated = useIsAuthenticated(); const isAuthenticated = useIsAuthenticated();
@@ -37,7 +38,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => { const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
try { try {
setIsLoading(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();
@@ -62,11 +63,11 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
const updatedLog = await getLog(); const updatedLog = await getLog();
setTracks(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 {
setIsLoading(false); dispatch({ type: 'SET_IS_LOADING', payload: false });
} }
} }
@@ -74,32 +75,41 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
onOpenClose(FormMode.CANCEL) onOpenClose(FormMode.CANCEL)
} }
const onDelete = async (fileName: string, index: number) => { const onDeleteTrack = async (fileName: string, index: number) => {
dispatch({ type: 'SET_ON_DELETE_TRACK', payload: { isConfirmDialogOpen: true, selectedTrack: { fileName: fileName, index: index }}})
}
const onConfirmDialogConfirm = async () => {
try { try {
const config = await getConfig(); const config = await getConfig();
await httpClient.delete(`api/logs/log/${selectedRowKey}/track?fileName=${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(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();
setTracks(JSON.parse(updatedLog.tracks!)) dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) })
dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false })
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
} }
const onConfirmDialogCancel = async () => {
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();
setTracks(JSON.parse(log.tracks!)); dispatch({ type: 'SET_TRACKS', payload: JSON.parse(log.tracks!) });
} }
updateTracks(); updateTracks();
@@ -125,7 +135,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
<Icon iconName={IconName.XMARK} /> <Icon iconName={IconName.XMARK} />
</IconButton> </IconButton>
</Grid> </Grid>
{tracks.length > 0 && tracks.map((track, index) => { {state.tracks.length > 0 && state.tracks.map((track, index) => {
const trackSplit = track.split('/') const trackSplit = track.split('/')
const filename = trackSplit[trackSplit.length - 1]; const filename = trackSplit[trackSplit.length - 1];
@@ -135,7 +145,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
<TextField disabled={true} fullWidth value={filename} /> <TextField disabled={true} fullWidth value={filename} />
</Grid> </Grid>
<Grid size={1}> <Grid size={1}>
<IconButton onClick={() => onDelete(filename, index)}><Icon iconName={IconName.TRASH} /></IconButton> <IconButton onClick={() => onDeleteTrack(filename, index)}><Icon iconName={IconName.TRASH} /></IconButton>
</Grid> </Grid>
</> </>
) )
@@ -153,16 +163,26 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
{mode.toString() !== FormMode.VIEW && ( {mode.toString() !== FormMode.VIEW && (
<Button <Button
component='label' component='label'
loading={isLoading} loading={state.isLoading}
startIcon={<Icon iconName={IconName.PLUS} />} startIcon={<Icon iconName={IconName.UPLOAD} />}
variant='contained' variant='contained'
> >
Add Track Upload Track
<input hidden onChange={handleFileUpload} type='file' /> <input hidden onChange={handleFileUpload} type='file' />
</Button> </Button>
)} )}
</Grid> </Grid>
</Grid> </Grid>
{state.isConfirmDialogOpen && (
<ConfirmationDialog
contentText="Are you sure you want to delete this track?"
isLoading={state.isConfirmDialogLoading}
isOpen={state.isConfirmDialogOpen}
onCancel={onConfirmDialogCancel}
onConfirm={onConfirmDialogConfirm}
title="Confirm Delete"
/>
)}
</Drawer> </Drawer>
) )
} }

View File

@@ -0,0 +1,10 @@
export interface LogTracksState {
isConfirmDialogOpen: boolean;
isConfirmDialogLoading: boolean;
isLoading: boolean;
selectedTrack: {
fileName: string,
index: number
} | undefined;
tracks: string[];
}

View File

@@ -0,0 +1,55 @@
import { LogTracksState } from "./LogTracksState.interface";
type Action =
| { type: 'SET_IS_CONFIRM_DIALOG_OPEN'; payload: boolean }
| { type: 'SET_IS_CONFORM_DIALOG_LOADING'; payload: boolean }
| { type: 'SET_IS_LOADING'; payload: boolean }
| { type: 'SET_ON_DELETE_TRACK'; payload: { isConfirmDialogOpen: boolean, selectedTrack: { fileName: string, index: number } }}
| { type: 'SET_TRACKS'; payload: string[] };
export const initialState: LogTracksState = {
isConfirmDialogOpen: false,
isConfirmDialogLoading: false,
isLoading: false,
selectedTrack: undefined,
tracks: []
}
export const reducer = (state: LogTracksState, action: Action): LogTracksState => {
switch (action.type) {
case 'SET_IS_CONFIRM_DIALOG_OPEN': {
return {
...state,
isConfirmDialogOpen: action.payload
}
}
case 'SET_IS_CONFORM_DIALOG_LOADING': {
return {
...state,
isConfirmDialogLoading: action.payload
}
}
case 'SET_IS_LOADING': {
return {
...state,
isLoading: action.payload
}
}
case 'SET_ON_DELETE_TRACK': {
return {
...state,
isConfirmDialogOpen: action.payload.isConfirmDialogOpen,
selectedTrack: action.payload.selectedTrack
}
}
case 'SET_TRACKS': {
return {
...state,
tracks: action.payload
}
}
default: {
return state
}
}
}

View File

@@ -197,7 +197,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
}} }}
> >
<FormProvider {...methods}> <FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}> <form onSubmit={methods.handleSubmit(onSubmit)} style={{ paddingBottom: '50px' }}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid size={11}> <Grid size={11}>
<Typography variant="h4">{`${mode.toString().toLowerCase().charAt(0).toUpperCase() + mode.toString().slice(1).toLowerCase()} Pilot`}</Typography> <Typography variant="h4">{`${mode.toString().toLowerCase().charAt(0).toUpperCase() + mode.toString().slice(1).toLowerCase()} Pilot`}</Typography>