adding tracks
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
10
app/src/components/logTracks/LogTracksState.interface.ts
Normal file
10
app/src/components/logTracks/LogTracksState.interface.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export interface LogTracksState {
|
||||||
|
isConfirmDialogOpen: boolean;
|
||||||
|
isConfirmDialogLoading: boolean;
|
||||||
|
isLoading: boolean;
|
||||||
|
selectedTrack: {
|
||||||
|
fileName: string,
|
||||||
|
index: number
|
||||||
|
} | undefined;
|
||||||
|
tracks: string[];
|
||||||
|
}
|
||||||
55
app/src/components/logTracks/reducer.ts
Normal file
55
app/src/components/logTracks/reducer.ts
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user