fix(nacos): adapt service workbench layout to narrow panes
This commit is contained in:
2 files changed
+108
-15
No files matched your search
@@ -2821,9 +2821,9 @@ onBeforeUnmount(() => {
|
||||
</Pane>
|
||||
|
||||
<Pane :size="100 - nacosSplitSize" min-size="20">
|
||||
<div class="flex h-full min-h-0 flex-col">
|
||||
<div class="nacos-service-workbench flex h-full min-h-0 flex-col">
|
||||
<header class="shrink-0 border-b bg-background">
|
||||
<div class="flex min-h-16 flex-wrap items-center gap-x-3 gap-y-2 px-4 py-3">
|
||||
<div class="nacos-service-heading flex min-h-16 flex-wrap items-center gap-x-3 gap-y-2 px-4 py-3">
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="truncate text-base font-semibold">{{ selectedService?.serviceName || t("nacos.instances") }}</div>
|
||||
<div v-if="selectedService" class="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
|
||||
@@ -2838,9 +2838,9 @@ onBeforeUnmount(() => {
|
||||
{{ t("nacos.refresh") }}
|
||||
</Button>
|
||||
</div>
|
||||
<div v-if="selectedService" class="flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-muted/30 px-4 py-2">
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
<Input v-model="serviceCluster" class="h-8 w-40" :placeholder="t('nacos.filterInstanceCluster')" @keyup.enter="loadInstances" />
|
||||
<div v-if="selectedService" class="nacos-service-toolbar flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-muted/30 px-4 py-2">
|
||||
<div class="nacos-service-filter-group flex min-w-0 items-center gap-1">
|
||||
<Input v-model="serviceCluster" class="nacos-service-cluster-input h-8 min-w-0" :placeholder="t('nacos.filterInstanceCluster')" @keyup.enter="loadInstances" />
|
||||
<Button size="sm" variant="secondary" class="h-8" :disabled="instancesLoading" @click="loadInstances">{{ t("nacos.filter") }}</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -2855,7 +2855,7 @@ onBeforeUnmount(() => {
|
||||
>{{ t("nacos.clear") }}</Button
|
||||
>
|
||||
</div>
|
||||
<div class="ml-auto flex flex-wrap items-center gap-2">
|
||||
<div class="nacos-service-management-actions flex flex-wrap items-center gap-2">
|
||||
<div class="flex items-center gap-1 rounded-md border bg-background p-1">
|
||||
<span class="px-1 text-xs text-muted-foreground">{{ t("nacos.serviceSettings") }}</span>
|
||||
<Button
|
||||
@@ -2895,7 +2895,7 @@ onBeforeUnmount(() => {
|
||||
<span class="text-xs font-medium">{{ t("nacos.serviceDetails") }}</span>
|
||||
<span class="text-xs text-muted-foreground">{{ serviceDetailExpanded ? t("nacos.collapse") : t("nacos.expand") }}</span>
|
||||
</button>
|
||||
<div class="mt-2 grid grid-cols-2 gap-2 text-xs sm:grid-cols-4">
|
||||
<div class="nacos-service-stat-grid mt-2 grid gap-2 text-xs">
|
||||
<div class="rounded border bg-muted/20 px-2 py-1.5">
|
||||
<div class="text-muted-foreground">{{ t("nacos.instanceStat") }}</div>
|
||||
<div class="mt-0.5 font-medium">{{ selectedService.ipCount ?? instances.length }}</div>
|
||||
@@ -2913,7 +2913,7 @@ onBeforeUnmount(() => {
|
||||
<div class="mt-0.5 font-medium">{{ selectedServiceDetail?.protectThreshold ?? "-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="serviceDetailExpanded" class="mt-2 grid gap-2 text-xs lg:grid-cols-2">
|
||||
<div v-if="serviceDetailExpanded" class="nacos-service-detail-grid mt-2 grid gap-2 text-xs">
|
||||
<div class="min-w-0 rounded border p-2">
|
||||
<div class="mb-1 flex items-center justify-between text-muted-foreground">
|
||||
<span>{{ t("nacos.metadataLabel") }}</span
|
||||
@@ -2939,16 +2939,16 @@ onBeforeUnmount(() => {
|
||||
<div class="min-h-0 flex-1 overflow-auto bg-muted/20 p-3">
|
||||
<div v-if="instances.length" class="space-y-2">
|
||||
<article v-for="instance in instances" :key="instanceIdentity(instance)" class="rounded-lg border bg-background p-3 shadow-sm">
|
||||
<div class="flex flex-col gap-3 xl:flex-row xl:items-start xl:justify-between">
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="nacos-instance-layout flex gap-3">
|
||||
<div class="nacos-instance-main min-w-0">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="font-mono text-sm font-medium">{{ instance.ip }}:{{ instance.port }}</span>
|
||||
<span class="nacos-instance-address max-w-full font-mono text-sm font-medium">{{ instance.ip }}:{{ instance.port }}</span>
|
||||
<Badge variant="outline">{{ instance.clusterName || "DEFAULT" }}</Badge>
|
||||
<Badge variant="outline" :class="instance.healthy === false ? 'border-destructive/50 text-destructive' : 'border-emerald-500/50 text-emerald-700 dark:text-emerald-300'">{{ instance.healthy === false ? t("nacos.unhealthy") : t("nacos.healthy") }}</Badge>
|
||||
<Badge :variant="instance.enabled === false ? 'outline' : 'secondary'" :class="instance.enabled === false ? 'border-muted-foreground/50 text-muted-foreground' : ''">{{ instance.enabled === false ? t("nacos.offline") : t("nacos.enabled") }}</Badge>
|
||||
<Badge v-if="instance.ephemeral != null" variant="outline">{{ instance.ephemeral ? t("nacos.ephemeral") : t("nacos.persistent") }}</Badge>
|
||||
</div>
|
||||
<div class="mt-3 grid gap-x-5 gap-y-3 text-xs sm:grid-cols-[auto_minmax(0,1fr)]">
|
||||
<div class="nacos-instance-detail-grid mt-3 grid gap-x-5 gap-y-3 text-xs">
|
||||
<div class="flex items-end gap-1 self-start">
|
||||
<label class="grid gap-1 text-muted-foreground">
|
||||
<span>{{ t("nacos.weight") }}</span>
|
||||
@@ -2974,7 +2974,7 @@ onBeforeUnmount(() => {
|
||||
<span v-else class="self-start text-muted-foreground">{{ t("nacos.noMetadata") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex shrink-0 flex-wrap items-center gap-2 xl:justify-end">
|
||||
<div class="nacos-instance-actions flex flex-wrap items-center gap-2">
|
||||
<Button size="sm" variant="outline" class="h-7" :disabled="readOnly || !supportsInstanceUpdate || isInstanceUpdating(instance)" @click="openInstanceEditor(instance)">{{ t("nacos.edit") }}</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -3323,6 +3323,39 @@ onBeforeUnmount(() => {
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
.nacos-service-workbench {
|
||||
container: nacos-service-workbench / inline-size;
|
||||
}
|
||||
|
||||
.nacos-service-cluster-input {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.nacos-service-management-actions {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.nacos-service-stat-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.nacos-service-detail-grid,
|
||||
.nacos-instance-detail-grid {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.nacos-instance-layout {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nacos-instance-address {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.nacos-instance-actions {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nacos-config-context-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -3390,6 +3423,54 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
|
||||
@container nacos-service-workbench (max-width: 480px) {
|
||||
.nacos-service-filter-group,
|
||||
.nacos-service-management-actions {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.nacos-service-cluster-input {
|
||||
width: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.nacos-service-management-actions {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@container nacos-service-workbench (min-width: 620px) {
|
||||
.nacos-service-stat-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.nacos-service-detail-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.nacos-instance-detail-grid {
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@container nacos-service-workbench (min-width: 720px) {
|
||||
.nacos-instance-layout {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nacos-instance-main {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.nacos-instance-actions {
|
||||
flex: 0 1 auto;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.nacos-admin-splitpanes :deep(.splitpanes--vertical > .splitpanes__splitter) {
|
||||
width: 4px !important;
|
||||
border-left: 1px solid var(--border);
|
||||
|
||||
+14
-2
@@ -93,12 +93,24 @@ describe("NacosAdminConsole config workbench layout", () => {
|
||||
|
||||
it("reserves the cluster-clear action space so entering a filter cannot reflow the toolbar", () => {
|
||||
expect(source).toContain('class="min-w-0 flex-1"');
|
||||
expect(source).toContain('class="flex shrink-0 items-center gap-1"');
|
||||
expect(source).toContain('class="nacos-service-filter-group flex min-w-0 items-center gap-1"');
|
||||
expect(source).toContain(':class="{ invisible: !serviceCluster }"');
|
||||
expect(source).toContain(':disabled="instancesLoading || !serviceCluster"');
|
||||
expect(source).not.toContain('v-if="serviceCluster"\n size="sm"');
|
||||
});
|
||||
|
||||
it("uses the service split pane width for responsive service and instance layouts", () => {
|
||||
expect(source).toContain(".nacos-service-workbench {\n container: nacos-service-workbench / inline-size;");
|
||||
expect(source).toContain("@container nacos-service-workbench (max-width: 480px)");
|
||||
expect(source).toContain("@container nacos-service-workbench (min-width: 620px)");
|
||||
expect(source).toContain("@container nacos-service-workbench (min-width: 720px)");
|
||||
expect(source).toContain('class="nacos-instance-layout flex gap-3"');
|
||||
expect(source).toContain('class="nacos-instance-actions flex flex-wrap items-center gap-2"');
|
||||
expect(source).toContain("overflow-wrap: anywhere;");
|
||||
expect(source).not.toContain("xl:flex-row xl:items-start xl:justify-between");
|
||||
expect(source).not.toContain("sm:grid-cols-[auto_minmax(0,1fr)]");
|
||||
});
|
||||
|
||||
it("adds icon-only clear controls to populated configuration and service filters", () => {
|
||||
for (const [filter, clear] of [
|
||||
["configDataId", "clearConfigFilter('dataId')"],
|
||||
@@ -205,7 +217,7 @@ describe("NacosAdminConsole config workbench layout", () => {
|
||||
|
||||
it("separates the service header, filtering controls, and management actions", () => {
|
||||
expect(source).toContain('<header class="shrink-0 border-b bg-background">');
|
||||
expect(source).toContain('class="flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-muted/30 px-4 py-2"');
|
||||
expect(source).toContain('class="nacos-service-toolbar flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-muted/30 px-4 py-2"');
|
||||
expect(source).toContain('t("nacos.serviceSettings")');
|
||||
expect(source).toContain('t("nacos.registerInstance")');
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user