@meddleware/dao-ui 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +28 -6
- package/src/App.vue +7 -3
- package/src/DaoView.vue +8 -16
- package/src/components/ProposalRow.vue +63 -36
- package/src/composables/useDaoEvents.ts +3 -2
- package/src/composables/useEpoch.ts +3 -2
- package/src/composables/useGates.ts +4 -3
- package/src/composables/usePlatformConfig.ts +3 -2
- package/src/styles/qt.css +61 -231
- package/src/tabs/GovernanceTab.vue +42 -28
- package/src/tabs/HistoryTab.vue +76 -59
- package/src/tabs/OverviewTab.vue +38 -39
- package/src/tabs/ProposalsTab.vue +9 -14
- package/src/tabs/TreasuryTab.vue +23 -22
- package/src/components/DataTable.vue +0 -26
- package/src/components/Panel.vue +0 -13
- package/src/components/StatusBar.vue +0 -36
- package/src/components/TabBar.vue +0 -19
package/src/tabs/OverviewTab.vue
CHANGED
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
// Overview tab: treasury balance + commission, platform activity counters (active gates,
|
|
3
3
|
// accesses minted/consumed derived from the event feed), and a recent-activity list.
|
|
4
4
|
import { computed } from 'vue'
|
|
5
|
-
import Panel from '../components/Panel.vue'
|
|
6
5
|
import AmountCell from '../components/AmountCell.vue'
|
|
7
6
|
import { usePlatformConfig } from '../composables/usePlatformConfig.js'
|
|
8
7
|
import { useTreasury } from '../composables/useTreasury.js'
|
|
9
8
|
import { useDaoEvents } from '../composables/useDaoEvents.js'
|
|
10
9
|
import { useGates } from '../composables/useGates.js'
|
|
11
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
CopyableAddress,
|
|
12
|
+
ExplorerLink,
|
|
13
|
+
suiExplorerUrl,
|
|
14
|
+
UiPanel,
|
|
15
|
+
UiStatGrid,
|
|
16
|
+
UiStatRow,
|
|
17
|
+
UiActivityFeed,
|
|
18
|
+
UiActivityItem,
|
|
19
|
+
} from '@meddleware/ui'
|
|
12
20
|
import { NETWORK } from '../config.js'
|
|
13
21
|
import type { DaoEvent } from '../composables/useDaoEvents.js'
|
|
14
22
|
|
|
@@ -34,50 +42,41 @@ const accessesConsumed = computed(() => events.value.filter((e) => e.type === 'A
|
|
|
34
42
|
<template>
|
|
35
43
|
<div class="dao-overview-cols">
|
|
36
44
|
<!-- Left: treasury summary -->
|
|
37
|
-
<div
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
<span class="dao-stat-grid__label">Commission rate</span>
|
|
44
|
-
<span class="dao-stat-grid__value dao-mono">{{ commissionPct }}</span>
|
|
45
|
-
|
|
46
|
-
<span class="dao-stat-grid__label">Treasury address</span>
|
|
47
|
-
<span class="dao-stat-grid__value" style="text-align: left">
|
|
45
|
+
<div class="dao-stack dao-stack--tight">
|
|
46
|
+
<UiPanel title="Treasury Balance">
|
|
47
|
+
<UiStatGrid>
|
|
48
|
+
<UiStatRow label="SUI balance"><AmountCell :mist="balance" /></UiStatRow>
|
|
49
|
+
<UiStatRow label="Commission rate">{{ commissionPct }}</UiStatRow>
|
|
50
|
+
<UiStatRow label="Treasury address" align="left">
|
|
48
51
|
<CopyableAddress v-if="config?.treasury" :address="config.treasury">
|
|
49
52
|
<ExplorerLink :href="suiExplorerUrl('account', config.treasury, NETWORK)" :value="config.treasury" />
|
|
50
53
|
</CopyableAddress>
|
|
51
|
-
<span v-else class="dao-mono
|
|
52
|
-
</
|
|
53
|
-
</
|
|
54
|
-
</
|
|
55
|
-
|
|
56
|
-
<Panel title="Platform Activity">
|
|
57
|
-
<div class="dao-stat-grid">
|
|
58
|
-
<span class="dao-stat-grid__label">Active gates</span>
|
|
59
|
-
<span class="dao-stat-grid__value dao-mono">{{ gatesLoading ? '…' : gates.length }}</span>
|
|
60
|
-
|
|
61
|
-
<span class="dao-stat-grid__label">Accesses minted</span>
|
|
62
|
-
<span class="dao-stat-grid__value dao-mono">{{ accessesMinted || '—' }}</span>
|
|
54
|
+
<span v-else class="dao-mono dao-mono--sm">—</span>
|
|
55
|
+
</UiStatRow>
|
|
56
|
+
</UiStatGrid>
|
|
57
|
+
</UiPanel>
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
<UiPanel title="Platform Activity">
|
|
60
|
+
<UiStatGrid>
|
|
61
|
+
<UiStatRow label="Active gates">{{ gatesLoading ? '…' : gates.length }}</UiStatRow>
|
|
62
|
+
<UiStatRow label="Accesses minted">{{ accessesMinted || '—' }}</UiStatRow>
|
|
63
|
+
<UiStatRow label="Accesses consumed">{{ accessesConsumed || '—' }}</UiStatRow>
|
|
64
|
+
</UiStatGrid>
|
|
65
|
+
</UiPanel>
|
|
68
66
|
</div>
|
|
69
67
|
|
|
70
68
|
<!-- Right: recent activity -->
|
|
71
|
-
<
|
|
72
|
-
<p v-if="eventsLoading" class="dao-muted
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
<UiPanel title="Recent Activity">
|
|
70
|
+
<p v-if="eventsLoading" class="dao-muted dao-flush">Loading events…</p>
|
|
71
|
+
<UiActivityFeed v-else-if="events.length">
|
|
72
|
+
<UiActivityItem
|
|
73
|
+
v-for="ev in events"
|
|
74
|
+
:key="ev.txDigest"
|
|
75
|
+
:type="eventLabel[ev.type]"
|
|
76
|
+
:time="`ckpt ${ev.checkpoint ?? '?'}`"
|
|
77
|
+
/>
|
|
78
|
+
</UiActivityFeed>
|
|
80
79
|
<p v-else class="dao-placeholder">No recent events.</p>
|
|
81
|
-
</
|
|
80
|
+
</UiPanel>
|
|
82
81
|
</div>
|
|
83
82
|
</template>
|
|
@@ -10,18 +10,13 @@ const { epoch } = useEpoch()
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</template>
|
|
23
|
-
<div v-else class="dao-placeholder">
|
|
24
|
-
No proposals yet.
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
13
|
+
<template v-if="proposals.length > 0">
|
|
14
|
+
<h2 class="dao-section-title">Active & Pending Proposals</h2>
|
|
15
|
+
<ul role="list">
|
|
16
|
+
<li v-for="p in proposals" :key="p.id">
|
|
17
|
+
<ProposalRow :proposal="p" :current-epoch="epoch" />
|
|
18
|
+
</li>
|
|
19
|
+
</ul>
|
|
20
|
+
</template>
|
|
21
|
+
<p v-else class="dao-placeholder">No proposals yet.</p>
|
|
27
22
|
</template>
|
package/src/tabs/TreasuryTab.vue
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
// Treasury tab: commission rate + live SUI balance + treasury address, plus the table
|
|
3
3
|
// of Community Gates the treasury controls (discovered via AdminCap ownership).
|
|
4
4
|
import { computed } from 'vue'
|
|
5
|
-
import Panel from '../components/Panel.vue'
|
|
6
5
|
import AmountCell from '../components/AmountCell.vue'
|
|
7
|
-
import DataTable from '../components/DataTable.vue'
|
|
8
6
|
import { usePlatformConfig } from '../composables/usePlatformConfig.js'
|
|
9
7
|
import { useTreasury } from '../composables/useTreasury.js'
|
|
10
8
|
import { useGates } from '../composables/useGates.js'
|
|
11
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
CopyableAddress,
|
|
11
|
+
ExplorerLink,
|
|
12
|
+
suiExplorerUrl,
|
|
13
|
+
UiPanel,
|
|
14
|
+
UiStatGrid,
|
|
15
|
+
UiStatRow,
|
|
16
|
+
UiDataTable,
|
|
17
|
+
} from '@meddleware/ui'
|
|
12
18
|
import { NETWORK } from '../config.js'
|
|
13
19
|
|
|
14
20
|
const { config, loading: cfgLoading, error: cfgErr } = usePlatformConfig()
|
|
@@ -26,32 +32,27 @@ function formatPrice(mist: bigint): string {
|
|
|
26
32
|
</script>
|
|
27
33
|
|
|
28
34
|
<template>
|
|
29
|
-
<div
|
|
30
|
-
<
|
|
35
|
+
<div class="dao-stack">
|
|
36
|
+
<UiPanel title="Treasury">
|
|
31
37
|
<p v-if="cfgLoading" class="dao-muted">Loading…</p>
|
|
32
38
|
<p v-else-if="cfgErr" class="dao-muted">{{ cfgErr }}</p>
|
|
33
39
|
<template v-else-if="config">
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
<span class="dao-stat-grid__label">Current balance</span>
|
|
39
|
-
<AmountCell class="dao-stat-grid__value" :mist="balance" />
|
|
40
|
-
|
|
41
|
-
<span class="dao-stat-grid__label">Treasury address</span>
|
|
42
|
-
<span class="dao-stat-grid__value" style="text-align: left">
|
|
40
|
+
<UiStatGrid class="dao-stat-grid">
|
|
41
|
+
<UiStatRow label="Commission rate">{{ commissionPct }} ({{ config.commissionBps }} bps)</UiStatRow>
|
|
42
|
+
<UiStatRow label="Current balance"><AmountCell :mist="balance" /></UiStatRow>
|
|
43
|
+
<UiStatRow label="Treasury address" align="left">
|
|
43
44
|
<CopyableAddress :address="config.treasury">
|
|
44
45
|
<ExplorerLink :href="suiExplorerUrl('account', config.treasury, NETWORK)" :value="config.treasury" />
|
|
45
46
|
</CopyableAddress>
|
|
46
|
-
</
|
|
47
|
-
</
|
|
47
|
+
</UiStatRow>
|
|
48
|
+
</UiStatGrid>
|
|
48
49
|
</template>
|
|
49
50
|
<p v-else class="dao-muted">PlatformConfig not loaded.</p>
|
|
50
|
-
</
|
|
51
|
+
</UiPanel>
|
|
51
52
|
|
|
52
|
-
<
|
|
53
|
+
<UiPanel title="Community Gates">
|
|
53
54
|
<p v-if="gatesLoading" class="dao-muted">Loading gates…</p>
|
|
54
|
-
<
|
|
55
|
+
<UiDataTable v-else-if="gates.length" :empty="'No gates found'">
|
|
55
56
|
<template #head>
|
|
56
57
|
<th>Gate name</th>
|
|
57
58
|
<th>Price</th>
|
|
@@ -60,14 +61,14 @@ function formatPrice(mist: bigint): string {
|
|
|
60
61
|
<tr v-for="gate in gates" :key="gate.id">
|
|
61
62
|
<td>{{ gate.name }}</td>
|
|
62
63
|
<td class="dao-amount">{{ formatPrice(gate.price) }}</td>
|
|
63
|
-
<td class="dao-mono
|
|
64
|
+
<td class="dao-mono dao-mono--sm dao-nowrap">
|
|
64
65
|
<CopyableAddress :address="gate.id" label="Copy object ID">
|
|
65
66
|
<ExplorerLink :href="suiExplorerUrl('object', gate.id, NETWORK)" :value="gate.id" />
|
|
66
67
|
</CopyableAddress>
|
|
67
68
|
</td>
|
|
68
69
|
</tr>
|
|
69
|
-
</
|
|
70
|
+
</UiDataTable>
|
|
70
71
|
<p v-else class="dao-placeholder">No gates found.</p>
|
|
71
|
-
</
|
|
72
|
+
</UiPanel>
|
|
72
73
|
</div>
|
|
73
74
|
</template>
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
// Scrollable table shell with a `head` slot (header cells) and default slot (rows).
|
|
3
|
-
// Renders the `empty` message when no rows are provided.
|
|
4
|
-
defineProps<{ empty?: string }>()
|
|
5
|
-
|
|
6
|
-
const slots = defineSlots<{
|
|
7
|
-
head(): unknown
|
|
8
|
-
default(): unknown
|
|
9
|
-
}>()
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<template>
|
|
13
|
-
<div style="overflow-x: auto">
|
|
14
|
-
<table class="dao-table">
|
|
15
|
-
<thead>
|
|
16
|
-
<tr>
|
|
17
|
-
<slot name="head" />
|
|
18
|
-
</tr>
|
|
19
|
-
</thead>
|
|
20
|
-
<tbody>
|
|
21
|
-
<slot />
|
|
22
|
-
</tbody>
|
|
23
|
-
</table>
|
|
24
|
-
<p v-if="empty && !slots.default" class="dao-placeholder">{{ empty }}</p>
|
|
25
|
-
</div>
|
|
26
|
-
</template>
|
package/src/components/Panel.vue
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
// Titled content panel — the console's basic surface primitive. Optional heading + default slot.
|
|
3
|
-
defineProps<{ title?: string }>()
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<template>
|
|
7
|
-
<div class="dao-panel">
|
|
8
|
-
<div v-if="title" class="dao-panel__head">{{ title }}</div>
|
|
9
|
-
<div class="dao-panel__body">
|
|
10
|
-
<slot />
|
|
11
|
-
</div>
|
|
12
|
-
</div>
|
|
13
|
-
</template>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
// Bottom status bar: network + health dot (error-driven), current epoch, and a
|
|
3
|
-
// relative "refreshed Ns ago" timestamp. Purely presentational.
|
|
4
|
-
import { computed } from 'vue'
|
|
5
|
-
import { NETWORK } from '../config.js'
|
|
6
|
-
|
|
7
|
-
const props = defineProps<{
|
|
8
|
-
epoch: number | null
|
|
9
|
-
lastRefresh: Date | null
|
|
10
|
-
error?: boolean
|
|
11
|
-
}>()
|
|
12
|
-
|
|
13
|
-
const dotClass = computed(() => (props.error ? 'dao-statusbar__dot--error' : 'dao-statusbar__dot--ok'))
|
|
14
|
-
|
|
15
|
-
function timeAgo(d: Date): string {
|
|
16
|
-
const s = Math.floor((Date.now() - d.getTime()) / 1000)
|
|
17
|
-
if (s < 5) return 'just now'
|
|
18
|
-
if (s < 60) return `${s}s ago`
|
|
19
|
-
return `${Math.floor(s / 60)}m ago`
|
|
20
|
-
}
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<template>
|
|
24
|
-
<footer class="dao-statusbar">
|
|
25
|
-
<span class="dao-statusbar__item">
|
|
26
|
-
<span class="dao-statusbar__dot" :class="dotClass" />
|
|
27
|
-
{{ NETWORK.charAt(0).toUpperCase() + NETWORK.slice(1) }}
|
|
28
|
-
</span>
|
|
29
|
-
<span class="dao-statusbar__sep">│</span>
|
|
30
|
-
<span v-if="epoch !== null" class="dao-statusbar__item">Epoch {{ epoch }}</span>
|
|
31
|
-
<span v-else class="dao-statusbar__item dao-muted">Epoch —</span>
|
|
32
|
-
<span class="dao-statusbar__sep">│</span>
|
|
33
|
-
<span v-if="lastRefresh" class="dao-statusbar__item">Refreshed {{ timeAgo(lastRefresh) }}</span>
|
|
34
|
-
<span v-else class="dao-statusbar__item dao-muted">Loading…</span>
|
|
35
|
-
</footer>
|
|
36
|
-
</template>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
// Thin wrapper over AppTabNav variant="raised" from @meddleware/ui.
|
|
3
|
-
// Keeps dao-ui's internal import path stable while using the shared component.
|
|
4
|
-
import { AppTabNav } from '@meddleware/ui'
|
|
5
|
-
export type { AppTab as Tab } from '@meddleware/ui'
|
|
6
|
-
|
|
7
|
-
defineProps<{ tabs: { id: string; label: string }[]; modelValue: string }>()
|
|
8
|
-
const emit = defineEmits<{ 'update:modelValue': [id: string] }>()
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<template>
|
|
12
|
-
<AppTabNav
|
|
13
|
-
:tabs="tabs"
|
|
14
|
-
:model-value="modelValue"
|
|
15
|
-
variant="raised"
|
|
16
|
-
aria-label="DAO sections"
|
|
17
|
-
@update:model-value="emit('update:modelValue', $event)"
|
|
18
|
-
/>
|
|
19
|
-
</template>
|