fix(nacos): allow overriding target group when copying configs
This commit is contained in:
1 parent
d782667b22
commit
bdf5f6a87c
14 files changed
+163
-9
No files matched your search
@@ -1244,7 +1244,7 @@ async function exportConfigArchive(scope: NacosConfigSelectionScope) {
|
||||
|
||||
const batchTransferRequest = shallowRef<NacosConfigTransferRequest | null>(null);
|
||||
|
||||
async function previewBatch(payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; policy: NacosConflictPolicy }) {
|
||||
async function previewBatch(payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; targetGroup: string; policy: NacosConflictPolicy }) {
|
||||
batchLoading.value = true;
|
||||
batchError.value = "";
|
||||
batchPreview.value = null;
|
||||
@@ -1260,6 +1260,7 @@ async function previewBatch(payload: { scope: NacosConfigSelectionScope; targetC
|
||||
targetConnectionId: payload.targetConnectionId,
|
||||
source: buildConfigSelector(payload.scope),
|
||||
targetNamespace: payload.targetNamespace,
|
||||
targetGroup: payload.targetGroup || undefined,
|
||||
conflictPolicy: payload.policy,
|
||||
};
|
||||
batchTransferRequest.value = req;
|
||||
@@ -1272,7 +1273,7 @@ async function previewBatch(payload: { scope: NacosConfigSelectionScope; targetC
|
||||
}
|
||||
}
|
||||
|
||||
async function applyBatch(payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; policy: NacosConflictPolicy }) {
|
||||
async function applyBatch(payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; targetGroup: string; policy: NacosConflictPolicy }) {
|
||||
if (batchLoading.value || batchReport.value || !batchPreview.value) return;
|
||||
if (payload.policy === "OVERWRITE" && !window.confirm(t("nacos.overwriteConfirm"))) return;
|
||||
const targetConnectionId = batchMode.value === "import" ? props.connectionId : payload.targetConnectionId;
|
||||
|
||||
@@ -37,8 +37,8 @@ const emit = defineEmits<{
|
||||
chooseFile: [];
|
||||
reset: [];
|
||||
targetConnectionChange: [connectionId: string];
|
||||
preview: [payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; policy: NacosConflictPolicy }];
|
||||
apply: [payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; policy: NacosConflictPolicy }];
|
||||
preview: [payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; targetGroup: string; policy: NacosConflictPolicy }];
|
||||
apply: [payload: { scope: NacosConfigSelectionScope; targetConnectionId: string; targetNamespace: string; targetGroup: string; policy: NacosConflictPolicy }];
|
||||
export: [scope: NacosConfigSelectionScope];
|
||||
}>();
|
||||
|
||||
@@ -46,6 +46,7 @@ const { t } = useI18n();
|
||||
const scope = ref<NacosConfigSelectionScope>("selected");
|
||||
const policy = ref<NacosConflictPolicy>("ABORT");
|
||||
const targetNamespace = ref("");
|
||||
const targetGroup = ref("");
|
||||
|
||||
const titleKey = computed(() => `nacos.batch${props.mode[0].toUpperCase()}${props.mode.slice(1)}Title`);
|
||||
const descriptionKey = computed(() => `nacos.batch${props.mode[0].toUpperCase()}${props.mode.slice(1)}Description`);
|
||||
@@ -116,6 +117,7 @@ watch(
|
||||
if (!open) return;
|
||||
scope.value = props.selectedCount ? "selected" : "filtered";
|
||||
policy.value = "ABORT";
|
||||
targetGroup.value = "";
|
||||
resetTargetNamespace();
|
||||
},
|
||||
{ immediate: true },
|
||||
@@ -202,6 +204,10 @@ watch(targetNamespaces, () => {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<div class="text-sm font-medium">{{ t("nacos.targetGroup") }}</div>
|
||||
<input v-model="targetGroup" type="text" class="h-10 w-full rounded-md border border-input bg-background px-3 text-sm" :disabled="loading" :placeholder="t('nacos.targetGroupPlaceholder')" @change="emit('reset')" />
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground">{{ t("nacos.copyKeepsSource") }}</p>
|
||||
</div>
|
||||
|
||||
@@ -279,11 +285,11 @@ watch(targetNamespaces, () => {
|
||||
{{ t("nacos.exportZip") }}
|
||||
</Button>
|
||||
<template v-else>
|
||||
<Button v-if="!preview" :disabled="loading || !canContinue" @click="emit('preview', { scope, targetConnectionId, targetNamespace: selectedTargetNamespace, policy })">
|
||||
<Button v-if="!preview" :disabled="loading || !canContinue" @click="emit('preview', { scope, targetConnectionId, targetNamespace: selectedTargetNamespace, targetGroup: targetGroup.trim(), policy })">
|
||||
<Loader2 v-if="loading" class="mr-2 h-4 w-4 animate-spin" />
|
||||
{{ t("nacos.preview") }}
|
||||
</Button>
|
||||
<Button v-else :variant="policy === 'OVERWRITE' ? 'destructive' : 'default'" :disabled="loading || hasPreviewBlockingErrors" @click="emit('apply', { scope, targetConnectionId, targetNamespace: selectedTargetNamespace, policy })">
|
||||
<Button v-else :variant="policy === 'OVERWRITE' ? 'destructive' : 'default'" :disabled="loading || hasPreviewBlockingErrors" @click="emit('apply', { scope, targetConnectionId, targetNamespace: selectedTargetNamespace, targetGroup: targetGroup.trim(), policy })">
|
||||
<Loader2 v-if="loading" class="mr-2 h-4 w-4 animate-spin" />
|
||||
{{ t("nacos.apply") }}
|
||||
</Button>
|
||||
|
||||
@@ -73,6 +73,27 @@ describe("NacosConfigBatchDialog cross-connection sync", () => {
|
||||
scope: "selected",
|
||||
targetConnectionId: "remote",
|
||||
targetNamespace: "shared",
|
||||
targetGroup: "",
|
||||
policy: "ABORT",
|
||||
});
|
||||
});
|
||||
|
||||
it("includes a trimmed target group override in the preview payload when provided", async () => {
|
||||
const { onPreview } = await mountDialog("remote");
|
||||
const groupInput = document.body.querySelector("input[type=text]") as HTMLInputElement;
|
||||
groupInput.value = " TARGET_GROUP ";
|
||||
groupInput.dispatchEvent(new Event("input"));
|
||||
await nextTick();
|
||||
|
||||
Array.from(document.body.querySelectorAll("button"))
|
||||
.find((button) => button.textContent?.includes("Preview"))
|
||||
?.click();
|
||||
await nextTick();
|
||||
expect(onPreview).toHaveBeenCalledWith({
|
||||
scope: "selected",
|
||||
targetConnectionId: "remote",
|
||||
targetNamespace: "shared",
|
||||
targetGroup: "TARGET_GROUP",
|
||||
policy: "ABORT",
|
||||
});
|
||||
});
|
||||
@@ -100,6 +121,7 @@ describe("NacosConfigBatchDialog cross-connection sync", () => {
|
||||
scope: "selected",
|
||||
targetConnectionId: "remote",
|
||||
targetNamespace: "",
|
||||
targetGroup: "",
|
||||
policy: "ABORT",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7680,6 +7680,8 @@ export default {
|
||||
noTargetConnections: "No writable Nacos connections are available. Add one or remove the target connection's read-only setting.",
|
||||
targetNamespace: "Target namespace",
|
||||
chooseTargetNamespace: "Choose another namespace",
|
||||
targetGroup: "Target group (optional)",
|
||||
targetGroupPlaceholder: "Same as source group",
|
||||
copyKeepsSource: "Sync uses one-way copy semantics. Source namespace configs stay unchanged.",
|
||||
conflictPolicy: "Conflict policy",
|
||||
policyABORT: "Abort on conflict",
|
||||
|
||||
@@ -6363,6 +6363,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "No hay conexiones Nacos con escritura disponibles. Añada una o desactive el modo de solo lectura del destino.",
|
||||
targetNamespace: "Namespace de destino",
|
||||
chooseTargetNamespace: "Seleccione otro namespace",
|
||||
targetGroup: "Group de destino (opcional)",
|
||||
targetGroupPlaceholder: "Igual que el group de origen",
|
||||
copyKeepsSource: "La sincronización usa una copia unidireccional. Las configuraciones del namespace de origen no cambian.",
|
||||
conflictPolicy: "Política de conflictos",
|
||||
policyABORT: "Abortar al encontrar conflictos",
|
||||
|
||||
@@ -6363,6 +6363,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "Non sono disponibili connessioni Nacos scrivibili. Aggiungine una o disattiva la sola lettura sulla destinazione.",
|
||||
targetNamespace: "Namespace di destinazione",
|
||||
chooseTargetNamespace: "Scegli un altro namespace",
|
||||
targetGroup: "Group di destinazione (facoltativo)",
|
||||
targetGroupPlaceholder: "Uguale al group di origine",
|
||||
copyKeepsSource: "La sincronizzazione usa una copia unidirezionale. Le configurazioni del namespace di origine restano invariate.",
|
||||
conflictPolicy: "Strategia conflitti",
|
||||
policyABORT: "Interrompi in caso di conflitto",
|
||||
|
||||
@@ -6404,6 +6404,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "書き込み可能な Nacos 接続がありません。接続を追加するか、宛先接続の読み取り専用設定を解除してください。",
|
||||
targetNamespace: "宛先名前空間",
|
||||
chooseTargetNamespace: "別の名前空間を選択",
|
||||
targetGroup: "宛先グループ(任意)",
|
||||
targetGroupPlaceholder: "元のグループと同じ",
|
||||
copyKeepsSource: "同期は一方向コピーです。元の名前空間の設定は変更されません。",
|
||||
conflictPolicy: "競合ポリシー",
|
||||
policyABORT: "競合時に中止",
|
||||
|
||||
@@ -7133,6 +7133,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "쓰기 가능한 Nacos 연결이 없습니다. 연결을 추가하거나 대상 연결의 읽기 전용 설정을 제거하세요.",
|
||||
targetNamespace: "대상 네임스페이스",
|
||||
chooseTargetNamespace: "다른 네임스페이스 선택",
|
||||
targetGroup: "대상 그룹(선택 사항)",
|
||||
targetGroupPlaceholder: "원본 그룹과 동일",
|
||||
copyKeepsSource: "동기화는 단방향 복사 의미를 사용합니다. 소스 네임스페이스 구성은 변경되지 않습니다.",
|
||||
conflictPolicy: "충돌 정책",
|
||||
policyABORT: "충돌 시 중단",
|
||||
|
||||
@@ -6365,6 +6365,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "Não há conexões Nacos graváveis disponíveis. Adicione uma ou desative o modo somente leitura da conexão de destino.",
|
||||
targetNamespace: "Namespace de destino",
|
||||
chooseTargetNamespace: "Escolha outro namespace",
|
||||
targetGroup: "Group de destino (opcional)",
|
||||
targetGroupPlaceholder: "Igual ao group de origem",
|
||||
copyKeepsSource: "A sincronização usa cópia unidirecional. As configurações do namespace de origem permanecem inalteradas.",
|
||||
conflictPolicy: "Política de conflitos",
|
||||
policyABORT: "Abortar ao encontrar conflito",
|
||||
|
||||
@@ -7664,6 +7664,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "没有可写入的 Nacos 连接。请先新增连接或取消目标连接的只读设置。",
|
||||
targetNamespace: "目标命名空间",
|
||||
chooseTargetNamespace: "请选择其他命名空间",
|
||||
targetGroup: "目标 Group(可选)",
|
||||
targetGroupPlaceholder: "与源 Group 相同",
|
||||
copyKeepsSource: "同步采用单向复制语义,源命名空间中的配置保持不变。",
|
||||
conflictPolicy: "冲突策略",
|
||||
policyABORT: "遇冲突终止",
|
||||
|
||||
@@ -5690,6 +5690,8 @@ export default withEnglishFallback({
|
||||
noTargetConnections: "沒有可寫入的 Nacos 連線。請新增連線或取消目標連線的唯讀設定。",
|
||||
targetNamespace: "目標命名空間",
|
||||
chooseTargetNamespace: "請選擇其他命名空間",
|
||||
targetGroup: "目標 Group(選填)",
|
||||
targetGroupPlaceholder: "與來源 Group 相同",
|
||||
copyKeepsSource: "同步採用單向複製,來源命名空間中的設定保持不變。",
|
||||
conflictPolicy: "衝突策略",
|
||||
policyABORT: "遇到衝突時終止",
|
||||
|
||||
@@ -230,6 +230,7 @@ export interface NacosConfigTransferRequest {
|
||||
targetConnectionId: string;
|
||||
source: NacosConfigSelector;
|
||||
targetNamespace: string;
|
||||
targetGroup?: string;
|
||||
conflictPolicy: NacosConflictPolicy;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user