diff --git a/web/src/components/agent/AgentManager.vue b/web/src/components/agent/AgentManager.vue index a6b77f138..3b51a9722 100644 --- a/web/src/components/agent/AgentManager.vue +++ b/web/src/components/agent/AgentManager.vue @@ -40,6 +40,7 @@ import { useAsyncAction } from '~/compositions/useAsyncAction'; import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import type { Agent } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; import AgentForm from './AgentForm.vue'; import AgentList from './AgentList.vue'; @@ -91,7 +92,7 @@ const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (_ }); function editAgent(agent: Agent) { - selectedAgent.value = structuredClone(agent); + selectedAgent.value = deepClone(agent); } function showAddAgent() { diff --git a/web/src/lib/utils/index.ts b/web/src/lib/utils/index.ts index cc4c4f4ad..5340d52a2 100644 --- a/web/src/lib/utils/index.ts +++ b/web/src/lib/utils/index.ts @@ -1,3 +1,5 @@ +import { toRaw } from 'vue'; + export function debounce(fn: (...args: T) => void, delay: number): (...args: T) => void { let timer: ReturnType; return (...args: T) => { @@ -5,3 +7,7 @@ export function debounce(fn: (...args: T) => void, delay: n timer = setTimeout(fn, delay, ...args); }; } + +export function deepClone(value: T): T { + return JSON.parse(JSON.stringify(toRaw(value))) as T; +} diff --git a/web/src/views/admin/AdminRegistries.vue b/web/src/views/admin/AdminRegistries.vue index 5a682c967..468d60c15 100644 --- a/web/src/views/admin/AdminRegistries.vue +++ b/web/src/views/admin/AdminRegistries.vue @@ -52,6 +52,7 @@ import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { Registry } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptyRegistry: Partial = { address: '', @@ -97,11 +98,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async }); function editRegistry(registry: Registry) { - selectedRegistry.value = structuredClone(registry); + selectedRegistry.value = deepClone(registry); } function showAddRegistry() { - selectedRegistry.value = structuredClone(emptyRegistry); + selectedRegistry.value = deepClone(emptyRegistry); } useWPTitle(computed(() => [i18n.t('registries.registries'), i18n.t('admin.settings.settings')])); diff --git a/web/src/views/admin/AdminSecrets.vue b/web/src/views/admin/AdminSecrets.vue index dc933e63e..b6ad8e521 100644 --- a/web/src/views/admin/AdminSecrets.vue +++ b/web/src/views/admin/AdminSecrets.vue @@ -48,6 +48,7 @@ import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { Secret } from '~/lib/api/types'; import { WebhookEvents } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptySecret: Partial = { name: '', @@ -94,11 +95,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async ( }); function editSecret(secret: Secret) { - selectedSecret.value = structuredClone(secret); + selectedSecret.value = deepClone(secret); } function showAddSecret() { - selectedSecret.value = structuredClone(emptySecret); + selectedSecret.value = deepClone(emptySecret); } useWPTitle(computed(() => [i18n.t('secrets.secrets'), i18n.t('admin.settings.settings')])); diff --git a/web/src/views/admin/AdminUsers.vue b/web/src/views/admin/AdminUsers.vue index 57cb1308f..a8f6bcd01 100644 --- a/web/src/views/admin/AdminUsers.vue +++ b/web/src/views/admin/AdminUsers.vue @@ -104,6 +104,7 @@ import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { User } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const apiClient = useApiClient(); const notifications = useNotifications(); @@ -152,7 +153,7 @@ const { doSubmit: deleteUser, isLoading: isDeleting } = useAsyncAction(async (_u }); function editUser(user: User) { - selectedUser.value = structuredClone(user); + selectedUser.value = deepClone(user); } function showAddUser() { diff --git a/web/src/views/org/settings/OrgRegistries.vue b/web/src/views/org/settings/OrgRegistries.vue index 17ce92bc7..66428025e 100644 --- a/web/src/views/org/settings/OrgRegistries.vue +++ b/web/src/views/org/settings/OrgRegistries.vue @@ -48,6 +48,7 @@ import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { Registry } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptyRegistry: Partial = { address: '', @@ -130,11 +131,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async }); function editRegistry(registry: Registry) { - selectedRegistry.value = structuredClone(registry); + selectedRegistry.value = deepClone(registry); } function showAddRegistry() { - selectedRegistry.value = structuredClone(emptyRegistry); + selectedRegistry.value = deepClone(emptyRegistry); } useWPTitle(computed(() => [i18n.t('registries.registries'), org.value.name])); diff --git a/web/src/views/org/settings/OrgSecrets.vue b/web/src/views/org/settings/OrgSecrets.vue index e4c21e9b0..6eb8cb0fb 100644 --- a/web/src/views/org/settings/OrgSecrets.vue +++ b/web/src/views/org/settings/OrgSecrets.vue @@ -40,6 +40,7 @@ import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import { WebhookEvents } from '~/lib/api/types'; import type { Secret } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptySecret: Partial = { name: '', @@ -87,11 +88,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async ( }); function editSecret(secret: Secret) { - selectedSecret.value = structuredClone(secret); + selectedSecret.value = deepClone(secret); } function showAddSecret() { - selectedSecret.value = structuredClone(emptySecret); + selectedSecret.value = deepClone(emptySecret); } useWPTitle(computed(() => [i18n.t('secrets.secrets'), org.value.name])); diff --git a/web/src/views/repo/settings/Registries.vue b/web/src/views/repo/settings/Registries.vue index 51618b2fd..71944b8ae 100644 --- a/web/src/views/repo/settings/Registries.vue +++ b/web/src/views/repo/settings/Registries.vue @@ -44,6 +44,7 @@ import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { Registry } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptyRegistry: Partial = { address: '', @@ -132,11 +133,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async }); function editRegistry(registry: Registry) { - selectedRegistry.value = structuredClone(registry); + selectedRegistry.value = deepClone(registry); } function showAddRegistry() { - selectedRegistry.value = structuredClone(emptyRegistry); + selectedRegistry.value = deepClone(emptyRegistry); } useWPTitle(computed(() => [i18n.t('registries.registries'), repo.value.full_name])); diff --git a/web/src/views/repo/settings/Secrets.vue b/web/src/views/repo/settings/Secrets.vue index a73936bb8..d0466949e 100644 --- a/web/src/views/repo/settings/Secrets.vue +++ b/web/src/views/repo/settings/Secrets.vue @@ -40,6 +40,7 @@ import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import { WebhookEvents } from '~/lib/api/types'; import type { Secret } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptySecret: Partial = { name: '', @@ -128,11 +129,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async ( }); function editSecret(secret: Secret) { - selectedSecret.value = structuredClone(secret); + selectedSecret.value = deepClone(secret); } function showAddSecret() { - selectedSecret.value = structuredClone(emptySecret); + selectedSecret.value = deepClone(emptySecret); } useWPTitle(computed(() => [i18n.t('secrets.secrets'), repo.value.full_name])); diff --git a/web/src/views/user/UserRegistries.vue b/web/src/views/user/UserRegistries.vue index df91b4ee6..fdcebbf5e 100644 --- a/web/src/views/user/UserRegistries.vue +++ b/web/src/views/user/UserRegistries.vue @@ -48,6 +48,7 @@ import useNotifications from '~/compositions/useNotifications'; import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import type { Registry } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptyRegistry: Partial = { address: '', @@ -101,11 +102,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async }); function editRegistry(registry: Registry) { - selectedRegistry.value = structuredClone(registry); + selectedRegistry.value = deepClone(registry); } function showAddRegistry() { - selectedRegistry.value = structuredClone(emptyRegistry); + selectedRegistry.value = deepClone(emptyRegistry); } useWPTitle(computed(() => [i18n.t('registries.registries'), i18n.t('user.settings.settings')])); diff --git a/web/src/views/user/UserSecrets.vue b/web/src/views/user/UserSecrets.vue index 5b2c36ac2..1778c2efa 100644 --- a/web/src/views/user/UserSecrets.vue +++ b/web/src/views/user/UserSecrets.vue @@ -44,6 +44,7 @@ import { usePagination } from '~/compositions/usePaginate'; import { useWPTitle } from '~/compositions/useWPTitle'; import { WebhookEvents } from '~/lib/api/types'; import type { Secret } from '~/lib/api/types'; +import { deepClone } from '~/lib/utils'; const emptySecret: Partial = { name: '', @@ -98,11 +99,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async ( }); function editSecret(secret: Secret) { - selectedSecret.value = structuredClone(secret); + selectedSecret.value = deepClone(secret); } function showAddSecret() { - selectedSecret.value = structuredClone(emptySecret); + selectedSecret.value = deepClone(emptySecret); } useWPTitle(computed(() => [i18n.t('secrets.secrets'), i18n.t('user.settings.settings')]));