diff --git a/src/App.tsx b/src/App.tsx
index f9dfd38..86a4788 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -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
@@ -97,7 +97,7 @@ const App = () => (
}>
}>
- } />
+ } />
}>
>
]
+ tabbedServices: [
+ string[],
+ React.Dispatch>
+ ]
}
export const AppContext = React.createContext({} as IAppState)
@@ -100,6 +104,7 @@ export const AppStoreProvider = ({
null
)
const [tabbedDesktops, setTabbedDesktops] = useState([])
+ const [tabbedServices, setTabbedServices] = useState([])
// BIDS Tools Store, to be renamed or refactored into a new type
const [selectedBidsDataset, setSelectedBidsDataset] = useState()
@@ -201,6 +206,7 @@ export const AppStoreProvider = ({
selectedParticipants: [selectedParticipants, setSelectedParticipants],
selectedFiles: [selectedFiles, setSelectedFiles],
tabbedDesktops: [tabbedDesktops, setTabbedDesktops],
+ tabbedServices: [tabbedServices, setTabbedServices],
}),
[
debug,
diff --git a/src/components/Documentation/AppList.tsx b/src/components/Documentation/AppList.tsx
index e0f7c0f..d444957 100644
--- a/src/components/Documentation/AppList.tsx
+++ b/src/components/Documentation/AppList.tsx
@@ -23,7 +23,7 @@ const Apps = () => {
diff --git a/src/components/Services/Service.tsx b/src/components/Services/Service.tsx
index a1a736c..1e4861e 100644
--- a/src/components/Services/Service.tsx
+++ b/src/components/Services/Service.tsx
@@ -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(null)
const iFrameRef = useRef(null)
const params = useParams()
+ const {
+ tabbedServices: [tabbedServices, setTabbedServices],
+ } = useAppStore()
// Remove scroll for entire window
useEffect(() => {
@@ -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
@@ -37,19 +49,37 @@ export default function Service() {
}, [iFrameRef])
return (
- service && (
-
- )
+ <>
+
+ {loading && (
+
+
+
+ )}
+ {!loading && service && (
+
+ )}
+ >
)
}
diff --git a/src/components/Services/Services.tsx b/src/components/Services/Services.tsx
new file mode 100644
index 0000000..32541bf
--- /dev/null
+++ b/src/components/Services/Services.tsx
@@ -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 (
+ <>
+
+
+ {SERVICES?.map((service, i) => (
+ {
+ goto(service)
+ }}
+ >
+
+
+
+
+
+ {service.label}
+
+
+
+ {service.description}
+
+
+
+ {service.url}
+
+
+
+
+
+
+
+ ))}
+
+ >
+ )
+}
+
+export default Services
diff --git a/src/components/Services/index.tsx b/src/components/Services/index.tsx
deleted file mode 100644
index 27b10c6..0000000
--- a/src/components/Services/index.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React, { useEffect, useRef, useState } from 'react'
-import TitleBar from '../UI/titleBar'
-import { Box, CircularProgress, Typography } from '@mui/material'
-import { DRAWER_WIDTH } from '../../constants'
-
-export default function Service() {
- const [loading, setLoading] = useState(true)
- const iFrameRef = useRef(null)
-
- useEffect(() => {
- if (!iFrameRef.current) return
- iFrameRef.current.addEventListener('load', function () {
- setLoading(false)
- })
- }, [iFrameRef])
-
- return (
-
-
-
- )
-}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx
index 936d792..ed751ae 100644
--- a/src/components/Sidebar.tsx
+++ b/src/components/Sidebar.tsx
@@ -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
@@ -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) {
@@ -219,8 +218,8 @@ const Sidebar = () => {
from: `/apps/hip/centers/${center?.id}/desktops`,
workspace: 'private',
trackingName: `center/${center?.id}`,
- showAdminView: false
- }
+ showAdminView: false,
+ },
}
)
}
@@ -392,35 +391,30 @@ const Sidebar = () => {
{
- setOpenTools(!openTools)
+ handleClickNavigate(`/services`)
}}
+ selected={`${ROUTE_PREFIX}/services` === pathname}
>
- {openTools ? : }
-
-
- {SERVICES.map((s, i) => (
- handleClickNavigate(`/services/${s.id}`)}
- >
-
-
-
-
-
- ))}
-
-
+ {tabbedServices
+ ?.map(s => ({ ...SERVICES.find(t => `${t.id}` === s) }))
+ .map(st => (
+ handleClickNavigate(`/services/${st.id}`)}
+ >
+
+
+
+
+
+ ))}
handleClickNavigate('/apps')}
diff --git a/src/constants.tsx b/src/constants.tsx
index 4b2d6b2..0c6c2dc 100644
--- a/src/constants.tsx
+++ b/src/constants.tsx
@@ -146,25 +146,40 @@ export const ENTITIES: IEntity[] = [
},
]
+
export const SERVICES = [
{
- id: 1,
+ id: 'i2b2',
label: 'i2b2 Cohort Explorer',
- url: 'https://i2b2.horus-tools.intranet.chuv/webclient2/'
+ description: 'i2b2 Cohort Explorer',
+ url: 'https://i2b2.horus-tools.intranet.chuv/webclient2/',
+ image: 'i2b2',
+ target: 'self',
},
{
- id: 2,
+ id: 'kheops',
label: 'Kheops DICOM Images Explorer',
- url: 'https://kheops.chuv.ch/'
+ description: 'Kheops DICOM Images Explorer',
+ url: 'https://kheops.chuv.ch/',
+ image: 'kheops',
+ target: 'self',
},
{
- id: 3,
+ id: 'sarus',
label: 'Sarus',
- url: 'http://lvn01091v.intranet.chuv/'
+ description: 'Sarus',
+ url: 'http://lvn01091v.intranet.chuv/',
+ image: 'sarus',
+ target: '_blank',
},
{
- id: 4,
+ id: 'datasets-catalog',
label: 'Datasets catalog',
- url: 'https://catalog.horus-services.intranet.chuv/'
- }
+ description: 'Datasets catalog',
+ url: 'https://catalog.horus-services.intranet.chuv/',
+ image: 'chuv',
+ target: 'self',
+ },
]
+
+export type ISERVICE = typeof SERVICES[0]