Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devops 272 public instances #539

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d97e909
feat: update routing for public routes and implementing login page
Chisomchima Jul 31, 2024
4f2b1d4
feat: update routing for public routes and implementing login page
Chisomchima Jul 31, 2024
e3a6ae2
feat: public instances table
Chisomchima Aug 6, 2024
69a8ee4
Merge branch 'master' of github.com:dhis2-sre/im-web-client into DEVO…
Chisomchima Aug 6, 2024
8ad0022
feat: public instances table
Chisomchima Aug 6, 2024
dee9262
feat: filter the deployment with name of play
Chisomchima Aug 7, 2024
b142448
chore: remove hard coded strings
Chisomchima Aug 7, 2024
ab65e57
Merge branch 'master' of github.com:dhis2-sre/im-web-client into DEVO…
Chisomchima Aug 7, 2024
6dc074e
chore: cleanup
Chisomchima Aug 7, 2024
5572f6f
feat: integrate instance table with new api
Chisomchima Sep 13, 2024
41f3cb5
Merge branch 'master' of github-chisom:dhis2-sre/im-web-client into D…
Chisomchima Sep 13, 2024
10f3f9c
feat: integrate instance table with new api
Chisomchima Sep 13, 2024
c4900b0
feat: revert auth-provider
Chisomchima Sep 14, 2024
4c9f624
feat: revert auth-provider
Chisomchima Sep 14, 2024
c2d622d
fix: remove capitalize styling on the instance names
Chisomchima Sep 25, 2024
22e561c
Merge branch 'master' of github-chisom:dhis2-sre/im-web-client into D…
Chisomchima Sep 25, 2024
f25eba5
chore: update yarn.lock
tonsV2 Sep 25, 2024
77bfc32
fix: yarn lock
Chisomchima Sep 25, 2024
8e81639
chore: removed unused constants
Chisomchima Sep 27, 2024
162f6f2
chore: update yarn.lock file
Chisomchima Sep 27, 2024
767453b
chore: resolve keys when mapping groups
Chisomchima Sep 27, 2024
0e4b243
fix: properly name and remove unnecessary styling
Chisomchima Sep 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import '@fontsource/roboto/400.css'
import '@fontsource/roboto/400-italic.css'
import '@fontsource/roboto/500.css'
import '@fontsource/roboto/700.css'
import React from 'react'
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom'
import { Alerts, AuthProvider, ErrorView, Layout } from '../components/index.ts'
import { Alerts, AuthProvider, ErrorView, Layout, PublicLayout } from '../components/index.ts'
import {
ValidateSuccess,
DatabasesList,
Expand All @@ -16,25 +15,34 @@ import {
NewDhis2Instance,
RequestPasswordReset,
ResetPassword,
Login,
SignUp,
StackDetails,
StacksList,
GroupsList,
UsersList,
UserDetails,
Validate,
InstancesTable,
} from '../views/index.ts'

const router = createBrowserRouter(
createRoutesFromElements(
<Route>
<Route path="/sign-up" element={<SignUp />} />
<Route path="/request-password-reset" element={<RequestPasswordReset />} />
<Route path="/reset-password/:token" element={<ResetPassword />} />
<Route path="/validate/success" element={<ValidateSuccess />} />
<Route path="/validate/:token" element={<Validate />} />

<Route element={<AuthProvider />}>
<Route path="/sign-up" element={<SignUp />} />
<Route path="/sign-in" element={<Login />} />
<Route path="/validate/:token" element={<Validate />} />
<Route path="/request-password-reset" element={<RequestPasswordReset />} />
<Route path="/reset-password/:token" element={<ResetPassword />} />
<Route path="/account-verification">
<Route path="success" element={<ValidateSuccess />} />
</Route>

<Route path="/play" element={<PublicLayout />}>
tonsV2 marked this conversation as resolved.
Show resolved Hide resolved
<Route path="instances" element={<InstancesTable />} />
</Route>

<Route errorElement={<ErrorView />} path="/" element={<Layout />}>
<Route path="/stacks" element={<StacksList />} />
<Route path="/stacks/:name" element={<StackDetails />} />
Expand Down
13 changes: 9 additions & 4 deletions src/components/auth-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Outlet, useNavigate } from 'react-router-dom'
import { AuthContext } from '../contexts/index.ts'
import { useAuthAxios, UNAUTHORIZED_EVENT } from '../hooks/use-auth-axios.ts'
import type { Tokens, User } from '../types/index.ts'
import { Login } from './login.tsx'

const CURRENT_USER_LOCAL_STORAGE_KEY = 'DHIS2_IM_CURRENT_USER'
const getCurrentUserFromLocalStorage = () => JSON.parse(localStorage.getItem(CURRENT_USER_LOCAL_STORAGE_KEY))
Expand Down Expand Up @@ -70,6 +69,7 @@ export const AuthProvider: FC = () => {

setAuthenticationErrorMessage('')
setCurrentUser(userResponse.data)
navigate('/instances')
Chisomchima marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
console.error(error)
const errorMessage = error instanceof AxiosError || error instanceof Error ? error.message : 'Unknown error'
Expand All @@ -79,7 +79,7 @@ export const AuthProvider: FC = () => {
setIsAuthenticating(false)
}
},
[getTokens, getUser, setCurrentUser]
[getTokens, getUser, setCurrentUser, navigate]
)

const logout = useCallback(async () => {
Expand All @@ -103,6 +103,10 @@ export const AuthProvider: FC = () => {
}
}, [setCurrentUser, navigate])

if (checkingUser) {
return null
}

return (
<AuthContext.Provider
value={{
Expand All @@ -114,7 +118,8 @@ export const AuthProvider: FC = () => {
logout,
}}
>
{
<Outlet />
{/* {
// We're not validating a user on app load and there's a user
!checkingUser && currentUser && <Outlet />
}
Expand All @@ -130,7 +135,7 @@ export const AuthProvider: FC = () => {
// We won't display anything while we're still checking the user initially
// to prevent flickering
''
}
} */}
</AuthContext.Provider>
)
}
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export { ConfirmationModal } from './confirmation-modal.tsx'
export { ErrorView } from './error-view.tsx'
export { Heading } from './heading.tsx'
export { Layout } from './layout.tsx'
export { PublicLayout } from './public-layout.tsx'
export { LogoutButton } from './logout-button.tsx'
export { MomentExpiresFromNow } from './moment-expires-from-now.tsx'
2 changes: 1 addition & 1 deletion src/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const Layout: FC = () => {
)

if (location.pathname === '/') {
return <Navigate to="/instances" />
return <Navigate to="/sign-in" />
}

return (
Expand Down
57 changes: 57 additions & 0 deletions src/components/public-layout.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.container {
display: flex;
flex-direction: column;
width: 100vw;
height: 100%;
}
.mainArea {
width: 100vw;
height: 100%;
}
.nav {
background-color: var(--colors-grey300);
padding: 0 10px;
display: flex;
align-items: center;
justify-content: space-between;
}

.header {
display: flex;
align-items: center;
gap: 15px;
margin: 0;
font-size: 20px;
line-height: 16px;
font-weight: 700;
padding: 15px;
}
.logo {
width: 35px;
height: 35px;
}
.navlist {
display: flex;
}

.navlist :global(a) {
font-weight: 400;
font-size: 15px;
line-height: 18px;
padding: 9px 8px 9px 12px;
color: var(--colors-grey800);
text-decoration: none;
transition: background-color 150ms ease-in-out;
display: inline-flex;
justify-content: space-between;
}

.navlist :global(a):hover {
color: var(--colors-blue600);
text-decoration: underline;
}

.navlist :global(a.active) {
text-decoration: underline;
color: var(--colors-blue600);
}
26 changes: 26 additions & 0 deletions src/components/public-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { LogoIcon } from '@dhis2/ui'
import type { FC } from 'react'
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import styles from './public-layout.module.css'

export const PublicLayout: FC = () => {
const location = useLocation()

if (location.pathname === '/') {
return <Navigate to="/sign-in" />
}

return (
<div className={styles.container}>
<div className={styles.nav}>
<h1 className={styles.header}>
<LogoIcon className={styles.logo} />
DHIS2 Playground
Mohammer5 marked this conversation as resolved.
Show resolved Hide resolved
</h1>
</div>
<div className={styles.mainArea}>
<Outlet />
</div>
</div>
)
}
17 changes: 17 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,21 @@ export const STACK_NAMES: Record<string, Dhis2StackName> = {
PG_ADMIN: 'pgadmin',
}

export const DePLOYMENT_CATEGORIES: Record<string, string> = {
Chisomchima marked this conversation as resolved.
Show resolved Hide resolved
STABLE: 'Stable',
CANARY: 'Canary',
UNDER_DEVELOPMENT: 'Under Development',
}

export const INSTANCE_NAME: Record<string, string> = {
Chisomchima marked this conversation as resolved.
Show resolved Hide resolved
DEV: 'dev',
NIGHTLY: 'nightly',
STABLE: 'stable',
}
export const DEPLOYMENT_NAME: Record<string, string> = {
Chisomchima marked this conversation as resolved.
Show resolved Hide resolved
ANDROID_DEV: 'android',
PLAY: 'play',
STABLE: 'qa',
}

export const VIEWABLE_INSTANCE_TYPES = ['pgadmin', 'dhis2-core']
2 changes: 1 addition & 1 deletion src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ body {
}

#root {
height: 100vh;
height: 100%;
width: 100vw;
overflow: auto;
}
Expand Down
2 changes: 2 additions & 0 deletions src/views/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './databases/index.ts'
export * from './instances/index.ts'
export * from './sign-up/sign-up.tsx'
export * from './sign-in/login.tsx'
export * from './stacks/stack-details.tsx'
export * from './stacks/stacks-list.tsx'
export * from './reset-password/reset-password.tsx'
Expand All @@ -9,3 +10,4 @@ export { GroupsList } from './groups/index.ts'
export { UsersList } from './users/index.ts'
export { UserDetails } from './users/user-details.tsx'
export * from './validate/index.ts'
export { InstancesTable } from './public-instances-play/index.ts'
9 changes: 4 additions & 5 deletions src/views/instances/list/instances-list.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
cursor: pointer;
}
.groupName {
all: unset;
font-size: 18px;
font-weight: 500;
line-height: 23px;
color: var(--colors-grey800) !important;
font-size: 1.2rem;
font-weight: bold;
color: var(--colors-blue600) !important;
}

td {
font-weight: 400;
color: var(--colors-grey600) !important;
Expand Down
1 change: 1 addition & 0 deletions src/views/public-instances-play/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { InstancesTable } from './list/instances-table.tsx'
41 changes: 41 additions & 0 deletions src/views/public-instances-play/list/instance-play.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.wrapper {
padding: 20px;
}
.heading {
font-size: 1.5rem;
margin-bottom: 20px;
color: var(--colors-grey900);
}

.description {
font-size: 1rem;
margin-bottom: 24px;
}

.loginInfo {
margin-bottom: 24px;
}

.loginInfo h2 {
font-size: 1rem;
margin-bottom: 4px;
}

.loginInfo ul {
list-style-type: none;
padding: 0;
}

.loginInfo li {
font-size: 1rem;
margin-bottom: 4px;
}

.additionalInfo a {
color: var(--colors-blue800);
text-decoration: none;
}

.additionalInfo a:hover {
text-decoration: underline;
}
27 changes: 27 additions & 0 deletions src/views/public-instances-play/list/instance-play.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styles from './instance-play.module.css'

export const InstancePlay = () => (
<div className={styles.wrapper}>
<h1 className={styles.heading}>DHIS2 Demo Instances</h1>
<p className={styles.description}>
Explore demo instances for the latest DHIS2 versions! Each link below provides access to DHIS2 with our demo database. For additional demo databases for specific DHIS2
apps and use cases, visit
<a href="https://www.dhis2.org/demo" target="_blank" rel="noopener noreferrer">
{' '}
DHIS2 Demo
</a>
.
</p>
<div className={styles.loginInfo}>
<h2>Log in with:</h2>
<ul>
<li>
<strong>User:</strong> admin
</li>
<li>
<strong>Password:</strong> district
</li>
</ul>
</div>
</div>
)
55 changes: 55 additions & 0 deletions src/views/public-instances-play/list/instance-table-filters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { DEPLOYMENT_NAME, INSTANCE_NAME, STACK_NAMES } from '../../../constants.ts'
import { useAuthAxios } from '../../../hooks/index.ts'
import { Deployment } from '../../../types/index.ts'

export interface CategorizedDeployments {
stable: Deployment[]
canary: Deployment[]
underDevelopment: Deployment[]
}

const getCoreInstanceLink = (deployments: Deployment) => {
const coreInstance = deployments.instances.find((instance) => instance.stackName === STACK_NAMES.CORE)
return coreInstance ? `https://${deployments.groupName}.im.dhis2.org/${coreInstance.name}` : '#'
}

const filterInstancesByCondition = (instances, condition: (deployment: Deployment) => boolean): Deployment[] => {
return instances?.flatMap((group) => group.deployments.filter((deployment) => deployment.public && condition(deployment))) || []
}

const categorizeInstances = (deployments: Deployment[]): CategorizedDeployments => {
const categories: CategorizedDeployments = {
stable: [],
canary: [],
underDevelopment: [],
}

deployments.forEach((deployment) => {
if (deployment.name.includes(INSTANCE_NAME.DEV)) {
categories.underDevelopment.push(deployment)
} else if (deployment.name.includes(INSTANCE_NAME.STABLE)) {
categories.canary.push(deployment)
} else {
categories.stable.push(deployment)
}
})

return categories
}

export const useInstanceTableData = () => {
const [{ data: groupsWithDeployments, error, loading }] = useAuthAxios('/deployments/public', { useCache: true })
const playGroup = groupsWithDeployments?.filter((groupWithDeployments) => groupWithDeployments.name === DEPLOYMENT_NAME.PLAY)

const coreDeployments = filterInstancesByCondition(playGroup, (deployment) => deployment.instances.some((instance) => instance.stackName === STACK_NAMES.CORE))

const categorizedCoreDeployments = categorizeInstances(coreDeployments)

return {
groupsWithDeployments,
error,
loading,
getCoreInstanceLink,
categorizedCoreDeployments,
}
}
Loading
Loading