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) {