Skip to content

Commit

Permalink
feat: add ui components for the namespace page
Browse files Browse the repository at this point in the history
  • Loading branch information
d-rita committed Dec 18, 2024
1 parent 659f214 commit 5ba3657
Show file tree
Hide file tree
Showing 13 changed files with 392 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { FC } from 'react'
import { RouterProvider } from 'react-router-dom'
import AppWrapper from './components/AppWrapper'
import { router } from './routes/Router'
import { hashRouter } from './routes/Router'

const App: FC = () => {
return (
<AppWrapper>
<RouterProvider router={router} />
<RouterProvider router={hashRouter} />
</AppWrapper>
)
}
Expand Down
23 changes: 23 additions & 0 deletions src/components/error/ErrorComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NoticeBox, Center } from '@dhis2/ui'
import React from 'react'
import { Link } from 'react-router-dom'
import i18n from '../../locales'

const ErrorComponent = () => {
return (
<div
style={{
marginTop: '200px',
}}
>
<Center>
<NoticeBox warning title={i18n.t('An error has occurred')}>
<p>{i18n.t('404 Page Not Found')}</p>
<Link to={'/dataStore'}>{i18n.t('Back to datastore')}</Link>
</NoticeBox>
</Center>
</div>
)
}

export default ErrorComponent
10 changes: 10 additions & 0 deletions src/components/header/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import classes from '../../App.module.css'

type HeaderProps = {
children?: React.ReactNode
}

export default function PageHeader({ children }: HeaderProps) {
return <div className={classes.pageHeader}>{children}</div>
}
72 changes: 72 additions & 0 deletions src/components/pages/Namespaces.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { IconAdd24, colors } from '@dhis2/ui'
import React, { useEffect, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import classes from '../../App.module.css'
import i18n from '../../locales'
import CreateButton from '../sections/CreateButton'
import DataStoreTabBar from '../sections/DataStoreTabBar'
import PageHeader from '../header/PageHeader'
import SearchField from '../sections/SearchField'
import ItemsTable from '../table/ItemsTable'

const NamespacesPage = () => {
const navigate = useNavigate()
const { store } = useParams()

const data = {
results: [
'AUTO_CONFIG',
'CLIMATE_DATA',
'DHIS2_MAPS_APP',
'METADATASTORE',
],
}

const [activeTab, setActiveTab] = useState(store || 'dataStore')

const handleSwitchTab = (selectedTab) => {
setActiveTab(selectedTab)
navigate(`/${selectedTab}`)
}

useEffect(() => {
const storeOptions = ['dataStore', 'userDataStore']
if (storeOptions.includes(store)) {
setActiveTab(store)
}
}, [store])

return (
<div className={classes.firstPage}>
<PageHeader>
<span className={classes.firstPageHeader}>
Configure Namespaces
</span>
</PageHeader>

<div className={classes.firstPageContainer}>
<div>
<DataStoreTabBar
activeTab={activeTab}
switchTab={handleSwitchTab}
/>
</div>
<div className={classes.midSection}>
<SearchField placeholder={i18n.t('Search namespaces')} />
<CreateButton
label={i18n.t('New Namespace')}
handleClick={() => console.log('create new namespace')}
icon={<IconAdd24 color={colors.grey600} />}
/>
</div>
<div>
{data && (
<ItemsTable data={data} label={i18n.t('Namespace')} />
)}
</div>
</div>
</div>
)
}

export default NamespacesPage
27 changes: 27 additions & 0 deletions src/components/sections/CreateButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Button } from '@dhis2/ui'
import React from 'react'
import classes from '../../App.module.css'

type CreateButtonProps = {
label: string
handleClick: () => void
icon: React.ReactElement
}

const CreateButton = ({ label, handleClick, icon }: CreateButtonProps) => {
return (
<div className={classes.createButton}>
<Button
aria-label={label}
icon={icon}
name="create"
onClick={handleClick}
title={label}
>
{label}
</Button>
</div>
)
}

export default CreateButton
35 changes: 35 additions & 0 deletions src/components/sections/DataStoreTabBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Tab, TabBar } from '@dhis2/ui'
import React from 'react'
import i18n from '../../locales'

type DataStoreProps = {
activeTab: string
switchTab: (string) => void
}

