Skip to content

Commit

Permalink
Merge pull request #108 from gov4git/community-dashboard
Browse files Browse the repository at this point in the history
add community dashboard
  • Loading branch information
dworthen authored Feb 28, 2024
2 parents 0be03d6 + 79a34f7 commit 1d804e7
Show file tree
Hide file tree
Showing 29 changed files with 431 additions and 160 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-bears-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'gov4git-desktop-app': minor
---

Add community dashboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {
Breadcrumb,
BreadcrumbButton,
BreadcrumbDivider,
BreadcrumbItem,
} from '@fluentui/react-components'
import { FC, memo, useMemo } from 'react'

import { useDataStore } from '../../../store/store.js'

export const CommunityBreadcrumbs: FC = memo(function CommunityBreadcrumbs() {
const state = useDataStore((s) => s.communityDashboard.state)
const setCommunityDashboardState = useDataStore(
(s) => s.communityDashboard.setState,
)
const setCommunityManageState = useDataStore(
(s) => s.communityManage.setState,
)
const communityManageState = useDataStore((s) => s.communityManage.state)
const communityToManage = useDataStore(
(s) => s.communityManage.communityToManage,
)

const communityManageMessage = useMemo(() => {
switch (communityManageState) {
case 'users':
return 'Users'
case 'issues':
return 'Issues'
case 'pull-requests':
return 'Pull Requests'
default:
return ''
}
}, [communityManageState])

if (state == 'overview') {
return <></>
}

return (
<Breadcrumb size="large">
<BreadcrumbItem>
<BreadcrumbButton
onClick={() => {
setCommunityDashboardState('overview')
setCommunityManageState('overview')
}}
>
Communities
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbDivider />
<BreadcrumbItem>
<BreadcrumbButton onClick={() => setCommunityManageState('overview')}>
Manage {communityToManage?.name}
</BreadcrumbButton>
</BreadcrumbItem>
{communityManageMessage !== '' && (
<>
<BreadcrumbDivider />
<BreadcrumbItem>
<BreadcrumbButton>{communityManageMessage}</BreadcrumbButton>
</BreadcrumbItem>
</>
)}
</Breadcrumb>
)
})

This file was deleted.

47 changes: 5 additions & 42 deletions src/renderer/src/pages/dashboard/community/DashboardCommunity.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { Button } from '@fluentui/react-components'
import { Add32Filled, People32Filled } from '@fluentui/react-icons'
import { FC, memo, useMemo } from 'react'

import { StyledCard } from '../../../components/index.js'
import { useDataStore } from '../../../store/store.js'
import { useHeadingsStyles } from '../../../styles/index.js'
import { CommunityTable } from './CommunityTable.js'
import { useDashboardCommunityStyle } from './DashboardCommunity.styles.js'
import { CommunityDeploy } from './deploy/CommunityDeploy.js'
import { JoinCommunity } from './join/JoinCommunity.js'
import { CommunityBreadcrumbs } from './CommunityBreadcrumbs.js'
import { ManageCommunity } from './manage/ManageCommunity.js'
import { CommunityOverview } from './overview/CommunityOverview.js'

