@meddleware/dao-ui 0.1.1 → 0.1.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meddleware/dao-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Meddleware DAO console — treasury overview, proposals, and governance on Sui.",
5
5
  "author": "Meddleware <dev@meddleware.co.uk>",
6
6
  "license": "0BSD",
package/src/DaoView.vue CHANGED
@@ -2,7 +2,11 @@
2
2
  // Core DAO tool UI — tab-based console with desktop-application aesthetics.
3
3
  // Rendered standalone by App.vue and embedded in the dashboard at the default route.
4
4
  // All chain reads are read-only; no wallet connection is required to view data.
5
- import { ref, shallowRef, computed } from 'vue'
5
+ //
6
+ // qt.css is imported here (not just in main.ts) so the styles are included when
7
+ // DaoView is consumed as a library by the dashboard or any other host.
8
+ import './styles/qt.css'
9
+ import { ref, computed } from 'vue'
6
10
  import TabBar from './components/TabBar.vue'
7
11
  import StatusBar from './components/StatusBar.vue'
8
12
  import OverviewTab from './tabs/OverviewTab.vue'
@@ -43,10 +47,6 @@ const { epoch } = useEpoch()
43
47
  <div class="dao-view">
44
48
  <div class="dao-toolbar">
45
49
  <button class="dao-toolbar__btn" @click="activeTab = 'overview'">🏛 Meddleware DAO</button>
46
- <span class="dao-toolbar__sep" />
47
- <span class="dao-muted" style="font-size: 0.75rem; padding: 0 4px">
48
- access_gate · testnet
49
- </span>
50
50
  </div>
51
51
 
52
52
  <TabBar :tabs="TABS" v-model="activeTab" />
@@ -5,7 +5,7 @@ import { PACKAGE_ID } from '../config.js'
5
5
  export interface DaoEvent {
6
6
  type: 'AccessMinted' | 'AccessConsumed' | 'GateCreated' | 'AccessBurned'
7
7
  txDigest: string
8
- timestampMs: number
8
+ checkpoint: string | null
9
9
  address?: string
10
10
  }
11
11
 
@@ -47,7 +47,7 @@ export function useDaoEvents(limit = 20) {
47
47
  all.push({
48
48
  type: label as DaoEvent['type'],
49
49
  txDigest: e.transactionDigest,
50
- timestampMs: 0,
50
+ checkpoint: e.checkpoint ?? null,
51
51
  address: String(f.recipient ?? f.creator ?? f.sender ?? ''),
52
52
  })
53
53
  }
package/src/styles/qt.css CHANGED
@@ -131,6 +131,9 @@
131
131
  border-top: 1px solid var(--border);
132
132
  flex-shrink: 0;
133
133
  font-family: var(--font-mono);
134
+ position: sticky;
135
+ bottom: 0;
136
+ z-index: 1;
134
137
  }
135
138
 
