Skip to content

Commit

Permalink
feat: tabbed services
Browse files Browse the repository at this point in the history
  • Loading branch information
nicedexter committed Oct 27, 2023
1 parent c12f836 commit 0b8cb19
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 97 deletions.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import MyFiles from './components/Center/Files'
import GettingStarted from './components/Documentation/GettingStarted'
import TransferData from './components/Project/TransferData'
import Service from './components/Services/Service'

import Services from './components/Services/Services'
export interface Space {
label: string
route: string
Expand Down Expand Up @@ -97,7 +97,7 @@ const App = () => (
</Route>
<Route path={'public'} element={<PublicDatasets />}></Route>
<Route path={'services'} element={<Outlet />}>
<Route index element={<Outlet / >} />
<Route index element={<Services / >} />
<Route path={':serviceId'} element={<Service />}></Route>
</Route>
<Route
Expand Down
6 changes: 6 additions & 0 deletions src/Store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export interface IAppState {
Container[],
React.Dispatch<React.SetStateAction<Container[]>>
]
tabbedServices: [
string[],
React.Dispatch<React.SetStateAction<string[]>>
]
}

export const AppContext = React.createContext<IAppState>({} as IAppState)
Expand All @@ -100,6 +104,7 @@ export const AppStoreProvider = ({
null
)
const [tabbedDesktops, setTabbedDesktops] = useState<Container[]>([])
const [tabbedServices, setTabbedServices] = useState<string[]>([])

// BIDS Tools Store, to be renamed or refactored into a new type
const [selectedBidsDataset, setSelectedBidsDataset] = useState<BIDSDataset>()
Expand Down Expand Up @@ -201,6 +206,7 @@ export const AppStoreProvider = ({
selectedParticipants: [selectedParticipants, setSelectedParticipants],
selectedFiles: [selectedFiles, setSelectedFiles],
tabbedDesktops: [tabbedDesktops, setTabbedDesktops],
tabbedServices: [tabbedServices, setTabbedServices],
}),
[
debug,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Documentation/AppList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Apps = () => {
<TitleBar
title={'App Catalog'}
description={
'A list of all the applications made available to the HIP users. The applications can be started from an existing desktop. Software and applications contained in the HIP are made available pursuant to the terms of their respective licenses.'
'A list of all the applications made available to the users. The applications can be started from an existing desktop. Software and applications contained in the HIP are made available pursuant to the terms of their respective licenses.'
}
/>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '16px 16px', mt: 2 }}>
Expand Down
78 changes: 54 additions & 24 deletions src/components/Services/Service.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React, { useEffect, useRef, useState } from 'react'
import TitleBar from '../UI/titleBar'
import { Box, CircularProgress, Typography } from '@mui/material'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import {
APP_MARGIN_TOP,
DRAWER_WIDTH,
ROUTE_PREFIX,
SERVICES,
} from '../../constants'
import { CircularProgress } from '@mui/material'
import { useParams } from 'react-router-dom'
import { SERVICES } from '../../constants'
import { useAppStore } from '../../Store'

export default function Service() {
const [loading, setLoading] = useState(true)
const [service, setService] = useState<any>(null)
const iFrameRef = useRef<HTMLIFrameElement>(null)
const params = useParams()
const {
tabbedServices: [tabbedServices, setTabbedServices],
} = useAppStore()

// Remove scroll for entire window
useEffect(() => {
Expand All @@ -24,10 +23,23 @@ export default function Service() {
}, [])

useEffect(() => {
const serviceId = Number(params?.serviceId)
if (!params.serviceId) return

const serviceId = params?.serviceId
const service = SERVICES.find(s => s.id === serviceId)

if (!service) return

setService(service)
}, [params])
setTabbedServices((prev: any) => {
const index = prev.findIndex((s: any) => s === serviceId)
if (index === -1) {
return [...prev, serviceId]
}

return prev
})
}, [params, setTabbedServices, setService])

useEffect(() => {
if (!iFrameRef.current) return
Expand All @@ -37,19 +49,37 @@ export default function Service() {
}, [iFrameRef])

return (
service && (
<iframe
ref={iFrameRef}
title='services'
src={service?.url}
allow={'autoplay; fullscreen; clipboard-write;'}
style={{
width: '100%',
height: 'calc(100vh - 164px)',
backgroundColor: '#333',
}}
className='iframe-display'
/>
)
<>
<TitleBar title={service?.label} />
{loading && (
<div
aria-label='Loading remote desktop'
style={{
width: '100%',
height: 'calc(100vh - 164px)',
display: 'flex',
alignItems: 'center',
backgroundColor: '#eee',
justifyContent: 'center',
}}
>
<CircularProgress size={32} />
</div>
)}
{!loading && service && (
<iframe
ref={iFrameRef}
title='services'
src={service?.url}
allow={'autoplay; fullscreen; clipboard-write;'}
style={{
width: '100%',
height: 'calc(100vh - 164px)',
backgroundColor: '#333',
}}
className='iframe-display'
/>
)}
</>
)
}
99 changes: 99 additions & 0 deletions src/components/Services/Services.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
Box,
Button,
Card,
CardActions,
CardContent,
CardMedia,
Chip,
Divider,
Link,
} from '@mui/material'
import Typography from '@mui/material/Typography'
import { API_GATEWAY } from '../../api/gatewayClientAPI'
import TitleBar from '../UI/titleBar'
import React from 'react'
import { ROUTE_PREFIX, SERVICES, ISERVICE } from '../../constants'
import { useNavigate } from 'react-router-dom'

const Services = () => {
const navigate = useNavigate()

const goto = (service: ISERVICE) => {
if (service.target === '_blank') {
window.open(service.url, '_blank')
return
}

navigate(`${ROUTE_PREFIX}/services/${service.id}`)
}

return (
<>
<TitleBar
title={'Services Catalog'}
description={'A list of all the services made available to the users.'}
/>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '16px 16px', mt: 2 }}>
{SERVICES?.map((service, i) => (
<Card
sx={{
cursor: 'pointer',
width: 288,
display: 'flex',
flexDirection: 'column',
}}
key={service.label}
onClick={() => {
goto(service)
}}
>
<CardMedia
component='img'
height='140'
src={`${API_GATEWAY}/public/media/288x140-${service.image}__logo.png`}
alt={service.label}
sx={{ cursor: 'pointer' }}
/>
<Divider />
<CardContent sx={{ cursor: 'pointer', flexGrow: 1, pb: 0, mb: 0 }}>
<Box sx={{ display: 'flex' }}>
<Typography variant='h5' sx={{ flex: 1 }}>
{service.label}
</Typography>
</Box>
<Typography
sx={{ mb: 2, mt: 2 }}
gutterBottom
variant='body2'
color='text.secondary'
>
{service.description}
</Typography>
<Typography
variant='caption'
color='text.secondary'
sx={{ wordWrap: 'break-word' }}
>
<Link href={service.url} target='_blank'>
{service.url}
</Link>
</Typography>
</CardContent>
<CardActions sx={{ p: 2 }}>
<Button
onClick={() => {
goto(service)
}}
>
Open Service
</Button>
</CardActions>
</Card>
))}
</Box>
</>
)
}

