diff --git a/web/src/assets/locales/en.json b/web/src/assets/locales/en.json index 32378f7edc3..7a920c6425b 100644 --- a/web/src/assets/locales/en.json +++ b/web/src/assets/locales/en.json @@ -517,6 +517,8 @@ "update_woodpecker": "Please update your Woodpecker instance to {0}", "global_level_secret": "global secret", "org_level_secret": "organization secret", + "global_level_registry": "global registry", + "org_level_registry": "organization registry", "login_to_cli": "Login to CLI", "login_to_cli_description": "If you continue, you will be logged in to the CLI.", "abort": "Abort", diff --git a/web/src/components/registry/RegistryList.vue b/web/src/components/registry/RegistryList.vue index 986f9c4ca25..6be282f88ef 100644 --- a/web/src/components/registry/RegistryList.vue +++ b/web/src/components/registry/RegistryList.vue @@ -6,15 +6,20 @@ class="bg-wp-background-200! dark:bg-wp-background-200! items-center" > {{ registry.address }} +
>(); const isEditing = computed(() => !!selectedRegistry.value?.id); -async function loadRegistries(page: number): Promise { - return apiClient.getOrgRegistryList(org.value.id, { page }); +async function loadRegistries(page: number, level: 'org' | 'global'): Promise { + switch (level) { + case 'org': + return apiClient.getOrgRegistryList(org.value.id, { page }); + case 'global': + return apiClient.getGlobalRegistryList({ page }); + default: + throw new Error(`Unexpected level: ${level}`); + } } -const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value); +const { + resetPage, + data: _registries, + loading, +} = usePagination(loadRegistries, () => !selectedRegistry.value, { + each: ['org', 'global'], +}); +const registries = computed(() => { + const registriesList: Record = {}; + + for (const level of ['org', 'global']) { + for (const registry of _registries.value) { + if ( + ((level === 'org' && registry.org_id !== 0) || (level === 'global' && registry.org_id === 0)) && + !registriesList[registry.address] + ) { + registriesList[registry.address] = { ...registry, edit: registry.org_id !== 0, level }; + } + } + } + + const levelsOrder = { + global: 0, + org: 1, + }; + + return Object.values(registriesList) + .toSorted((a, b) => a.address.localeCompare(b.address)) + .toSorted((a, b) => levelsOrder[b.level] - levelsOrder[a.level]); +}); const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => { if (!selectedRegistry.value) { diff --git a/web/src/views/repo/settings/Registries.vue b/web/src/views/repo/settings/Registries.vue index 7955598a1c9..27013744745 100644 --- a/web/src/views/repo/settings/Registries.vue +++ b/web/src/views/repo/settings/Registries.vue @@ -60,11 +60,52 @@ const repo = requiredInject('repo'); const selectedRegistry = ref>(); const isEditingRegistry = computed(() => !!selectedRegistry.value?.id); -async function loadRegistries(page: number): Promise { - return apiClient.getRegistryList(repo.value.id, { page }); +async function loadRegistries(page: number, level: 'repo' | 'org' | 'global'): Promise { + switch (level) { + case 'repo': + return apiClient.getRegistryList(repo.value.id, { page }); + case 'org': + return apiClient.getOrgRegistryList(repo.value.org_id, { page }); + case 'global': + return apiClient.getGlobalRegistryList({ page }); + default: + throw new Error(`Unexpected level: ${level}`); + } } -const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value); +const { + resetPage, + data: _registries, + loading, +} = usePagination(loadRegistries, () => !selectedRegistry.value, { + each: ['repo', 'org', 'global'], +}); +const registries = computed(() => { + const registriesList: Record = {}; + + for (const level of ['repo', 'org', 'global']) { + for (const registry of _registries.value) { + if ( + ((level === 'repo' && registry.repo_id !== 0 && registry.org_id === 0) || + (level === 'org' && registry.repo_id === 0 && registry.org_id !== 0) || + (level === 'global' && registry.repo_id === 0 && registry.org_id === 0)) && + !registriesList[registry.address] + ) { + registriesList[registry.address] = { ...registry, edit: registry.repo_id !== 0, level }; + } + } + } + + const levelsOrder = { + global: 0, + org: 1, + repo: 2, + }; + + return Object.values(registriesList) + .toSorted((a, b) => a.address.localeCompare(b.address)) + .toSorted((a, b) => levelsOrder[b.level] - levelsOrder[a.level]); +}); const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => { if (!selectedRegistry.value) {