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

feat: initial governance ui #5327

Merged
merged 11 commits into from
Dec 2, 2022
3 changes: 3 additions & 0 deletions packages/desktop/lib/routers/actions/initialiseRouters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
CollectiblesRouter,
DashboardRouter,
dashboardRouter,
GovernanceRouter,
governanceRouter,
OnboardingRouter,
onboardingRouter,
SettingsRouter,
Expand Down Expand Up @@ -53,6 +55,7 @@ function initialiseBaseRouters(): void {
dashboardRouter.set(new DashboardRouter())
settingsRouter.set(new SettingsRouter())
collectiblesRouter.set(new CollectiblesRouter())
governanceRouter.set(new GovernanceRouter())
initialiseBaseOnboardingRouters()
}

Expand Down
2 changes: 2 additions & 0 deletions packages/desktop/lib/routers/actions/resetRouters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
appSetupRouter,
collectiblesRouter,
dashboardRouter,
governanceRouter,
ledgerSetupRouter,
loginRouter,
networkSetupRouter,
Expand Down Expand Up @@ -41,4 +42,5 @@ function resetBaseRouters(): void {
get(onboardingRouter).reset()
get(settingsRouter).reset()
get(collectiblesRouter).reset()
get(governanceRouter).reset()
}
2 changes: 2 additions & 0 deletions packages/desktop/views/dashboard/Dashboard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { Wallet } from './wallet'
import { onDestroy, onMount } from 'svelte'
import Collectibles from './collectibles/Collectibles.svelte'
import { Governance } from './governance'
import Sidebar from './Sidebar.svelte'
import TopNavigation from './TopNavigation.svelte'

Expand All @@ -29,6 +30,7 @@
wallet: Wallet,
settings: Settings,
collectibles: Collectibles,
governance: Governance,
developer: Developer,
}

