This is an automated email from the ASF dual-hosted git repository. wu-sheng pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
commit 129b4472b7618101daa12b41f2fcbf3f13ce9e7b Author: Wu Sheng <[email protected]> AuthorDate: Tue May 12 10:19:53 2026 +0800 ui: stub admin and operate placeholder pages --- apps/ui/src/router/index.ts | 84 +++++++++++++++++++++++++++++++---- apps/ui/src/views/PlaceholderView.vue | 67 ++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 8 deletions(-) diff --git a/apps/ui/src/router/index.ts b/apps/ui/src/router/index.ts index 3ba0a0b..a597c20 100644 --- a/apps/ui/src/router/index.ts +++ b/apps/ui/src/router/index.ts @@ -14,9 +14,78 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createRouter, createWebHistory } from 'vue-router'; +import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'; import { useAuthStore } from '@/stores/auth'; +const shellRoutes: RouteRecordRaw[] = [ + { + path: '', + name: 'home', + component: () => import('@/views/landing/LandingView.vue'), + }, + // Layer drill-down stubs + { + path: 'layer/:layerKey', + name: 'layer-overview', + component: () => import('@/views/PlaceholderView.vue'), + props: (route) => ({ + title: `Layer · ${route.params.layerKey}`, + phase: 'Phase 2', + note: 'Layer overview · KPIs, throughput, services table, constellation.', + }), + }, + { + path: 'layer/:layerKey/services', + component: () => import('@/views/PlaceholderView.vue'), + props: (route) => ({ + title: `${route.params.layerKey} · Services`, + phase: 'Phase 2', + }), + }, + { + path: 'layer/:layerKey/instances', + component: () => import('@/views/PlaceholderView.vue'), + props: (route) => ({ + title: `${route.params.layerKey} · Instances`, + phase: 'Phase 3', + }), + }, + { + path: 'layer/:layerKey/endpoints', + component: () => import('@/views/PlaceholderView.vue'), + props: (route) => ({ + title: `${route.params.layerKey} · Endpoints`, + phase: 'Phase 3', + }), + }, + { + path: 'layer/:layerKey/topology', + component: () => import('@/views/PlaceholderView.vue'), + props: (route) => ({ + title: `${route.params.layerKey} · Topology`, + phase: 'Phase 4', + note: 'Three variants: force-directed, hierarchical DAG, hex/honeycomb.', + }), + }, + + // Telemetry + { path: 'dashboards', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Dashboards', phase: 'Phase 3', note: 'Widget grid, per-scope templates, MQE editor.' } }, + { path: 'operate/traces', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Trace explorer', phase: 'Phase 5', note: 'Native (v2/v1) + Zipkin Lens, switchable.' } }, + { path: 'operate/traces/:traceId', component: () => import('@/views/PlaceholderView.vue'), props: (r) => ({ title: `Trace · ${r.params.traceId}`, phase: 'Phase 5' }) }, + { path: 'operate/logs', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Log explorer', phase: 'Phase 5' } }, + { path: 'profiling', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Profiling', phase: 'Phase 8', note: 'Sampled · async-profiler · eBPF · Go pprof — unified flame graph.' } }, + { path: 'operate/events', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Events', phase: 'Phase 5' } }, + + // Operate + { path: 'operate/alarms', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Alarms', phase: 'Phase 5', note: 'Read-only; recovery is backend-auto. Live debug card via admin REST.' } }, + + // Admin + { path: 'cluster', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Cluster status', phase: 'Phase 6 / 7', note: 'Module activity matrix · storage health · receiver activity · effective config tree · TTL grid.' } }, + { path: 'admin/users', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Users', phase: 'Phase 7' } }, + { path: 'admin/roles', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Roles & permissions', phase: 'Phase 7' } }, + { path: 'admin/audit', component: () => import('@/views/PlaceholderView.vue'), props: { title: 'Audit log', phase: 'Phase 7' } }, +]; + const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ @@ -29,13 +98,12 @@ const router = createRouter({ { path: '/', component: () => import('@/components/shell/AppShell.vue'), - children: [ - { - path: '', - name: 'home', - component: () => import('@/views/landing/LandingView.vue'), - }, - ], + children: shellRoutes, + }, + { + path: '/:catchAll(.*)*', + component: () => import('@/views/PlaceholderView.vue'), + props: { title: 'Not found', phase: 'never', note: 'No route matches.' }, }, ], }); diff --git a/apps/ui/src/views/PlaceholderView.vue b/apps/ui/src/views/PlaceholderView.vue new file mode 100644 index 0000000..57094ba --- /dev/null +++ b/apps/ui/src/views/PlaceholderView.vue @@ -0,0 +1,67 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<script setup lang="ts"> +defineProps<{ title: string; phase: string; note?: string }>(); +</script> + +<template> + <div class="ph"> + <div class="ph-card"> + <div class="ph-kicker">Coming in {{ phase }}</div> + <h1>{{ title }}</h1> + <p v-if="note">{{ note }}</p> + </div> + </div> +</template> + +<style scoped> +.ph { + display: flex; + align-items: center; + justify-content: center; + min-height: 60vh; + padding: 32px; +} +.ph-card { + background: var(--sw-bg-1); + border: 1px solid var(--sw-line); + border-radius: 10px; + padding: 28px 32px; + max-width: 520px; + text-align: center; +} +.ph-kicker { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--sw-accent); + margin-bottom: 10px; +} +.ph-card h1 { + font-size: 22px; + font-weight: 600; + letter-spacing: -0.02em; + color: var(--sw-fg-0); + margin: 0 0 8px; +} +.ph-card p { + font-size: 12px; + color: var(--sw-fg-2); + margin: 0; + line-height: 1.5; +} +</style>