136
139
  .dao-statusbar__dot {
@@ -12,9 +12,8 @@ const eventLabel: Record<DaoEvent['type'], string> = {
12
12
  AccessBurned: 'Access Burned',
13
13
  }
14
14
 
15
- function shortTs(ms: number): string {
16
- if (!ms) return '—'
17
- return new Date(ms).toISOString().replace('T', ' ').slice(0, 19) + ' UTC'
15
+ function shortCkpt(ckpt: string | null): string {
16
+ return ckpt ? `ckpt ${ckpt}` : '—'
18
17
  }
19
18
 
20
19
  function shortAddr(addr: string | undefined): string {
@@ -42,10 +41,10 @@ function explorerUrl(digest: string): string {
42
41
  <template #head>
43
42
  <th>Type</th>
44
43
  <th>Address</th>
45
- <th>Time (UTC)</th>
44
+ <th>Checkpoint</th>
46
45
  <th>Tx</th>
47
46
  </template>
48
- <tr v-for="ev in events" :key="ev.txDigest + ev.timestampMs">
47
+ <tr v-for="ev in events" :key="ev.txDigest">
49
48
  <td>
50
49
  <span
51
50
  class="dao-badge"
@@ -57,7 +56,7 @@ function explorerUrl(digest: string): string {
57
56
  >{{ eventLabel[ev.type] }}</span>
58
57
  </td>
59
58
  <td class="dao-mono" style="font-size: 0.72rem">{{ shortAddr(ev.address) }}</td>
60
- <td class="dao-mono" style="font-size: 0.72rem">{{ shortTs(ev.timestampMs) }}</td>
59
+ <td class="dao-mono" style="font-size: 0.72rem">{{ shortCkpt(ev.checkpoint) }}</td>
61
60
  <td class="dao-mono" style="font-size: 0.72rem">
62
61
  <a :href="explorerUrl(ev.txDigest)" target="_blank" rel="noopener" style="color: var(--accent)">
63
62
  {{ ev.txDigest.slice(0, 8) }}…
@@ -5,19 +5,13 @@ import AmountCell from '../components/AmountCell.vue'
5
5
  import { usePlatformConfig } from '../composables/usePlatformConfig.js'
6
6
  import { useTreasury } from '../composables/useTreasury.js'
7
7
  import { useDaoEvents } from '../composables/useDaoEvents.js'
8
+ import { useGates } from '../composables/useGates.js'
8
9
  import type { DaoEvent } from '../composables/useDaoEvents.js'
9
10
 
10
11
  const { config } = usePlatformConfig()
11
12
  const { balance } = useTreasury(() => config.value?.treasury ?? null)
12
13
  const { events, loading: eventsLoading } = useDaoEvents(12)
13
-
14
- function timeAgo(ms: number): string {
15
- const s = Math.floor((Date.now() - ms) / 1000)
16
- if (s < 5) return 'just now'
17
- if (s < 60) return `${s}s ago`
18
- if (s < 3600) return `${Math.floor(s / 60)}m ago`
19
- return `${Math.floor(s / 3600)}h ago`
20
- }
14
+ const { gates } = useGates()
21
15
 
22
16
  const eventLabel: Record<DaoEvent['type'], string> = {
23
17
  AccessMinted: 'Access sold',
@@ -29,6 +23,9 @@ const eventLabel: Record<DaoEvent['type'], string> = {
29
23
  const commissionPct = computed(() =>
30
24
  config.value ? (config.value.commissionBps / 100).toFixed(2) + '%' : '—',
31
25
  )
26
+
27
+ const accessesMinted = computed(() => events.value.filter((e) => e.type === 'AccessMinted').length)
28
+ const accessesConsumed = computed(() => events.value.filter((e) => e.type === 'AccessConsumed').length)
32
29
  </script>
33
30
 
34
31
  <template>
@@ -54,21 +51,17 @@ const commissionPct = computed(() =>
54
51
  </div>
55
52
  </Panel>
56
53
 
57
- <Panel title="Platform Stats">
54
+ <Panel title="Platform Activity">
58
55
  <div class="dao-stat-grid">
59
- <span class="dao-stat-grid__label">Strategy NAV</span>
60
- <span class="dao-stat-grid__value dao-muted">—</span>
56
+ <span class="dao-stat-grid__label">Active gates</span>
57
+ <span class="dao-stat-grid__value dao-mono">{{ gates.length || '—' }}</span>
61
58
 
62
- <span class="dao-stat-grid__label">Buyback/burn</span>
63
- <span class="dao-stat-grid__value dao-muted">—</span>
59
+ <span class="dao-stat-grid__label">Accesses minted</span>
60
+ <span class="dao-stat-grid__value dao-mono">{{ accessesMinted || '—' }}</span>
64
61
 
65
- <span class="dao-stat-grid__label">Fee distributor</span>
66
- <span class="dao-stat-grid__value dao-muted">—</span>
62
+ <span class="dao-stat-grid__label">Accesses consumed</span>
63
+ <span class="dao-stat-grid__value dao-mono">{{ accessesConsumed || '—' }}</span>
67
64
  </div>
68
- <p class="dao-muted" style="margin: 8px 0 0; font-size: 0.72rem">
69
- Strategy NAV, buyback and fee distribution data will appear here when
70
- <code>vault_core</code> and <code>vault_fee_distributor</code> are deployed.
71
- </p>
72
65
  </Panel>
73
66
  </div>
74
67
 
@@ -76,10 +69,10 @@ const commissionPct = computed(() =>
76
69
  <Panel title="Recent Activity">
77
70
  <p v-if="eventsLoading" class="dao-muted" style="margin: 0">Loading events…</p>
78
71
  <ul v-else-if="events.length" class="dao-feed">
79
- <li v-for="ev in events" :key="ev.txDigest + ev.timestampMs" class="dao-feed__item">
72
+ <li v-for="ev in events" :key="ev.txDigest" class="dao-feed__item">
80
73
  <span class="dao-feed__dot" />
81
74
  <span class="dao-feed__type">{{ eventLabel[ev.type] }}</span>
82
- <span class="dao-feed__time">{{ timeAgo(ev.timestampMs) }}</span>
75
+ <span class="dao-feed__time">ckpt {{ ev.checkpoint ?? '?' }}</span>
83
76
  </li>
84
77
  </ul>
85
78
  <p v-else class="dao-placeholder">No recent events.</p>
@@ -9,11 +9,6 @@ const { epoch } = useEpoch()
9
9
 
10
10
  <template>
11
11
  <div>
12
- <div class="dao-notice">
13
- On-chain governance proposals will appear here once <code>vault_dao</code> is deployed.
14
- Contributions and voting will be enabled at that point.
15
- </div>
16
-
17
12
  <template v-if="proposals.length > 0">
18
13
  <p class="dao-section-title">Active &amp; Pending Proposals</p>
19
14
  <ProposalRow