@meddleware/dashboard 0.1.10 → 0.1.12
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 +6 -6
- package/src/App.vue +38 -19
- package/src/components/NetworkSelector.vue +113 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Meddleware tools hub — Vue 3 SPA listing hosted services (Walrus, Access Gate) with white-label deploy options.",
|
|
5
5
|
"author": "Meddleware <dev@meddleware.co.uk>",
|
|
6
6
|
"license": "0BSD",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@meddleware/access-gate-ui": "^0.1.
|
|
29
|
+
"@meddleware/access-gate-ui": "^0.1.5",
|
|
30
30
|
"@meddleware/design-tokens": "^0.1.2",
|
|
31
|
-
"@meddleware/seal-ui": "^0.0.
|
|
32
|
-
"@meddleware/ui": "^0.1.
|
|
33
|
-
"@meddleware/wallet-adapter": "^0.0.
|
|
34
|
-
"@meddleware/walrus-ui": "^0.1.
|
|
31
|
+
"@meddleware/seal-ui": "^0.0.7",
|
|
32
|
+
"@meddleware/ui": "^0.1.7",
|
|
33
|
+
"@meddleware/wallet-adapter": "^0.0.5",
|
|
34
|
+
"@meddleware/walrus-ui": "^0.1.7",
|
|
35
35
|
"pinia": "^4.0.2",
|
|
36
36
|
"vue": "^3.5.40",
|
|
37
37
|
"vue-router": "^5.2.0"
|
package/src/App.vue
CHANGED
|
@@ -3,10 +3,11 @@ import { computed } from 'vue'
|
|
|
3
3
|
import { useRoute, RouterView } from 'vue-router'
|
|
4
4
|
import {
|
|
5
5
|
AppHeader, AppSidebar,
|
|
6
|
-
ColorModeControl, SidebarItem, StatusWidget,
|
|
6
|
+
ColorModeControl, SidebarItem, StatusWidget, CopyableAddress,
|
|
7
7
|
useColorMode,
|
|
8
8
|
} from '@meddleware/ui'
|
|
9
|
-
import { useWallet
|
|
9
|
+
import { useWallet } from '@meddleware/wallet-adapter'
|
|
10
|
+
import NetworkSelector from './components/NetworkSelector.vue'
|
|
10
11
|
|
|
11
12
|
const { mode, set } = useColorMode('dark')
|
|
12
13
|
const route = useRoute()
|
|
@@ -21,10 +22,6 @@ const isSealedStorage = computed(() => route.path === '/sealed-storage')
|
|
|
21
22
|
const { account, disconnect } = useWallet({
|
|
22
23
|
requiredFeatures: ['sui:signTransaction', 'sui:signPersonalMessage'],
|
|
23
24
|
})
|
|
24
|
-
|
|
25
|
-
function shortAddr(addr: string): string {
|
|
26
|
-
return `${addr.slice(0, 6)}…${addr.slice(-4)}`
|
|
27
|
-
}
|
|
28
25
|
</script>
|
|
29
26
|
|
|
30
27
|
<template>
|
|
@@ -35,7 +32,6 @@ function shortAddr(addr: string): string {
|
|
|
35
32
|
<span>Meddleware</span>
|
|
36
33
|
</template>
|
|
37
34
|
<template #actions>
|
|
38
|
-
<StatusWidget />
|
|
39
35
|
<ColorModeControl :model-value="mode" @update:model-value="set" />
|
|
40
36
|
</template>
|
|
41
37
|
</AppHeader>
|
|
@@ -53,12 +49,20 @@ function shortAddr(addr: string): string {
|
|
|
53
49
|
</router-link>
|
|
54
50
|
</nav>
|
|
55
51
|
|
|
52
|
+
<template #body>
|
|
53
|
+
<NetworkSelector />
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
56
|
<template #foot>
|
|
57
|
+
<StatusWidget class="sidebar-status" />
|
|
57
58
|
<div v-if="account" class="wallet-connected">
|
|
58
|
-
<
|
|
59
|
+
<CopyableAddress :address="account.address" />
|
|
59
60
|
<button type="button" class="wallet-disconnect" @click="disconnect">Disconnect</button>
|
|
60
61
|
</div>
|
|
61
|
-
<
|
|
62
|
+
<div v-else class="wallet-disconnected">
|
|
63
|
+
<span class="wallet-status-dot" aria-hidden="true"></span>
|
|
64
|
+
<span class="wallet-status-label">Not connected</span>
|
|
65
|
+
</div>
|
|
62
66
|
<p class="sidebar-copyright">© {{ new Date().getFullYear() }} Meddleware</p>
|
|
63
67
|
</template>
|
|
64
68
|
</AppSidebar>
|
|
@@ -96,7 +100,11 @@ function shortAddr(addr: string): string {
|
|
|
96
100
|
color: var(--gold);
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
/* ── Sidebar
|
|
103
|
+
/* ── Sidebar foot ──────────────────────────────────────── */
|
|
104
|
+
.sidebar-status {
|
|
105
|
+
margin-bottom: 0.5rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
100
108
|
.wallet-connected {
|
|
101
109
|
display: flex;
|
|
102
110
|
align-items: center;
|
|
@@ -105,15 +113,6 @@ function shortAddr(addr: string): string {
|
|
|
105
113
|
margin-bottom: 0.75rem;
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
.wallet-addr {
|
|
109
|
-
font-family: monospace;
|
|
110
|
-
font-size: 0.8rem;
|
|
111
|
-
color: var(--muted);
|
|
112
|
-
white-space: nowrap;
|
|
113
|
-
overflow: hidden;
|
|
114
|
-
text-overflow: ellipsis;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
116
|
.wallet-disconnect {
|
|
118
117
|
background: none;
|
|
119
118
|
border: none;
|
|
@@ -130,6 +129,26 @@ function shortAddr(addr: string): string {
|
|
|
130
129
|
color: var(--text);
|
|
131
130
|
}
|
|
132
131
|
|
|
132
|
+
.wallet-disconnected {
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
gap: 0.45rem;
|
|
136
|
+
margin-bottom: 0.75rem;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.wallet-status-dot {
|
|
140
|
+
width: 6px;
|
|
141
|
+
height: 6px;
|
|
142
|
+
border-radius: 50%;
|
|
143
|
+
background: var(--muted, #666);
|
|
144
|
+
flex-shrink: 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.wallet-status-label {
|
|
148
|
+
font-size: 0.8rem;
|
|
149
|
+
color: var(--muted);
|
|
150
|
+
}
|
|
151
|
+
|
|
133
152
|
.sidebar-copyright {
|
|
134
153
|
font-size: 0.75rem;
|
|
135
154
|
color: var(--muted);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// Network selector for the dashboard sidebar. Reads and writes the shared useNetwork()
|
|
3
|
+
// singleton so every embedded tool view reacts to the chosen network immediately.
|
|
4
|
+
import { ref, watch } from 'vue'
|
|
5
|
+
import { useNetwork } from '@meddleware/wallet-adapter'
|
|
6
|
+
import type { MwNetwork } from '@meddleware/wallet-adapter'
|
|
7
|
+
|
|
8
|
+
const { network, localnetRpc, setNetwork, setLocalnetRpc } = useNetwork()
|
|
9
|
+
|
|
10
|
+
const localnetInput = ref(localnetRpc.value)
|
|
11
|
+
|
|
12
|
+
// Sync input when singleton changes externally (e.g. another tab via storage event).
|
|
13
|
+
watch(localnetRpc, (v) => { localnetInput.value = v })
|
|
14
|
+
|
|
15
|
+
function onNetworkChange(e: Event): void {
|
|
16
|
+
setNetwork((e.target as HTMLSelectElement).value as MwNetwork)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function commitLocalnetUrl(): void {
|
|
20
|
+
const url = localnetInput.value.trim()
|
|
21
|
+
if (url) setLocalnetRpc(url)
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<div class="ns-root">
|
|
27
|
+
<label class="ns-label" for="ns-select">Network</label>
|
|
28
|
+
<select id="ns-select" class="ns-select" :value="network" @change="onNetworkChange">
|
|
29
|
+
<option value="testnet">Testnet</option>
|
|
30
|
+
<option value="mainnet">Mainnet</option>
|
|
31
|
+
<option value="localnet">Localnet</option>
|
|
32
|
+
</select>
|
|
33
|
+
|
|
34
|
+
<p v-if="network === 'mainnet'" class="ns-notice">Mainnet coming soon.</p>
|
|
35
|
+
|
|
36
|
+
<template v-if="network === 'localnet'">
|
|
37
|
+
<label class="ns-label ns-label--url" for="ns-localnet-url">RPC URL</label>
|
|
38
|
+
<input
|
|
39
|
+
id="ns-localnet-url"
|
|
40
|
+
v-model="localnetInput"
|
|
41
|
+
type="url"
|
|
42
|
+
class="ns-input"
|
|
43
|
+
placeholder="http://127.0.0.1:9000"
|
|
44
|
+
@blur="commitLocalnetUrl"
|
|
45
|
+
@keydown.enter="commitLocalnetUrl"
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<style scoped>
|
|
52
|
+
.ns-root {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
gap: 0.35rem;
|
|
56
|
+
padding: 0.75rem 1rem;
|
|
57
|
+
border-top: 1px solid var(--border, #333);
|
|
58
|
+
border-bottom: 1px solid var(--border, #333);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ns-label {
|
|
62
|
+
font-size: 0.7rem;
|
|
63
|
+
text-transform: uppercase;
|
|
64
|
+
letter-spacing: 0.06em;
|
|
65
|
+
color: var(--muted, #888);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.ns-label--url {
|
|
69
|
+
margin-top: 0.25rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.ns-select {
|
|
73
|
+
appearance: none;
|
|
74
|
+
background: var(--surface, transparent)
|
|
75
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888'/%3E%3C/svg%3E")
|
|
76
|
+
no-repeat right 0.6rem center;
|
|
77
|
+
border: 1px solid var(--border, #444);
|
|
78
|
+
border-radius: 6px;
|
|
79
|
+
color: var(--text, #f0f0f0);
|
|
80
|
+
font-size: 0.85rem;
|
|
81
|
+
padding: 0.35rem 1.75rem 0.35rem 0.6rem;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
width: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ns-select:focus {
|
|
87
|
+
outline: 2px solid var(--accent, #6366f1);
|
|
88
|
+
outline-offset: 1px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.ns-notice {
|
|
92
|
+
font-size: 0.75rem;
|
|
93
|
+
color: var(--muted, #888);
|
|
94
|
+
margin: 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ns-input {
|
|
98
|
+
background: var(--surface, transparent);
|
|
99
|
+
border: 1px solid var(--border, #444);
|
|
100
|
+
border-radius: 6px;
|
|
101
|
+
color: var(--text, #f0f0f0);
|
|
102
|
+
font-size: 0.8rem;
|
|
103
|
+
font-family: monospace;
|
|
104
|
+
padding: 0.35rem 0.6rem;
|
|
105
|
+
width: 100%;
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.ns-input:focus {
|
|
110
|
+
outline: 2px solid var(--accent, #6366f1);
|
|
111
|
+
outline-offset: 1px;
|
|
112
|
+
}
|
|
113
|
+
</style>
|