Skip to content

Commit

Permalink
Feat/model page (#89)
Browse files Browse the repository at this point in the history
* chore: add fetchModel function

* chore: Add model view component

* chore: Add model image view component

* chore: Add model metadata view component

* chore: Add model name component

* chore: Add model navigation component, closes #62

* chore: Add model source view component

* feat: Add model page, closes #61

* chore: Button to view model page

* Update src/features/ModelView/ModelNavigationBar/ModelNavigationBar.tsx

Co-authored-by: Olava Faksdal <38139899+olavis@users.noreply.github.com>

* Update src/features/ModelView/ModelView.styled.tsx

Co-authored-by: Olava Faksdal <38139899+olavis@users.noreply.github.com>

* refactor: Removed empty styled file

* refactor: Grouped model pages in folder, updated imports

* fix: fixed typo, updated import

---------

Co-authored-by: Olava Faksdal <38139899+olavis@users.noreply.github.com>
  • Loading branch information
mheggelund and olavis authored Sep 19, 2023
1 parent 9f126c7 commit 87276f1
Show file tree
Hide file tree
Showing 17 changed files with 453 additions and 3 deletions.
34 changes: 34 additions & 0 deletions src/features/ModelView/ModelImageView/ModelImageView.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import styled from 'styled-components'
import { spacings } from '../../../tokens/spacings'

export const ImageWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
border-style: solid;
border-width: 1px;
border-color: #cdcdcd;
max-width: 100%;
height: 100%;
> h5 {
font-weight: normal;
margin: 0;
padding: ${spacings.SMALL};
}
> .metadata-image {
max-width: 100%;
padding: ${spacings.SMALL};
}
@media (max-width: 1350px) {
max-width: 100%;
> .metadata-image {
max-width: 100%;
}
}
`
13 changes: 13 additions & 0 deletions src/features/ModelView/ModelImageView/ModelImageView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Img from '../image.png'
import * as Styled from './ModelImageView.styled'

export const ModelImageView = () => {
// TODO
// Load image and text from results
return (
<Styled.ImageWrapper className="metadata-image-view">
<img className="metadata-image" alt="cat" src={Img} />
<h5>Image Text</h5>
</Styled.ImageWrapper>
)
}
68 changes: 68 additions & 0 deletions src/features/ModelView/ModelMetadataView/ModelMetadataView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useAnalogueModels } from '../../../hooks/useAnalogueModels'

import { Button, Table, Typography } from '@equinor/eds-core-react'
import { ModelType } from '../../../pages/ModelPages/Model/Model'

export const ModelMetadataView = () => {
const [model, setModel] = useState<ModelType>()
const { id } = useParams()
const { fetchModel } = useAnalogueModels()

useEffect(() => {
async function getModel() {
return await fetchModel({
params: { path: { id: id ?? '' } },
})
.then((response) => response?.data)
.then((model) => model && setModel(model as ModelType))
}
if (!model) {
getModel()
}
}, [id, model, fetchModel])

if (!model) return <p>Loading ...</p>

// TODO
// Map rows to model data

return (
<div className="metadata-view">
<Typography variant="h3">Description and metadata</Typography>
{model.description && (
<p>
{model.description}
<br />
</p>
)}
<div>
<Table>
<Table.Body>
<Table.Row className="table-row">
<Table.Cell className="table-first-col">Field</Table.Cell>
<Table.Cell>**Tor**</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="table-first-col">Fomation</Table.Cell>
<Table.Cell>**Tor**</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="table-first-col">Analouge</Table.Cell>
<Table.Cell>**Tor**</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell className="table-first-col">Zone</Table.Cell>
<Table.Cell>**Tor**</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</div>

<Button variant="outlined" className="edit-metadata-button">
Edit description and metadata
</Button>
</div>
)
}
14 changes: 14 additions & 0 deletions src/features/ModelView/ModelNameFrame/ModelNameFrame.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styled from 'styled-components'
import { spacings } from '../../../tokens/spacings'

export const NameFrame = styled.div`
width: 100%;
padding: ${spacings.LARGE} 0;
background-color: rgb(247, 247, 247, 1);
> h1 {
margin: 0;
padding: 0 ${spacings.X_LARGE};
font-weight: normal;
}
`
10 changes: 10 additions & 0 deletions src/features/ModelView/ModelNameFrame/ModelNameFrame.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ModelType } from '../../../pages/ModelPages/Model/Model'
import * as Styled from './ModelNameFrame.styled'

export const ModelNameFrame = ({ model }: { model: ModelType }) => {
return (
<Styled.NameFrame className="metadata-name-frame">
<h1>{model.name}</h1>
</Styled.NameFrame>
)
}
48 changes: 48 additions & 0 deletions src/features/ModelView/ModelNavigationBar/ModelNavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { SideBar, SidebarLinkProps } from '@equinor/eds-core-react'
import {
approve,
format_list_bulleted as formatListBullet,
settings,
} from '@equinor/eds-icons'
import { useLocation } from 'react-router-dom'

export const ModelNavigationBar = () => {
const menuItems: SidebarLinkProps[] = [
{
label: 'Details',
icon: formatListBullet,
href: 'details',
active: false,
},
{
label: 'Compute',
icon: settings,
href: 'compute',
active: false,
},
{
label: 'Results',
icon: approve,
href: 'results',
active: false,
},
]

const location = useLocation()
const tab = location.pathname.split('/')

return (
<SideBar open>
<SideBar.Content>
<SideBar.Toggle />
{menuItems.map((m) => (
<SideBar.Link
key={m.label}
{...m}
active={m.href === tab[tab.length - 1]}
/>
))}
</SideBar.Content>
</SideBar>
)
}
65 changes: 65 additions & 0 deletions src/features/ModelView/ModelSourceView/ModelSourceView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useAnalogueModels } from '../../../hooks/useAnalogueModels'

import { Table, Typography } from '@equinor/eds-core-react'
import { ModelType } from '../../../pages/ModelPages/Model/Model'

export const ModelSourceView = () => {
const [model, setModel] = useState<ModelType>()
const { id } = useParams()
const { fetchModel } = useAnalogueModels()

useEffect(() => {
async function getModel() {
return await fetchModel({
params: { path: { id: id ?? '' } },
})
.then((response) => response?.data)
.then((model) => model && setModel(model as ModelType))
}
if (!model) {
getModel()
}
}, [id, model, fetchModel])

if (!model) return <p>Loading ...</p>

// TODO
// Add uploaded by and upload time

return (
<div className="source-view">
<Typography variant="h3">Source</Typography>
<p>Uploaded by ABCD@equinor.com on Sep 13, 2023</p>
<Table>
<Table.Head>
<Table.Row className="table-row">
<Table.Cell className="table-first-col">
Model input files
</Table.Cell>
<Table.Cell>Size</Table.Cell>
</Table.Row>
</Table.Head>
<Table.Body>
{model.fileUploads?.length === undefined ||
model.fileUploads?.length > 0 ? (
model.fileUploads?.map((file: any) => (
<Table.Row key={file.uploadId} className="table-row">
<Table.Cell className="table-first-col">
{file.originalFileName}
</Table.Cell>
<Table.Cell>**Size**</Table.Cell>
</Table.Row>
))
) : (
<Table.Row>
<Table.Cell>No files uploaded</Table.Cell>
<Table.Cell>--</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
</div>
)
}
73 changes: 73 additions & 0 deletions src/features/ModelView/ModelView.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import styled from 'styled-components'
import { spacings } from '../../tokens/spacings'

export const MetadataWrapper = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100%;
width: 100%;
padding: ${spacings.X_LARGE};
row-gap: ${spacings.XXX_LARGE};
column-gap: ${spacings.X_LARGE};
overflow-y: scroll;
@media (max-width: 1350px) {
flex-direction: column;
}
`
export const InnerMetadataWrapper = styled.div`
display: flex;
flex-direction: column;
row-gap: ${spacings.XXX_LARGE};
.edit-metadata-button {
margin-top: ${spacings.MEDIUM_SMALL};
}
.metadata-view {
width: 100%;
min-width: 256px;
> div {
> table {
width: 480px;
> tbody {
> tr {
> .table-row {
}
> .table-first-col {
width: 80px;
padding-right: ${spacings.X_LARGE};
}
}
}
}
}
}
.source-view {
width: 100%;
min-width: 256px;
max-width: 640px;
> table {
width: 480px;
> thead,
tbody {
> tr {
> .table-row {
}
> .table-first-col {
width: 376px;
padding-right: ${spacings.X_LARGE};
}
}
}
}
}
`
16 changes: 16 additions & 0 deletions src/features/ModelView/ModelView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ModelImageView } from '../../features/ModelView/ModelImageView/ModelImageView'
import { ModelMetadataView } from '../../features/ModelView/ModelMetadataView/ModelMetadataView'
import { ModelSourceView } from '../../features/ModelView/ModelSourceView/ModelSourceView'
import * as Styled from './ModelView.styled'