export default function DataStoreTabBar({
activeTab,
switchTab,
}: DataStoreProps) {
return (
<TabBar>
<Tab
onClick={() => {
switchTab('dataStore')
}}
selected={activeTab === 'dataStore'}
>
{i18n.t('DataStore')}
</Tab>
<Tab
onClick={() => {
switchTab('userDataStore')
}}
selected={activeTab === 'userDataStore'}
>
{' '}
{i18n.t('UserDataStore')}
</Tab>
</TabBar>
)
}
18 changes: 18 additions & 0 deletions src/components/sections/SearchField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { InputField } from '@dhis2/ui'
import React from 'react'
import classes from '../../App.module.css'
import i18n from '../../locales'

const SearchField = ({ placeholder }: { placeholder?: string }) => {
return (
<div className={classes.search}>
<InputField
dense
name="search"
placeholder={placeholder || i18n.t('Search')}
/>
</div>
)
}

export default SearchField
16 changes: 16 additions & 0 deletions src/components/table/DeleteAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IconDelete16 } from '@dhis2/ui-icons'
import { Button } from '@dhis2-ui/button'
import React from 'react'
import i18n from '../../locales'

export default function DeleteAction() {
return (
<Button
aria-label={i18n.t('Delete')}
icon={<IconDelete16 />}
name="delete"
onClick={() => console.log('delete item')}
title={i18n.t('Delete')}
/>
)
}
93 changes: 93 additions & 0 deletions src/components/table/ItemsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
DataTable,
DataTableCell,
DataTableColumnHeader,
DataTableRow,
TableBody,
TableHead,
} from '@dhis2/ui'
import React from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import classes from '../../App.module.css'
import i18n from '../../locales'
import TableActions from './TableActions'

type TableProps = {
data: {
results: string[]
}
label: string
}

const ItemsTable = ({ data, label }: TableProps) => {
const navigate = useNavigate()
const { namespace: currentNamespace } = useParams()

return (
<div>
{data && (
<DataTable layout="fixed">
<TableHead>
<DataTableRow>
<DataTableColumnHeader
width={currentNamespace ? '85%' : '90%'}
>
<span className={classes.columnHeader}>
{label}
</span>
</DataTableColumnHeader>
<DataTableColumnHeader
width={currentNamespace ? '15%' : '10%'}
>
<span className={classes.columnHeader}>
{i18n.t('Actions')}
</span>
</DataTableColumnHeader>
</DataTableRow>
</TableHead>
<TableBody>
{data?.results?.length && (
<>
{data.results.map((item, index) => {
return (
<DataTableRow key={`${item}-${index}`}>
<DataTableCell
bordered
width={
currentNamespace
? '85%'
: '90%'
}
onClick={() => {
if (currentNamespace) {
navigate(`${item}`)
} else {
navigate(`edit/${item}`)
}
}}
>
{item}
</DataTableCell>
<DataTableCell
bordered
width={
currentNamespace
? '15%'
: '10%'
}
>
<TableActions />
</DataTableCell>
</DataTableRow>
)
})}
</>
)}
</TableBody>
</DataTable>
)}
</div>
)
}

export default ItemsTable
16 changes: 16 additions & 0 deletions src/components/table/SharingAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IconShare16 } from '@dhis2/ui-icons'
import { Button } from '@dhis2-ui/button'
import React from 'react'
import i18n from '../../locales'

export default function SharingAction() {
return (
<Button
aria-label={i18n.t('Share')}
icon={<IconShare16 />}
name="share"
onClick={() => console.log('open sharing dialog')}
title={i18n.t('Share')}
/>
)
}
19 changes: 19 additions & 0 deletions src/components/table/TableActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import classes from '../../App.module.css'
import DeleteAction from './DeleteAction'
import SharingAction from './SharingAction'

// type TableActionProps = {
// selectedItem?: string
// }

const TableActions = () => {
return (
<div className={classes.actionButtons}>
<SharingAction />
<DeleteAction />
</div>
)
}

export default TableActions
24 changes: 24 additions & 0 deletions src/routes/PageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { useEffect } from 'react'
import { Outlet, useNavigate, useParams } from 'react-router-dom'
import classes from '../App.module.css'

function PageLayout() {
const { store } = useParams()
const navigate = useNavigate()

useEffect(() => {
const storeOptions = ['dataStore', 'userDataStore']
if (!storeOptions.includes(store)) {
console.log("pGE LOAYOUT IN CONDITIONAL", store)
navigate('dataStore')
}
}, [store])

return (
<div className={classes.page}>
<Outlet />
</div>
)
}

export default PageLayout
Loading

0 comments on commit 5ba3657

Please sign in to comment.