From 39cfb9ffa2fc60c35deee43d42cc6877a24ff4c8 Mon Sep 17 00:00:00 2001 From: Wilhelm Vold Date: Wed, 13 Nov 2024 10:41:04 +0100 Subject: [PATCH 1/3] feat: adding functionality to upload ini File --- src/api/custom/postIniFile.ts | 26 ++++++++ src/api/generated/index.ts | 4 ++ .../models/AnalogueModelConfigurationDto.ts | 27 ++++++++ .../generated/models/AnalogueModelDetail.ts | 4 +- src/api/generated/models/AnalogueModelList.ts | 2 + .../models/ConfigurationParameterDto.ts | 11 ++++ src/api/generated/models/UploadFileType.ts | 1 + .../models/UploadIniFileCommandResponse.ts | 15 +++++ src/api/generated/models/UploadIniFileDto.ts | 17 +++++ src/api/generated/services/UploadsService.ts | 34 ++++++++++ .../HandleModelComponent.tsx | 14 ++-- .../ModelMetadataComponent.test.tsx | 12 +++- .../ModelMetadata/ModelMetadataHooks.test.tsx | 12 +++- src/hooks/GlobalState.tsx | 7 ++ src/pages/AddModel/AddModel.tsx | 66 +++++++------------ 15 files changed, 202 insertions(+), 50 deletions(-) create mode 100644 src/api/custom/postIniFile.ts create mode 100644 src/api/generated/models/AnalogueModelConfigurationDto.ts create mode 100644 src/api/generated/models/ConfigurationParameterDto.ts create mode 100644 src/api/generated/models/UploadIniFileCommandResponse.ts create mode 100644 src/api/generated/models/UploadIniFileDto.ts diff --git a/src/api/custom/postIniFile.ts b/src/api/custom/postIniFile.ts new file mode 100644 index 00000000..0c837f62 --- /dev/null +++ b/src/api/custom/postIniFile.ts @@ -0,0 +1,26 @@ +import axios from 'axios'; +import { OpenAPI } from '../generated'; +import type { UploadIniFileCommandResponse } from '../generated/models/UploadIniFileCommandResponse'; + +export const postIniFile = async ( + modelId: string, + formData: FormData, +): Promise => { + const token = OpenAPI.TOKEN; // replace with your bearer token + const base = OpenAPI.BASE; + + const response = await axios.post( + `/api/uploads/models/${modelId}/ini-file`, + formData, + { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'multipart/form-data', + }, + baseURL: base, + }, + ); + + // create an object URL for the image blob and return it + return response; +}; diff --git a/src/api/generated/index.ts b/src/api/generated/index.ts index 0532b4b4..9db69b71 100644 --- a/src/api/generated/index.ts +++ b/src/api/generated/index.ts @@ -24,6 +24,7 @@ export type { AddMetadataResponseDto } from './models/AddMetadataResponseDto'; export type { AddParameterDto } from './models/AddParameterDto'; export type { AddStatigraphicGroupForm } from './models/AddStatigraphicGroupForm'; export type { AddStratigraphicGroupCommandResponse } from './models/AddStratigraphicGroupCommandResponse'; +export type { AnalogueModelConfigurationDto } from './models/AnalogueModelConfigurationDto'; export type { AnalogueModelDetail } from './models/AnalogueModelDetail'; export type { AnalogueModelImageDto } from './models/AnalogueModelImageDto'; export type { AnalogueModelList } from './models/AnalogueModelList'; @@ -35,6 +36,7 @@ export type { ComputeCaseInputSettingsDto } from './models/ComputeCaseInputSetti export type { ComputeCaseModelAreaDto } from './models/ComputeCaseModelAreaDto'; export { ComputeJobStatus } from './models/ComputeJobStatus'; export { ComputeType } from './models/ComputeType'; +export type { ConfigurationParameterDto } from './models/ConfigurationParameterDto'; export type { ConvertAnalogueModelCommand } from './models/ConvertAnalogueModelCommand'; export type { ConvertAnalogueModelCommandResponse } from './models/ConvertAnalogueModelCommandResponse'; export type { ConvertAnalogueModelDto } from './models/ConvertAnalogueModelDto'; @@ -154,6 +156,8 @@ export type { UploadChunkCommandResponse } from './models/UploadChunkCommandResp export type { UploadDetail } from './models/UploadDetail'; export { UploadFileCategory } from './models/UploadFileCategory'; export { UploadFileType } from './models/UploadFileType'; +export type { UploadIniFileCommandResponse } from './models/UploadIniFileCommandResponse'; +export type { UploadIniFileDto } from './models/UploadIniFileDto'; export type { UploadList } from './models/UploadList'; export { UploadStatus } from './models/UploadStatus'; diff --git a/src/api/generated/models/AnalogueModelConfigurationDto.ts b/src/api/generated/models/AnalogueModelConfigurationDto.ts new file mode 100644 index 00000000..de3a3f4c --- /dev/null +++ b/src/api/generated/models/AnalogueModelConfigurationDto.ts @@ -0,0 +1,27 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ConfigurationParameterDto } from './ConfigurationParameterDto'; + +export type AnalogueModelConfigurationDto = { + analogueModelConfigurationId?: string; + analogueModelId?: string; + template?: ConfigurationParameterDto; + simStopTime?: ConfigurationParameterDto; + outputInterval?: ConfigurationParameterDto; + basinSlope?: ConfigurationParameterDto; + channelWidth?: ConfigurationParameterDto; + riverLength?: ConfigurationParameterDto; + riverDischargeIni?: ConfigurationParameterDto; + riverDischargeFin?: ConfigurationParameterDto; + tidalAmplitude?: ConfigurationParameterDto; + waveHeightIni?: ConfigurationParameterDto; + waveHeightFin?: ConfigurationParameterDto; + waveDirection?: ConfigurationParameterDto; + subsidenceLand?: ConfigurationParameterDto; + subsidenceSea?: ConfigurationParameterDto; + composition?: ConfigurationParameterDto; +}; + diff --git a/src/api/generated/models/AnalogueModelDetail.ts b/src/api/generated/models/AnalogueModelDetail.ts index 935e3d3a..8df4aff8 100644 --- a/src/api/generated/models/AnalogueModelDetail.ts +++ b/src/api/generated/models/AnalogueModelDetail.ts @@ -3,6 +3,7 @@ /* tslint:disable */ /* eslint-disable */ +import type { AnalogueModelConfigurationDto } from './AnalogueModelConfigurationDto'; import type { AnalogueModelImageDto } from './AnalogueModelImageDto'; import type { AnalogueModelSourceType } from './AnalogueModelSourceType'; import type { GeologicalGroupDto } from './GeologicalGroupDto'; @@ -32,6 +33,7 @@ export type AnalogueModelDetail = { geologicalGroups: Array; outcrops: Array; processingStatus: JobStatus; - analogueModelImage?: AnalogueModelImageDto; + analogueModelImage: AnalogueModelImageDto; + iniParameters: AnalogueModelConfigurationDto; }; diff --git a/src/api/generated/models/AnalogueModelList.ts b/src/api/generated/models/AnalogueModelList.ts index e5ea2ef7..fb32fc21 100644 --- a/src/api/generated/models/AnalogueModelList.ts +++ b/src/api/generated/models/AnalogueModelList.ts @@ -3,6 +3,7 @@ /* tslint:disable */ /* eslint-disable */ +import type { AnalogueModelConfigurationDto } from './AnalogueModelConfigurationDto'; import type { AnalogueModelSourceType } from './AnalogueModelSourceType'; import type { GeologicalGroupDto } from './GeologicalGroupDto'; import type { JobStatus } from './JobStatus'; @@ -21,6 +22,7 @@ export type AnalogueModelList = { stratigraphicGroups: Array; geologicalGroups: Array; outcrops: Array; + iniParameters: AnalogueModelConfigurationDto; analogueModelId: string; name: string; description: string; diff --git a/src/api/generated/models/ConfigurationParameterDto.ts b/src/api/generated/models/ConfigurationParameterDto.ts new file mode 100644 index 00000000..ed7e48c1 --- /dev/null +++ b/src/api/generated/models/ConfigurationParameterDto.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ConfigurationParameterDto = { + name?: string | null; + value?: string | null; + description?: string | null; +}; + diff --git a/src/api/generated/models/UploadFileType.ts b/src/api/generated/models/UploadFileType.ts index 1aff0b08..f4655123 100644 --- a/src/api/generated/models/UploadFileType.ts +++ b/src/api/generated/models/UploadFileType.ts @@ -7,4 +7,5 @@ export enum UploadFileType { NET_CDF = 'NetCDF', RES_QMLEPC = 'ResQMLEpc', RES_QMLDATA = 'ResQMLData', + INI_DATA = 'IniData', } diff --git a/src/api/generated/models/UploadIniFileCommandResponse.ts b/src/api/generated/models/UploadIniFileCommandResponse.ts new file mode 100644 index 00000000..064426d5 --- /dev/null +++ b/src/api/generated/models/UploadIniFileCommandResponse.ts @@ -0,0 +1,15 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { UploadIniFileDto } from './UploadIniFileDto'; + +export type UploadIniFileCommandResponse = { + success?: boolean; + count?: number | null; + message?: string | null; + validationErrors?: Array | null; + data: UploadIniFileDto; +}; + diff --git a/src/api/generated/models/UploadIniFileDto.ts b/src/api/generated/models/UploadIniFileDto.ts new file mode 100644 index 00000000..52ff47f5 --- /dev/null +++ b/src/api/generated/models/UploadIniFileDto.ts @@ -0,0 +1,17 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { UploadFileCategory } from './UploadFileCategory'; +import type { UploadFileType } from './UploadFileType'; +import type { UploadStatus } from './UploadStatus'; + +export type UploadIniFileDto = { + uploadId: string; + originalFileName: string; + uploadStatus: UploadStatus; + uploadFileType: UploadFileType; + uploadFileCategory: UploadFileCategory; +}; + diff --git a/src/api/generated/services/UploadsService.ts b/src/api/generated/services/UploadsService.ts index c50a6f13..427cb335 100644 --- a/src/api/generated/services/UploadsService.ts +++ b/src/api/generated/services/UploadsService.ts @@ -9,6 +9,7 @@ import type { PrepareChunkedUploadCommandResponse } from '../models/PrepareChunk import type { UploadAnalogueModelCommandResponse } from '../models/UploadAnalogueModelCommandResponse'; import type { UploadChunkCommandResponse } from '../models/UploadChunkCommandResponse'; import type { UploadFileType } from '../models/UploadFileType'; +import type { UploadIniFileCommandResponse } from '../models/UploadIniFileCommandResponse'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -155,4 +156,37 @@ export class UploadsService { }); } + /** + * @param id + * @param formData + * @returns UploadIniFileCommandResponse Success + * @throws ApiError + */ + public static postApiUploadsModelsIniFile( + id: string, + formData?: { + ContentType?: string; + ContentDisposition?: string; + Headers?: Record>; + Length?: number; + Name?: string; + FileName?: string; + }, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/uploads/models/{id}/ini-file', + path: { + 'id': id, + }, + formData: formData, + mediaType: 'multipart/form-data', + errors: { + 400: `Bad Request`, + 403: `Forbidden`, + 404: `Not Found`, + }, + }); + } + } diff --git a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx index 41190b92..216968b8 100644 --- a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx +++ b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx @@ -25,7 +25,11 @@ import { Icon.add({ error_outlined }); interface AddModelDialogProps { - confirm?: (file: File, metadata: AnalogueModelDetail) => Promise; + confirm?: ( + file: File, + metadata: AnalogueModelDetail, + iniFile?: File, + ) => Promise; progress?: number; uploading?: boolean; isAddUploading?: boolean; @@ -109,16 +113,16 @@ export const HandleModelComponent = ({ }; const finishSubmit = () => { - if (files.NC && confirm) { - confirm(files.NC, metadata); - } + if (files.NC && confirm && files.INI) { + confirm(files.NC, metadata, files.INI); + } else if (files.NC && confirm) confirm(files.NC, metadata); cleanupStates(); }; if (Object.keys(errors).length === 0 && submitting) { finishSubmit(); } - }, [confirm, errors, files.NC, metadata, submitting]); + }, [confirm, errors, files, metadata, submitting]); function toggleINIFileContent() { setFileDisplay(!isFileDisplay); diff --git a/src/features/HandleModel/ModelMetadata/ModelMetadataComponent.test.tsx b/src/features/HandleModel/ModelMetadata/ModelMetadataComponent.test.tsx index c86d1ebe..6d46675b 100644 --- a/src/features/HandleModel/ModelMetadata/ModelMetadataComponent.test.tsx +++ b/src/features/HandleModel/ModelMetadata/ModelMetadataComponent.test.tsx @@ -3,7 +3,11 @@ import { MsalProvider } from '@azure/msal-react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { cleanup, render, screen } from '@testing-library/react'; import { MsalReactTester } from 'msal-react-tester'; -import { AnalogueModelSourceType, JobStatus } from '../../../api/generated'; +import { + AnalogueModelSourceType, + FileType, + JobStatus, +} from '../../../api/generated'; import { useFetchOutcrops } from '../../../hooks/useFetchOutcrops'; import { ModelMetadata } from './ModelMetadata'; @@ -21,6 +25,12 @@ const mockMetadata = { modelAreas: [], stratigraphicGroups: [], geologicalGroups: [], + analogueModelImage: { + analogueModelImageId: '', + fileName: '', + type: FileType.JPG, + }, + iniParameters: {}, processingStatus: JobStatus.SUCCEEDED, }; const errors = {}; diff --git a/src/features/HandleModel/ModelMetadata/ModelMetadataHooks.test.tsx b/src/features/HandleModel/ModelMetadata/ModelMetadataHooks.test.tsx index 8ed635d3..72c24d71 100644 --- a/src/features/HandleModel/ModelMetadata/ModelMetadataHooks.test.tsx +++ b/src/features/HandleModel/ModelMetadata/ModelMetadataHooks.test.tsx @@ -5,7 +5,11 @@ import * as ReactQuery from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { cleanup, renderHook, waitFor } from '@testing-library/react'; import { MsalReactTester } from 'msal-react-tester'; -import { AnalogueModelSourceType, JobStatus } from '../../../api/generated'; +import { + AnalogueModelSourceType, + FileType, + JobStatus, +} from '../../../api/generated'; import { useFetchOutcrops } from '../../../hooks/useFetchOutcrops'; import { ModelMetadata } from './ModelMetadata'; @@ -23,6 +27,12 @@ const mockMetadata = { modelAreas: [], stratigraphicGroups: [], geologicalGroups: [], + analogueModelImage: { + analogueModelImageId: '', + fileName: '', + type: FileType.JPG, + }, + iniParameters: {}, processingStatus: JobStatus.SUCCEEDED, }; const errors = {}; diff --git a/src/hooks/GlobalState.tsx b/src/hooks/GlobalState.tsx index b8d3da0f..2b5b4172 100644 --- a/src/hooks/GlobalState.tsx +++ b/src/hooks/GlobalState.tsx @@ -6,6 +6,7 @@ import { ComputeCaseDto, CountryDto, FieldDto, + FileType, GeologicalStandardDto, JobStatus, ListComputeSettingsMethodDto, @@ -32,6 +33,12 @@ export const analogueModelDefault: AnalogueModelDetail = { stratigraphicGroups: [], geologicalGroups: [], outcrops: [], + analogueModelImage: { + analogueModelImageId: '', + fileName: '', + type: FileType.JPG, + }, + iniParameters: {}, processingStatus: JobStatus.UNKNOWN, }; diff --git a/src/pages/AddModel/AddModel.tsx b/src/pages/AddModel/AddModel.tsx index 2807eb1f..8e2fd50d 100644 --- a/src/pages/AddModel/AddModel.tsx +++ b/src/pages/AddModel/AddModel.tsx @@ -22,6 +22,7 @@ import { HandleModelComponent } from '../../features/HandleModel/HandleModelComp import { SidePane } from '../../features/HandleModel/SidePane/SidePane'; import { ModelMetadataView } from '../../features/ModelView/ModelMetadataView/ModelMetadataView'; import * as Styled from './AddModel.styled'; +import { postIniFile } from '../../api/custom/postIniFile'; enum UploadProcess { SUCCESS = 'Model successfully uploaded and is now beeing processed.', @@ -34,15 +35,6 @@ export const AddModel = () => { const [progress, setProgress] = useState(0); const [modelId, setModelId] = useState(''); const [uploading, setUploading] = useState(false); - - // Hard coded states for ease of development - - // const [progress, setProgress] = useState(12); - // const [modelId, setModelId] = useState( - // 'fa725ca1-ca33-4b7c-e742-08dc7b2938d0', - // ); - // const [uploading, setUploading] = useState(true); - const [counter, setCounter] = useState(defaultCounterValue); const [fileToBeUpload, setFileToBeUpload] = useState(); const [beginingOfTheChunk, setBeginingOfTheChunk] = useState( @@ -84,6 +76,18 @@ export const AddModel = () => { }, }); + const uploadIniFile = useMutation({ + mutationFn: ({ + id, + requestBody, + }: { + id: string; + requestBody: FormData; + }) => { + return postIniFile(id, requestBody); + }, + }); + const uploadModelMetadata = useMutation({ mutationFn: ({ id, @@ -99,23 +103,7 @@ export const AddModel = () => { }, }); - // const uploadModelAnalouges = useMutation({ - // mutationFn: ({ - // id, - // requestBody, - // }: { - // id: string; - // requestBody: AddAnalogueModelAnalogueCommandForm; - // }) => { - // return AnalogueModelAnaloguesService.putApiAnalogueModelsAnalogues( - // id, - // requestBody, - // ); - // }, - // }); - const metadataList: AddMetadataDto[] = []; - // const analougueList: AddAnalogueDto[] = []; function addMetadataFields(metadata?: MetadataDto[]) { if (!metadata) return; @@ -123,39 +111,27 @@ export const AddModel = () => { metadataList.push(...obj); } - // function addAnalogueFields(metadata?: AnalogueList[]) { - // if (!metadata) return; - // const obj = metadata.map((x) => ({ analogueId: x.analogueId })); - // analougueList.push(...obj); - // } - async function uploadMetadata( modelId: string, metadata: AnalogueModelDetail, ) { addMetadataFields(metadata.metadata); - // addAnalogueFields(metadata.analogues); const readyMetadata: AddAnalogueModelMetadataCommandForm = { metadata: metadataList, }; - // const readyAnalogue: AddAnalogueModelAnalogueCommandForm = { - // analogues: analougueList, - // }; - await uploadModelMetadata.mutateAsync({ id: modelId, requestBody: readyMetadata, }); - - // await uploadModelAnalouges.mutateAsync({ - // id: modelId, - // requestBody: readyAnalogue, - // }); } - async function uploadModel(file: File, metadata: AnalogueModelDetail) { + async function uploadModel( + file: File, + metadata: AnalogueModelDetail, + iniFile?: File, + ) { setUploading(true); const ModelBody: CreateAnalogueModelCommand = { name: metadata.name ? metadata.name : '', @@ -202,6 +178,12 @@ export const AddModel = () => { setFileToBeUpload(file); setFileSize(file.size); } + + if (iniFile && modelId) { + const data = new FormData(); + data.append('file', iniFile); + await uploadIniFile.mutateAsync({ id: modelId, requestBody: data }); + } } } From 78676b7cbbc7b1d03a2cf46ab0a47ac57f66790d Mon Sep 17 00:00:00 2001 From: Wilhelm Vold Date: Thu, 14 Nov 2024 13:50:14 +0100 Subject: [PATCH 2/3] feat: ini file --- .../IniParametersDialog.style.tsx | 25 ++++++ .../IniParametersDialog.tsx | 81 +++++++++++++++++++ .../FileRow.styled.tsx} | 0 .../FileColumn.tsx => FileRow/FileRow.tsx} | 4 +- .../HandleModel/FileUploader/FileUploader.tsx | 7 +- .../HandleModelComponent.hooks.ts | 12 --- .../HandleModelComponent.styled.ts | 7 ++ .../HandleModelComponent.tsx | 35 ++++---- .../ModelInputFilesTable.tsx | 13 ++- .../ModelMetadataView.styled.tsx | 14 ++++ .../ModelMetadataView/ModelMetadataView.tsx | 12 +++ src/pages/AddModel/AddModel.tsx | 34 +++++++- src/utils/ReadIniFile.ts | 15 ++++ 13 files changed, 216 insertions(+), 43 deletions(-) create mode 100644 src/components/IniParametersDialog/IniParametersDialog.style.tsx create mode 100644 src/components/IniParametersDialog/IniParametersDialog.tsx rename src/features/HandleModel/{FileColumn/FileColumn.styled.tsx => FileRow/FileRow.styled.tsx} (100%) rename src/features/HandleModel/{FileColumn/FileColumn.tsx => FileRow/FileRow.tsx} (96%) create mode 100644 src/utils/ReadIniFile.ts diff --git a/src/components/IniParametersDialog/IniParametersDialog.style.tsx b/src/components/IniParametersDialog/IniParametersDialog.style.tsx new file mode 100644 index 00000000..df4396d0 --- /dev/null +++ b/src/components/IniParametersDialog/IniParametersDialog.style.tsx @@ -0,0 +1,25 @@ +import { Accordion, Dialog } from '@equinor/eds-core-react'; +import { styled } from 'styled-components'; + +export const IniParamDialog = styled(Dialog)` + display: flex; + flex-direction: column; + width: 50vw; +`; + +export const IniParamAccordion = styled(Accordion)` + display: flex; + flex-direction: column; + height: 100%; +`; + +export const IniParamTable = styled.div` + display: grid; + overflow: auto; +`; + +export const IniDialogContent = styled(Dialog.CustomContent)` + display: flex; + flex-direction: column; + height: 40vh; +`; diff --git a/src/components/IniParametersDialog/IniParametersDialog.tsx b/src/components/IniParametersDialog/IniParametersDialog.tsx new file mode 100644 index 00000000..1ce1c59d --- /dev/null +++ b/src/components/IniParametersDialog/IniParametersDialog.tsx @@ -0,0 +1,81 @@ +import { Accordion, Button, Dialog, Table } from '@equinor/eds-core-react'; +import { useState } from 'react'; +import { AnalogueModelConfigurationDto } from '../../api/generated'; +import { + IniDialogContent, + IniParamAccordion, + IniParamDialog, + IniParamTable, +} from './IniParametersDialog.style'; + +export function IniParametersDialog(props: { + iniParameters: AnalogueModelConfigurationDto; +}) { + const [isOpen, setIsOpen] = useState(false); + + const handleOpen = () => { + setIsOpen(true); + }; + const handleClose = () => { + setIsOpen(false); + }; + + return ( + <> + + + + Ini Parameters + + + + {Object.entries(props.iniParameters) + .filter(([key, value]) => typeof value !== 'string') + .map(([key, parameter]) => ( + + + {key.charAt(0).toUpperCase() + + String(key) + .slice(1) + .replace(/([A-Z][a-z])/g, ' $1') + .trim()} + + + + + + + + Name + + + Value + + + + + {Object.entries(parameter) + .filter(([key, value]) => value !== '') + .map(([key, value]) => ( + + {key} + {value} + + ))} + +
+
+
+
+ ))} +
+
+ + + +
+ + ); +} diff --git a/src/features/HandleModel/FileColumn/FileColumn.styled.tsx b/src/features/HandleModel/FileRow/FileRow.styled.tsx similarity index 100% rename from src/features/HandleModel/FileColumn/FileColumn.styled.tsx rename to src/features/HandleModel/FileRow/FileRow.styled.tsx diff --git a/src/features/HandleModel/FileColumn/FileColumn.tsx b/src/features/HandleModel/FileRow/FileRow.tsx similarity index 96% rename from src/features/HandleModel/FileColumn/FileColumn.tsx rename to src/features/HandleModel/FileRow/FileRow.tsx index ef37e77a..057ae4e6 100644 --- a/src/features/HandleModel/FileColumn/FileColumn.tsx +++ b/src/features/HandleModel/FileRow/FileRow.tsx @@ -3,7 +3,7 @@ import { delete_to_trash as deleteIcon } from '@equinor/eds-icons'; import { ChangeEvent } from 'react'; import IconButton from '../../../components/IconButton/IconButton'; import { FileUploader } from '../FileUploader/FileUploader'; -import * as Styled from './FileColumn.styled'; +import * as Styled from './FileRow.styled'; type FileDisplay = { isVisible: boolean; toggle: () => void }; @@ -15,7 +15,7 @@ interface FileColumnProps { fileDisplay?: FileDisplay; fileSize?: number; } -export const FileColumn = ({ +export const FileRow = ({ onChange, onDelete, INI, diff --git a/src/features/HandleModel/FileUploader/FileUploader.tsx b/src/features/HandleModel/FileUploader/FileUploader.tsx index ec114097..a53e9687 100644 --- a/src/features/HandleModel/FileUploader/FileUploader.tsx +++ b/src/features/HandleModel/FileUploader/FileUploader.tsx @@ -27,7 +27,10 @@ export const FileUploader = ({ <>{file.name} ) : (
- + {INI && ( )} @@ -36,7 +39,7 @@ export const FileUploader = ({ {INI && '(optional)'} >, setMetadata: React.Dispatch>, - files: FilesProps, - rawFile?: File, existingData?: AnalogueModelDetail, ) => { - useEffect(() => { - if (rawFile === undefined) return; - setFileSize(rawFile.size); - }, [rawFile, setFileSize]); - - useEffect(() => { - if (files.NC === undefined) setFileSize(0); - }, [files, setFileSize]); - useEffect(() => { if (existingData) setMetadata(existingData); }, [existingData, setMetadata]); diff --git a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.styled.ts b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.styled.ts index 36842143..c8a624f2 100644 --- a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.styled.ts +++ b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.styled.ts @@ -1,6 +1,7 @@ import styled from 'styled-components'; import { spacings } from '../../../tokens/spacings'; import { theme } from '../../../tokens/theme'; +import { TextField } from '@equinor/eds-core-react'; export const Wrapper = styled.div` display: flex; @@ -52,3 +53,9 @@ export const InfoNavigation = styled.div` row-gap: ${spacings.MEDIUM}; `; + +export const IniFileTextField = styled(TextField)` + display: flex; + flex-direction: column; + row-gap: ${spacings.MEDIUM}; +`; diff --git a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx index 747887d9..b2d55a62 100644 --- a/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx +++ b/src/features/HandleModel/HandleModelComponent/HandleModelComponent.tsx @@ -22,6 +22,8 @@ import { analogueModelDefault, usePepmContextStore, } from '../../../hooks/GlobalState'; +import { readFileAsText } from '../../../utils/ReadIniFile'; +import { IniFileTextField } from './HandleModelComponent.styled'; Icon.add({ error_outlined }); interface AddModelDialogProps { @@ -68,28 +70,20 @@ export const HandleModelComponent = ({ progress, uploading, isAddUploading, - existingData, modelId, }: AddModelDialogProps) => { const { setAnalogueModelDefault } = usePepmContextStore(); const [isFileDisplay, setFileDisplay] = useState(false); const [files, setFiles] = useState(defaultFiles); + const [iniFileString, setIniFileString] = useState(); const [metadata, setMetadata] = useState(analogueModelDefault); const [submitting, setSubmitting] = useState(false); - const [fileSize, setFileSize] = useState(0); - const [rawFile, setrawFile] = useState(); const [errors, setErrors] = useState({}); const navigate = useNavigate(); - useHandleModelComponent( - setFileSize, - setMetadata, - files, - rawFile, - existingData, - ); + useHandleModelComponent(setMetadata); const handleSubmit = () => { setErrors(validateValues(metadata, files)); @@ -101,14 +95,11 @@ export const HandleModelComponent = ({ const file = e.target.files[0]; const type = e.target.name; setFiles({ ...files, [type]: file }); - setrawFile(e.target.files[0]); }; useEffect(() => { const cleanupStates = () => { setFiles(defaultFiles); - setrawFile(undefined); - setFileSize(0); setSubmitting(false); }; @@ -127,7 +118,14 @@ export const HandleModelComponent = ({ function toggleINIFileContent() { setFileDisplay(!isFileDisplay); } - const INIFileContent = () =>

Not implemented yet...

; + + useEffect(() => { + if (files.INI && iniFileString === undefined) { + readFileAsText(files.INI).then((val) => { + setIniFileString(val); + }); + } + }, [files, iniFileString]); return ( @@ -143,11 +141,16 @@ export const HandleModelComponent = ({ isVisible: isFileDisplay, toggle: toggleINIFileContent, }} - fileSize={fileSize} fileChange={fileAdded} /> )} - {isFileDisplay && } + {isFileDisplay && iniFileString && !uploading && ( +
+ + {iniFileString} + +
+ )} {!isAddUploading && ( <> void }; @@ -8,18 +8,16 @@ export const ModelInputFilesTable = ({ fileDisplay, files, setFiles, - fileSize, fileChange, }: { fileDisplay: FileDisplay; - files: { NC?: File; INI?: File }; + files: { INI?: File; NC?: File }; setFiles: React.Dispatch< React.SetStateAction<{ NC?: File | undefined; INI?: File | undefined; }> >; - fileSize: number; fileChange: (e: React.ChangeEvent) => void; }) => { return ( @@ -33,18 +31,19 @@ export const ModelInputFilesTable = ({ - setFiles({ ...files, NC: undefined })} - fileSize={fileSize} + fileSize={files.NC?.size} /> - setFiles({ ...files, INI: undefined })} fileDisplay={fileDisplay} + fileSize={files.INI?.size} /> diff --git a/src/features/ModelView/ModelMetadataView/ModelMetadataView.styled.tsx b/src/features/ModelView/ModelMetadataView/ModelMetadataView.styled.tsx index d43d6caf..abc22bda 100644 --- a/src/features/ModelView/ModelMetadataView/ModelMetadataView.styled.tsx +++ b/src/features/ModelView/ModelMetadataView/ModelMetadataView.styled.tsx @@ -9,6 +9,20 @@ export const DescriptionMeta = styled.div` row-gap: ${spacings.MEDIUM}; `; +export const IniParameters = styled.div` + display: flex; + flex-direction: column; + max-width: 50%; + row-gap: ${spacings.MEDIUM}; +`; + +export const IniParametersWrapper = styled.div` + display: flex; + flex-direction: column; + + row-gap: ${spacings.MEDIUM}; +`; + export const ModelImageView = styled.div` display: flex; flex-direction: column; diff --git a/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx b/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx index ad58f286..75c339cd 100644 --- a/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx +++ b/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx @@ -34,6 +34,8 @@ import { useFetchSmdaStratigraphicColumns, } from '../../../hooks/useFetchStratColData'; import { useFetchGrossDepData } from '../../../hooks/useFetchGrossDepData'; +import { IniParametersDialog } from '../../../components/IniParametersDialog/IniParametersDialog'; +import { IniParametersWrapper } from './ModelMetadataView.styled'; export const ModelMetadataView = ({ modelIdParent, @@ -352,6 +354,16 @@ export const ModelMetadataView = ({ Model metadata + {analogueModel.iniParameters && uploadingProgress === undefined && ( + + + Ini Parameters + +
+ +
+
+ )}
diff --git a/src/pages/AddModel/AddModel.tsx b/src/pages/AddModel/AddModel.tsx index 8e2fd50d..1d531ea0 100644 --- a/src/pages/AddModel/AddModel.tsx +++ b/src/pages/AddModel/AddModel.tsx @@ -36,6 +36,9 @@ export const AddModel = () => { const [modelId, setModelId] = useState(''); const [uploading, setUploading] = useState(false); const [counter, setCounter] = useState(defaultCounterValue); + const [iniFile, setIniFile] = useState(); + const [iniFileUploading, setIniFileUploading] = useState(false); + const [iniFileSucceeded, setIniFileSucceeded] = useState(false); const [fileToBeUpload, setFileToBeUpload] = useState(); const [beginingOfTheChunk, setBeginingOfTheChunk] = useState( defaultBeginningOfchunk, @@ -179,10 +182,8 @@ export const AddModel = () => { setFileSize(file.size); } - if (iniFile && modelId) { - const data = new FormData(); - data.append('file', iniFile); - await uploadIniFile.mutateAsync({ id: modelId, requestBody: data }); + if (iniFile) { + setIniFile(iniFile); } } } @@ -254,6 +255,31 @@ export const AddModel = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [fileToBeUpload, progress]); + useEffect(() => { + const uploadIniFileAsync = async (file: File, id: string) => { + const data = new FormData(); + data.append('file', file!); + const response = await uploadIniFile.mutateAsync({ + id: id, + requestBody: data, + }); + return response; + }; + + if (!iniFileUploading && !iniFileSucceeded && iniFile && modelId) { + setIniFileUploading(true); + const response = uploadIniFileAsync(iniFile, modelId); + response.then( + (res) => { + setIniFileSucceeded(true); + }, + () => { + setIniFileUploading(false); + }, + ); + } + }, [modelId, iniFile, iniFileUploading, iniFileSucceeded, uploadIniFile]); + function clearStatus() { setUploadStatus(undefined); } diff --git a/src/utils/ReadIniFile.ts b/src/utils/ReadIniFile.ts new file mode 100644 index 00000000..72b3f0c0 --- /dev/null +++ b/src/utils/ReadIniFile.ts @@ -0,0 +1,15 @@ +export function readFileAsText(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result as string); + }; + + reader.onerror = () => { + reject(reader.error); + }; + + reader.readAsText(file); + }); +} From 3d471851d87961b3539bb88dc4c5fb50bbfea3c5 Mon Sep 17 00:00:00 2001 From: Wilhelm Vold Date: Thu, 14 Nov 2024 14:06:17 +0100 Subject: [PATCH 3/3] chore: moved files --- .../AreaCoordinates/AreaCoordinates.styled.tsx | 0 .../AreaCoordinates/AreaCoordinates.tsx | 4 ++-- .../AreaCoordinates/CoordinateInput/CoordinateInput.tsx | 0 .../AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx | 0 .../AreaCoordinates}/ErrorMessage/ErrorMessage.tsx | 2 +- .../ImageView/AnalogueModelImageView.styled.tsx | 4 ++-- .../AreaCoordinates}/ImageView/AnalogueModelImageView.tsx | 4 ++-- .../ImageView/ModelImageCanvas/ModelImageCanvas.tsx | 4 ++-- .../AreaCoordinates/hooks/AreaCoordinates.hooks.ts | 0 .../AreaCoordinates/hooks/useModelResults.tsx | 0 .../tests/AreaCoordinates.components.testNo.tsx | 0 .../AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx | 0 .../AreaCoordinates/tests/mockedData.ts | 0 .../IniParametersDialog/IniParametersDialog.style.tsx | 0 .../ModelView}/IniParametersDialog/IniParametersDialog.tsx | 2 +- .../ModelView/ModelMetadataView/ModelMetadataView.tsx | 2 +- src/features/ModelView/ModelView.tsx | 2 +- 17 files changed, 12 insertions(+), 12 deletions(-) rename src/{components => features}/AreaCoordinates/AreaCoordinates.styled.tsx (100%) rename src/{components => features}/AreaCoordinates/AreaCoordinates.tsx (98%) rename src/{components => features}/AreaCoordinates/CoordinateInput/CoordinateInput.tsx (100%) rename src/{components => features}/AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx (100%) rename src/{components => features/AreaCoordinates}/ErrorMessage/ErrorMessage.tsx (92%) rename src/{components => features/AreaCoordinates}/ImageView/AnalogueModelImageView.styled.tsx (85%) rename src/{components => features/AreaCoordinates}/ImageView/AnalogueModelImageView.tsx (85%) rename src/{components => features/AreaCoordinates}/ImageView/ModelImageCanvas/ModelImageCanvas.tsx (97%) rename src/{components => features}/AreaCoordinates/hooks/AreaCoordinates.hooks.ts (100%) rename src/{components => features}/AreaCoordinates/hooks/useModelResults.tsx (100%) rename src/{components => features}/AreaCoordinates/tests/AreaCoordinates.components.testNo.tsx (100%) rename src/{components => features}/AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx (100%) rename src/{components => features}/AreaCoordinates/tests/mockedData.ts (100%) rename src/{components => features/ModelView}/IniParametersDialog/IniParametersDialog.style.tsx (100%) rename src/{components => features/ModelView}/IniParametersDialog/IniParametersDialog.tsx (97%) diff --git a/src/components/AreaCoordinates/AreaCoordinates.styled.tsx b/src/features/AreaCoordinates/AreaCoordinates.styled.tsx similarity index 100% rename from src/components/AreaCoordinates/AreaCoordinates.styled.tsx rename to src/features/AreaCoordinates/AreaCoordinates.styled.tsx diff --git a/src/components/AreaCoordinates/AreaCoordinates.tsx b/src/features/AreaCoordinates/AreaCoordinates.tsx similarity index 98% rename from src/components/AreaCoordinates/AreaCoordinates.tsx rename to src/features/AreaCoordinates/AreaCoordinates.tsx index bc61401f..1396df9d 100644 --- a/src/components/AreaCoordinates/AreaCoordinates.tsx +++ b/src/features/AreaCoordinates/AreaCoordinates.tsx @@ -16,8 +16,6 @@ import { ModelAreaTypeDto, } from '../../api/generated'; import { useMutateAreaCoordinates } from '../../hooks/useMutateAreaCoordinates'; -import { ErrorMessage } from '../ErrorMessage/ErrorMessage'; -import { AnalogueModelImageView } from '../ImageView/AnalogueModelImageView'; import * as Styled from './AreaCoordinates.styled'; import { CoordinateInput } from './CoordinateInput/CoordinateInput'; import { @@ -29,6 +27,8 @@ import { analogueModelDefault, usePepmContextStore, } from '../../hooks/GlobalState'; +import { ErrorMessage } from './ErrorMessage/ErrorMessage'; +import { AnalogueModelImageView } from './ImageView/AnalogueModelImageView'; export type AreaCoordinateType = { modelAreaId: string; diff --git a/src/components/AreaCoordinates/CoordinateInput/CoordinateInput.tsx b/src/features/AreaCoordinates/CoordinateInput/CoordinateInput.tsx similarity index 100% rename from src/components/AreaCoordinates/CoordinateInput/CoordinateInput.tsx rename to src/features/AreaCoordinates/CoordinateInput/CoordinateInput.tsx diff --git a/src/components/AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx b/src/features/AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx similarity index 100% rename from src/components/AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx rename to src/features/AreaCoordinates/CoordinatesDialog/CoordinatesDialog.tsx diff --git a/src/components/ErrorMessage/ErrorMessage.tsx b/src/features/AreaCoordinates/ErrorMessage/ErrorMessage.tsx similarity index 92% rename from src/components/ErrorMessage/ErrorMessage.tsx rename to src/features/AreaCoordinates/ErrorMessage/ErrorMessage.tsx index 61693990..0d307023 100644 --- a/src/components/ErrorMessage/ErrorMessage.tsx +++ b/src/features/AreaCoordinates/ErrorMessage/ErrorMessage.tsx @@ -1,5 +1,5 @@ import { Typography } from '@equinor/eds-core-react'; -import { CoordinateErrorType } from '../AreaCoordinates/hooks/AreaCoordinates.hooks'; +import { CoordinateErrorType } from '../hooks/AreaCoordinates.hooks'; export const ErrorMessage = ({ errors }: { errors: CoordinateErrorType }) => { return ( diff --git a/src/components/ImageView/AnalogueModelImageView.styled.tsx b/src/features/AreaCoordinates/ImageView/AnalogueModelImageView.styled.tsx similarity index 85% rename from src/components/ImageView/AnalogueModelImageView.styled.tsx rename to src/features/AreaCoordinates/ImageView/AnalogueModelImageView.styled.tsx index 7103758d..516f5a72 100644 --- a/src/components/ImageView/AnalogueModelImageView.styled.tsx +++ b/src/features/AreaCoordinates/ImageView/AnalogueModelImageView.styled.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { spacings } from '../../tokens/spacings'; -import { theme } from '../../tokens/theme'; +import { theme } from '../../../tokens/theme'; +import { spacings } from '../../../tokens/spacings'; export const ImageWrapper = styled.div` display: flex; diff --git a/src/components/ImageView/AnalogueModelImageView.tsx b/src/features/AreaCoordinates/ImageView/AnalogueModelImageView.tsx similarity index 85% rename from src/components/ImageView/AnalogueModelImageView.tsx rename to src/features/AreaCoordinates/ImageView/AnalogueModelImageView.tsx index dff6cd11..669ab90c 100644 --- a/src/components/ImageView/AnalogueModelImageView.tsx +++ b/src/features/AreaCoordinates/ImageView/AnalogueModelImageView.tsx @@ -1,8 +1,8 @@ import { Typography } from '@equinor/eds-core-react'; -import { AreaCoordinateType } from '../AreaCoordinates/AreaCoordinates'; +import { AreaCoordinateType } from '../../AreaCoordinates/AreaCoordinates'; import { ModelImageCanvas } from './ModelImageCanvas/ModelImageCanvas'; import { CanvasWrapper } from './AnalogueModelImageView.styled'; -import { usePepmContextStore } from '../../hooks/GlobalState'; +import { usePepmContextStore } from '../../../hooks/GlobalState'; export const AnalogueModelImageView = ({ coordinateBox, diff --git a/src/components/ImageView/ModelImageCanvas/ModelImageCanvas.tsx b/src/features/AreaCoordinates/ImageView/ModelImageCanvas/ModelImageCanvas.tsx similarity index 97% rename from src/components/ImageView/ModelImageCanvas/ModelImageCanvas.tsx rename to src/features/AreaCoordinates/ImageView/ModelImageCanvas/ModelImageCanvas.tsx index 7b45c007..4b97ed5a 100644 --- a/src/components/ImageView/ModelImageCanvas/ModelImageCanvas.tsx +++ b/src/features/AreaCoordinates/ImageView/ModelImageCanvas/ModelImageCanvas.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; -import { ImageMetadataDto } from '../../../api/generated'; -import { AreaCoordinateType } from '../../AreaCoordinates/AreaCoordinates'; +import { AreaCoordinateType } from '../../../AreaCoordinates/AreaCoordinates'; +import { ImageMetadataDto } from '../../../../api/generated'; export const ModelImageCanvas = ({ imageData, diff --git a/src/components/AreaCoordinates/hooks/AreaCoordinates.hooks.ts b/src/features/AreaCoordinates/hooks/AreaCoordinates.hooks.ts similarity index 100% rename from src/components/AreaCoordinates/hooks/AreaCoordinates.hooks.ts rename to src/features/AreaCoordinates/hooks/AreaCoordinates.hooks.ts diff --git a/src/components/AreaCoordinates/hooks/useModelResults.tsx b/src/features/AreaCoordinates/hooks/useModelResults.tsx similarity index 100% rename from src/components/AreaCoordinates/hooks/useModelResults.tsx rename to src/features/AreaCoordinates/hooks/useModelResults.tsx diff --git a/src/components/AreaCoordinates/tests/AreaCoordinates.components.testNo.tsx b/src/features/AreaCoordinates/tests/AreaCoordinates.components.testNo.tsx similarity index 100% rename from src/components/AreaCoordinates/tests/AreaCoordinates.components.testNo.tsx rename to src/features/AreaCoordinates/tests/AreaCoordinates.components.testNo.tsx diff --git a/src/components/AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx b/src/features/AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx similarity index 100% rename from src/components/AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx rename to src/features/AreaCoordinates/tests/AreaCoordinates.hooks.testNo.tsx diff --git a/src/components/AreaCoordinates/tests/mockedData.ts b/src/features/AreaCoordinates/tests/mockedData.ts similarity index 100% rename from src/components/AreaCoordinates/tests/mockedData.ts rename to src/features/AreaCoordinates/tests/mockedData.ts diff --git a/src/components/IniParametersDialog/IniParametersDialog.style.tsx b/src/features/ModelView/IniParametersDialog/IniParametersDialog.style.tsx similarity index 100% rename from src/components/IniParametersDialog/IniParametersDialog.style.tsx rename to src/features/ModelView/IniParametersDialog/IniParametersDialog.style.tsx diff --git a/src/components/IniParametersDialog/IniParametersDialog.tsx b/src/features/ModelView/IniParametersDialog/IniParametersDialog.tsx similarity index 97% rename from src/components/IniParametersDialog/IniParametersDialog.tsx rename to src/features/ModelView/IniParametersDialog/IniParametersDialog.tsx index 1ce1c59d..f3bb9e9f 100644 --- a/src/components/IniParametersDialog/IniParametersDialog.tsx +++ b/src/features/ModelView/IniParametersDialog/IniParametersDialog.tsx @@ -1,6 +1,6 @@ import { Accordion, Button, Dialog, Table } from '@equinor/eds-core-react'; import { useState } from 'react'; -import { AnalogueModelConfigurationDto } from '../../api/generated'; +import { AnalogueModelConfigurationDto } from '../../../api/generated'; import { IniDialogContent, IniParamAccordion, diff --git a/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx b/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx index 75c339cd..4a255a9e 100644 --- a/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx +++ b/src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx @@ -34,7 +34,7 @@ import { useFetchSmdaStratigraphicColumns, } from '../../../hooks/useFetchStratColData'; import { useFetchGrossDepData } from '../../../hooks/useFetchGrossDepData'; -import { IniParametersDialog } from '../../../components/IniParametersDialog/IniParametersDialog'; +import { IniParametersDialog } from '../IniParametersDialog/IniParametersDialog'; import { IniParametersWrapper } from './ModelMetadataView.styled'; export const ModelMetadataView = ({ diff --git a/src/features/ModelView/ModelView.tsx b/src/features/ModelView/ModelView.tsx index 4282d89f..2b2d9ec6 100644 --- a/src/features/ModelView/ModelView.tsx +++ b/src/features/ModelView/ModelView.tsx @@ -1,10 +1,10 @@ import { useState } from 'react'; -import { CoordinatesDialog } from '../../components/AreaCoordinates/CoordinatesDialog/CoordinatesDialog'; import { ModelMetadataView } from '../../features/ModelView/ModelMetadataView/ModelMetadataView'; import { DeleteModel } from './DeleteButton/DeleteModel'; import { ModelAreaCoordinates } from './ModelAreaCoordinates/ModelAreaCoordinates'; import { ModelFilesView } from './ModelFilesView/ModelFilesView'; import * as Styled from './ModelView.styled'; +import { CoordinatesDialog } from '../AreaCoordinates/CoordinatesDialog/CoordinatesDialog'; export const ModelView = () => { const [open, setOpen] = useState(false);