export const ModelView = () => {
return (
<Styled.MetadataWrapper>
<Styled.InnerMetadataWrapper>
<ModelMetadataView />
<ModelSourceView />
</Styled.InnerMetadataWrapper>
<ModelImageView />
</Styled.MetadataWrapper>
)
}
Binary file added src/features/ModelView/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 13 additions & 2 deletions src/hooks/useAnalogueModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ type UseQueryOptions<T> = ParamsOption<T> &
}

const ANALOGUEMODELS_KEY = '/api/analogue-models'
const NC_FILE_KEY = '/api/analogue-models/{id}/netcdf-models'
const ANALOGUEMODEL_KEY = '/api/analogue-models/{id}'
const NC_FILE_KEY = '/api/analogue-models/{id}/input-models'

export function useAnalogueModels() {
const apiClient = useApiClient()
Expand All @@ -30,6 +31,16 @@ export function useAnalogueModels() {
return data
}

async function fetchModel({
params,
}: UseQueryOptions<paths[typeof ANALOGUEMODEL_KEY]['get']>) {
const { data } = await apiClient.GET(ANALOGUEMODEL_KEY, {
params,
headers: new Headers({ Authorization: `Bearer ${token}` }),
})
return data
}

async function createModel({
body,
}: UseQueryOptions<paths[typeof ANALOGUEMODELS_KEY]['post']>) {
Expand Down Expand Up @@ -59,5 +70,5 @@ export function useAnalogueModels() {

const models = useQuery([ANALOGUEMODELS_KEY, token], fetchModels)

return { fetchModels, createModel, models, uploadNCFile }
return { fetchModels, fetchModel, createModel, models, uploadNCFile }
}
5 changes: 5 additions & 0 deletions src/pages/Browse/Browse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export const Browse = () => {

return (
<>
<div>
<Button href="/model/bf2171bc-2f5e-44a1-f6e0-08dbb5ed15e2/details">
model
</Button>
</div>
<Button onClick={toggleDialog}>Add new model</Button>
<Table />
<AddModelDialog
Expand Down
Loading

0 comments on commit 87276f1

Please sign in to comment.