Expand Down
10 changes: 10 additions & 0 deletions packages/desktop/views/dashboard/Sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
},
]
: []),
{
icon: 'governance',
label: localize('tabs.governance'),
route: DashboardRoute.Governance,
onClick: openGovernance,
},
...(features?.developerTools?.enabled && $activeProfile?.isDeveloperProfile
? [
{
Expand All @@ -72,6 +78,10 @@
$collectiblesRouter.reset()
}
jeeanribeiro marked this conversation as resolved.
Show resolved Hide resolved

function openGovernance(): void {
$dashboardRouter.goTo(DashboardRoute.Governance)
}

function openDeveloper(): void {
$dashboardRouter.goTo(DashboardRoute.Developer)
}
Expand Down
10 changes: 9 additions & 1 deletion packages/desktop/views/dashboard/TopNavigation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
collectiblesRouter,
DashboardRoute,
dashboardRoute,
GovernanceRoute,
governanceRoute,
governanceRouter,
SettingsRoute,
settingsRoute,
settingsRouter,
Expand All @@ -18,7 +21,7 @@

let showBackButton = false
$: {
if ($settingsRoute || $collectiblesRoute) {
if ($settingsRoute || $collectiblesRoute || $governanceRoute) {
showBackButton = isCorrectRoute()
}
}
Expand All @@ -30,6 +33,8 @@
return $settingsRoute !== SettingsRoute.Init
case DashboardRoute.Collectibles:
return $collectiblesRoute !== CollectiblesRoute.Gallery
case DashboardRoute.Governance:
return $governanceRoute !== GovernanceRoute.Proposals
default:
break
}
Expand All @@ -43,6 +48,9 @@
case DashboardRoute.Collectibles:
$collectiblesRouter.previous()
break
case DashboardRoute.Governance:
$governanceRouter.previous()
break
default:
break
}
Expand Down
15 changes: 15 additions & 0 deletions packages/desktop/views/dashboard/governance/Governance.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="typescript">
import { DetailsView, ProposalsView } from './views'
import { selectedAccount } from '@core/account'
import { GovernanceRoute, governanceRoute } from '@core/router'
</script>

{#if $selectedAccount}
{#key $selectedAccount?.index}
{#if $governanceRoute === GovernanceRoute.Proposals}
<ProposalsView />
{:else if $governanceRoute === GovernanceRoute.Details}
<DetailsView />
{/if}
{/key}
{/if}
1 change: 1 addition & 0 deletions packages/desktop/views/dashboard/governance/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Governance } from './Governance.svelte'
143 changes: 143 additions & 0 deletions packages/desktop/views/dashboard/governance/views/DetailsView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<script lang="typescript">
import { selectedProposal } from '@core/governance'
import { formatDate, localize } from '@core/i18n'
import { networkStatus } from '@core/network'
import { milestoneToDate } from '@core/utils'
import { Button, Text, MeatballMenuButton, Pane, ProposalStatusPill, TextType, FontWeight, Icon } from '@ui'
import { Icon as IconEnum } from '@auxiliary/icon'

const dateFormat = {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
} as Intl.DateTimeFormatOptions

const votesCounter = {
total: 0, // mocked data
power: '4821 SMR', // mocked data
}

const proposalInformation = {
countingEnds: formatDate(
milestoneToDate($networkStatus.currentMilestone, $selectedProposal?.milestones?.closed),
dateFormat
),
eventId: 'SGO-0001', // mocked data
nodeUrl: 'jfjk821391290jha.url', // mocked data
}

// just used for mocking
const questions = Array(4).fill('Should we burn the unclaimed tokens')
const options = ['This is option 1', 'This is option 2', 'This is option 3', 'Abstain']

let openedQuestionIndex = null

function handleMeatballMenu(): void {
return
}

function handleQuestionClick(index: number): void {
openedQuestionIndex = openedQuestionIndex === index ? null : index
}
</script>

<div class="w-full h-full flex flex-nowrap p-8 relative flex-1 space-x-4 bg-gray-50 dark:bg-gray-900">
<div class="w-2/5 flex flex-col space-y-4">
<Pane classes="p-6 flex flex-col flex-1">
<header-container class="flex justify-between items-center mb-4">
<ProposalStatusPill status={$selectedProposal?.status} />
<MeatballMenuButton onClick={handleMeatballMenu} />
</header-container>
<div class="flex flex-1 flex-col justify-between">
<Text type={TextType.h2}>{$selectedProposal?.title}</Text>
<div class="flex items-center cursor-pointer">
<Text fontSize="14" fontWeight={FontWeight.semibold} overrideColor classes="text-blue-500"
>{localize('views.governance.details.fullProposal')}</Text
>
<Icon icon={IconEnum.Link} height={16} classes="ml-0.5 text-blue-500" />
</div>
</div>
</Pane>
<Pane classes="p-6 h-fit">
<Text smaller classes="mb-5">
{localize('views.governance.details.yourVote.title')}
</Text>
<ul class="space-y-2">
{#each Object.keys(votesCounter) as counterKey}
<li class="flex justify-between bg-gray-50 px-4 py-3 rounded-lg">
<Text fontWeight={FontWeight.medium} overrideColor classes="text-gray-600">
{localize(`views.governance.details.yourVote.${counterKey}`)}
</Text>
<Text overrideColor classes="text-gray-600">
{votesCounter[counterKey]}
</Text>
</li>
{/each}
</ul>
</Pane>
<Pane classes="p-6 h-fit">
<Text smaller classes="mb-5">
{localize('views.governance.details.proposalInformation.title')}
</Text>
<ul class="space-y-2">
{#each Object.keys(proposalInformation) as counterKey}
<li class="flex justify-between bg-gray-50 px-4 py-3 rounded-lg">
<Text fontWeight={FontWeight.medium} overrideColor classes="text-gray-600">
{localize(`views.governance.details.proposalInformation.${counterKey}`)}
</Text>
<Text overrideColor classes="text-gray-600">
{proposalInformation[counterKey]}
</Text>
</li>
{/each}
</ul>
</Pane>
</div>
<Pane classes="w-3/5 h-full p-6 flex flex-col justify-between ">
<ul class="flex flex-1 flex-col space-y-5 overflow-y-scroll">
{#each questions as question, questionIndex}
<li
on:click={() => handleQuestionClick(questionIndex)}
class="flex flex-col px-5 py-4 rounded-xl border border-solid border-gray-200 cursor-pointer"
>
<div class="flex justify-between items-center">
<div class="flex flex-col">
<Text smaller fontWeight={FontWeight.bold} overrideColor classes="mb-1 text-blue-500"
>Question {questionIndex + 1}</Text
>
<Text fontWeight={FontWeight.bold} overrideColor classes="text-gray-900">{question}</Text>
</div>
<div class="transform {openedQuestionIndex === questionIndex ? 'rotate-180' : 'rotate-0'}">
<Icon icon={IconEnum.ChevronDown} classes="text-gray-500" />
</div>
</div>
<ul class:mt-4={openedQuestionIndex === questionIndex} class="space-y-2">
{#each options as option, optionIndex}
<li
class:hidden={openedQuestionIndex !== questionIndex}
class="flex justify-between items-center p-3 rounded-md border border-solid border-gray-200"
>
<div class="flex space-x-3">
<span
class="flex items-center justify-center h-5 w-5 text-12 text-700 text-gray-500 border border-solid border-gray-200"
>
{optionIndex + 1}
</span>
<Text fontWeight={FontWeight.medium}>{option}</Text>
</div>
<Icon icon={IconEnum.Info} width={10} height={10} classes="text-gray-600" />
</li>
{/each}
</ul>
</li>
{/each}
</ul>
<buttons-container class="flex w-full space-x-4 mt-6">
<Button outline classes="w-full">{localize('actions.cancel')}</Button>
<Button classes="w-full">{localize('actions.vote')}</Button>
</buttons-container>
</Pane>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="typescript">
import { Pane, Proposals, ProposalsDetails, VotingPower } from '@ui'
</script>

<div class="w-full h-full flex flex-nowrap p-8 relative flex-1 space-x-6 bg-gray-50 dark:bg-gray-900">
<div class="w-1/3 flex flex-col space-y-4">
<Pane classes="p-6 h-fit">
<VotingPower />
</Pane>
<Pane classes="p-6 h-fit">
<ProposalsDetails />
</Pane>
</div>
<span class="block w-0.5 h-full bg-gray-200" />
<div class="w-2/3">
<Proposals />
</div>
</div>
2 changes: 2 additions & 0 deletions packages/desktop/views/dashboard/governance/views/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as DetailsView } from './DetailsView.svelte'
export { default as ProposalsView } from './ProposalsView.svelte'
1 change: 1 addition & 0 deletions packages/desktop/views/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export * from './collectibles'
export * from './developer'
export * from './settings'
export * from './wallet'
export * from './governance'

export { default as Dashboard } from './Dashboard.svelte'
2 changes: 1 addition & 1 deletion packages/mobile/components/AsyncActivityTileFooter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
} from 'shared/components'
import { time } from '@core/app'
import { Icon as IconEnum } from '@lib/auxiliary/icon'
import { Position } from 'shared/components/Tooltip.svelte'
import { Position } from 'shared/components/enums'
import { localize } from '@core/i18n'

export let onClaim: () => unknown = () => {}
Expand Down
22 changes: 22 additions & 0 deletions packages/shared/components/ProposalStatusInfo.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="typescript">
import { ProposalStatusTimelineTooltip, ProposalStatusPill } from 'shared/components'
import { ProposalStatus, Position } from 'shared/components/enums'

export let milestones: Record<ProposalStatus, number>
export let status: ProposalStatus
export let position: Position = Position.Right

let anchor: HTMLElement
let isTooltipVisible = false

function showTooltip(show: boolean): void {
isTooltipVisible = show
}
</script>

<div bind:this={anchor} on:mouseenter={() => showTooltip(true)} on:mouseleave={() => showTooltip(false)}>
<ProposalStatusPill {status} />
</div>
{#if isTooltipVisible}
<ProposalStatusTimelineTooltip bind:anchor {milestones} {status} {position} />
{/if}