export default Services
34 changes: 0 additions & 34 deletions src/components/Services/index.tsx

This file was deleted.

48 changes: 21 additions & 27 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,11 @@ const Sidebar = () => {
selectedProject: [selectedProject],
tooltips: [showTooltip],
tabbedDesktops: [tabbedDesktops],
tabbedServices: [tabbedServices],
} = useAppStore()
const [drawerOpen, setDrawerOpen] = React.useState(true)
const [openProjects, setOpenProjects] = React.useState<{
[key: string]: boolean
}>({})
const [openTools, setOpenTools] = React.useState(false)

useEffect(() => {
const projectId = selectedProject?.name
Expand All @@ -100,7 +99,7 @@ const Sidebar = () => {
setOpenProjects(op => ({ ...op, [projectId]: !op[projectId] ?? false }))
}

const handleClickNavigate = (route: string, options:any = null) => {
const handleClickNavigate = (route: string, options: any = null) => {
trackPageView({ documentTitle: route })

if (options) {
Expand Down Expand Up @@ -219,8 +218,8 @@ const Sidebar = () => {
from: `/apps/hip/centers/${center?.id}/desktops`,
workspace: 'private',
trackingName: `center/${center?.id}`,
showAdminView: false
}
showAdminView: false,
},
}
)
}
Expand Down Expand Up @@ -392,35 +391,30 @@ const Sidebar = () => {
<Divider />
<ListItemButton
onClick={() => {
setOpenTools(!openTools)
handleClickNavigate(`/services`)
}}
selected={`${ROUTE_PREFIX}/services` === pathname}
>
<ListItemIcon>
<Hub />
</ListItemIcon>
<ListItemText primary={'Services'} />
{openTools ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={openTools} timeout='auto' unmountOnExit>
<List component='div' disablePadding>
{SERVICES.map((s, i) => (
<ListItemButton
sx={{ pl: 4 }}
key={s.label}
selected={
`${ROUTE_PREFIX}/services/${s.id}` ===
pathname
}
onClick={() => handleClickNavigate(`/services/${s.id}`)}
>
<ListItemIcon>
<Api />
</ListItemIcon>
<ListItemText primary={s.label} />
</ListItemButton>
))}
</List>
</Collapse>
{tabbedServices
?.map(s => ({ ...SERVICES.find(t => `${t.id}` === s) }))
.map(st => (
<ListItemButton
key={``}
sx={{ pl: 4 }}
selected={`${ROUTE_PREFIX}/services/${st?.id}` === pathname}
onClick={() => handleClickNavigate(`/services/${st.id}`)}
>
<ListItemIcon>
<Api />
</ListItemIcon>
<ListItemText primary={st.label} />
</ListItemButton>
))}
<ListItemButton
selected={`${ROUTE_PREFIX}/apps` === pathname}
onClick={() => handleClickNavigate('/apps')}
Expand Down
Loading

0 comments on commit 0b8cb19

Please sign in to comment.