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

add community dashboard #108

Merged
merged 1 commit into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading