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>

Reply via email to