export const DashboardCommunity: FC = memo(function DashboardCommunity() {
const headerStyles = useHeadingsStyles()
Expand All @@ -19,53 +15,20 @@ export const DashboardCommunity: FC = memo(function DashboardCommunity() {

const Component: FC = useMemo(() => {
switch (communityDashboardState) {
case 'join':
return JoinCommunity
case 'deploy':
return CommunityDeploy
case 'overview':
return CommunityOverview
case 'manage':
return ManageCommunity
default:
return DashboardCommunityButtons
}
}, [communityDashboardState])

return (
<>
<h2 className={headerStyles.pageHeading}>Communities</h2>
<StyledCard>
<CommunityTable />
<br />
<CommunityBreadcrumbs />
<Component />
</StyledCard>
</>
)
})

export const DashboardCommunityButtons: FC = memo(
function DashboardCommunityButtons() {
const styles = useDashboardCommunityStyle()
const setCommunityDashboardState = useDataStore(
(s) => s.communityDashboard.setState,
)

return (
<div className={styles.buttonRow}>
<Button
appearance="primary"
icon={<People32Filled />}
onClick={() => setCommunityDashboardState('join')}
>
Join a Community
</Button>
<Button
appearance="primary"
icon={<Add32Filled />}
onClick={() => setCommunityDashboardState('deploy')}
>
Deploy a New Community
</Button>
</div>
)
},
)
Original file line number Diff line number Diff line change
@@ -1,54 +1,27 @@
import { Tab, TabList } from '@fluentui/react-components'
import { type FC, memo, useMemo, useState } from 'react'
import { type FC, memo, useMemo } from 'react'

import { Loader } from '../../../../components/Loader.js'
import { useDataStore } from '../../../../store/store.js'
import { IssuesPanel } from './IssuesPanel.js'
import { UserPanel } from './UserPanel.js'
import { IssuesPanel } from './issues/IssuesPanel.js'
import { ManageCommunityOverview } from './overview/ManageCommunityOverview.js'
import { UserPanel } from './users/UserPanel.js'

export const ManageCommunity: FC = memo(function ManageCommunity() {
const [selectedTab, setSelectedTab] = useState('users')
const selectedCommunity = useDataStore(
(s) => s.communityManage.communityToManage,
)!
const managedUsers = useDataStore((s) => s.communityManage.users)
const managedIssues = useDataStore((s) => s.communityManage.issues)
const loading = useMemo(() => {
return managedUsers == null || managedIssues == null
}, [managedUsers, managedIssues])
const communityManageState = useDataStore((s) => s.communityManage.state)

const Component: FC = useMemo(() => {
if (selectedTab === 'issues') {
return IssuesPanel
switch (communityManageState) {
case 'users':
return UserPanel
case 'issues':
return IssuesPanel
default:
return ManageCommunityOverview
}

return UserPanel
}, [selectedTab])
}, [communityManageState])

return (
<>
<h2>Manage {selectedCommunity.name}</h2>
<div>
<TabList
selectedValue={selectedTab}
onTabSelect={(e, d) => setSelectedTab(d.value as string)}
>
<Tab id="users" value="users">
Users
</Tab>
<Tab id="issues" value="issues">
Issues
</Tab>
<Tab id="pull-requests" value="pull-requests">
Pull Requests
</Tab>
</TabList>
<div>
<Loader isLoading={loading}>
<Component />
</Loader>
</div>
</div>
<Component />
</>
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import {
import { parse } from 'marked'
import { type FC, memo, useCallback, useState } from 'react'

import { Policy } from '../../../../../../electron/db/schema.js'
import type { CommunityIssue } from '../../../../../../electron/services/index.js'
import { Message } from '../../../../components/Message.js'
import { useDataStore } from '../../../../store/store.js'
import { useMessageStyles } from '../../../../styles/messages.js'
import { useManageCommunityStyles } from './styles.js'
import { Policy } from '../../../../../../../electron/db/schema.js'
import type { CommunityIssue } from '../../../../../../../electron/services/index.js'
import { Loader } from '../../../../../components/Loader.js'
import { Message } from '../../../../../components/Message.js'
import { useDataStore } from '../../../../../store/store.js'
import { useMessageStyles } from '../../../../../styles/messages.js'
import { useManageCommunityStyles } from '../styles.js'

const isManaged = (issue: CommunityIssue): boolean => {
return issue.policy != null
Expand All @@ -37,6 +38,7 @@ export const IssuesPanel: FC = memo(function IssuesPanel() {
const [selectedPolicy, setSelectedPolicy] = useState<Policy | null>(null)
const manageIssue = useDataStore((s) => s.communityManage.manageIssue)
const issues = useDataStore((s) => s.communityManage.issues)
const issuesLoading = useDataStore((s) => s.communityManage.issuesLoading)

const selectPolicy = useCallback(
(policy: Policy) => {
Expand Down Expand Up @@ -83,7 +85,7 @@ export const IssuesPanel: FC = memo(function IssuesPanel() {
}, [setSuccessMessage])

return (
<div>
<Loader isLoading={issuesLoading}>
<div className={styles.tableArea}>
<Table>
<TableHeader>
Expand Down Expand Up @@ -171,6 +173,6 @@ export const IssuesPanel: FC = memo(function IssuesPanel() {
)}
</div>
)}
</div>
</Loader>
)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { makeStyles, shorthands } from '@fluentui/react-components'

import { gov4GitTokens } from '../../../../../App/theme/tokens.js'

export const useManageCommunityOverviewStyles = makeStyles({
container: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
...shorthands.gap('16px', '28px'),
},
card: {
...shorthands.borderRadius(gov4GitTokens.borderRadiusXLarge),
boxShadow: gov4GitTokens.shadow16,
...shorthands.border('1px', 'solid', gov4GitTokens.g4gColorNeutralDark),
':hover': {
boxShadow: gov4GitTokens.shadow28,
backgroundColor: gov4GitTokens.g4gColorSecondaryGreen1,
cursor: 'pointer',
},
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Card } from '@fluentui/react-components'
import { FC } from 'react'

import { useDataStore } from '../../../../../store/store.js'
import { useManageCommunityOverviewStyles } from './ManageCommunityOverview.styles.js'

export const ManageCommunityOverview: FC = function ManageCommunityOverview() {
const styles = useManageCommunityOverviewStyles()
const setCommunityManageState = useDataStore(
(s) => s.communityManage.setState,
)

return (
<div className={styles.container}>
<Card
size="small"
className={styles.card}
onClick={() => setCommunityManageState('users')}
>
<h3>Manage Users</h3>
<div>
View active users, issue voting credits, and manage requests to join
the community.
</div>
</Card>
<Card
size="small"
className={styles.card}
onClick={() => setCommunityManageState('issues')}
>
<h3>Manage Issues</h3>
<div>
View all issues for selected GitHub community. Select issues to be
managed by Gov4Git.
</div>
</Card>
<Card
size="small"
className={styles.card}
onClick={() => setCommunityManageState('pull-requests')}
>
<h3>Manage Pull Requests</h3>
<div>
View all pull requests for selected GitHub community. Select pull
requests to be managed by Gov4Git.
</div>
</Card>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import {
} from '@fluentui/react-components'
import { type FC, FormEvent, memo, useCallback, useState } from 'react'

import { useDataStore } from '../../../../store/store.js'
import { useManageCommunityStyles } from './styles.js'
import { Loader } from '../../../../../components/Loader.js'
import { useDataStore } from '../../../../../store/store.js'
import { useManageCommunityStyles } from '../styles.js'

export const UserPanel: FC = memo(function UserPanel() {
const selectedCommunity = useDataStore(
Expand All @@ -26,6 +27,7 @@ export const UserPanel: FC = memo(function UserPanel() {
const [loading, setLoading] = useState(false)
const styles = useManageCommunityStyles()
const users = useDataStore((s) => s.communityManage.users)
const usersLoading = useDataStore((s) => s.communityManage.usersLoading)

const issueCredits = useCallback(
async (ev: FormEvent<HTMLFormElement>) => {
Expand All @@ -52,7 +54,7 @@ export const UserPanel: FC = memo(function UserPanel() {
)

return (
<>
<Loader isLoading={usersLoading}>
<div className={styles.tableArea}>
<Table>
<TableHeader>
Expand Down Expand Up @@ -111,6 +113,6 @@ export const UserPanel: FC = memo(function UserPanel() {
</div>
</form>
)}
</>
</Loader>
)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { makeStyles, shorthands } from '@fluentui/react-components'

export const useCommunityOverviewStyles = makeStyles({
container: {
display: 'grid',
...shorthands.gap('28px'),
},
buttonRow: {
display: 'flex',
...shorthands.gap('16px'),
alignItems: 'center',
},
})
Loading

0 comments on commit 1d804e7

Please sign in to comment.