Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web/src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 9 additions & 3 deletions web/src/components/registry/RegistryList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@
class="bg-wp-background-200! dark:bg-wp-background-200! items-center"
>
<span>{{ registry.address }}</span>
<Badge
v-if="registry.edit === false"
class="ml-2"
:value="registry.org_id === 0 ? $t('global_level_registry') : $t('org_level_registry')"
/>
<div class="ml-auto flex items-center gap-2">
<IconButton
:icon="registry.readonly ? 'chevron-right' : 'edit'"
:icon="registry.edit === false ? 'chevron-right' : 'edit'"
class="h-8 w-8"
:title="registry.readonly ? $t('registries.view') : $t('registries.edit')"
:title="registry.edit === false ? $t('registries.view') : $t('registries.edit')"
@click="editRegistry(registry)"
/>
<IconButton
v-if="!registry.readonly"
v-if="registry.edit !== false"
icon="trash"
class="hover:text-wp-error-100 h-8 w-8"
:is-loading="isDeleting"
Expand All @@ -35,6 +40,7 @@
import { toRef } from 'vue';
import { useI18n } from 'vue-i18n';

import Badge from '~/components/atomic/Badge.vue';
import Icon from '~/components/atomic/Icon.vue';
import IconButton from '~/components/atomic/IconButton.vue';
import ListItem from '~/components/atomic/ListItem.vue';
Expand Down
42 changes: 39 additions & 3 deletions web/src/views/org/settings/OrgRegistries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,47 @@ const org = requiredInject('org');
const selectedRegistry = ref<Partial<Registry>>();
const isEditing = computed(() => !!selectedRegistry.value?.id);

async function loadRegistries(page: number): Promise<Registry[] | null> {
return apiClient.getOrgRegistryList(org.value.id, { page });
async function loadRegistries(page: number, level: 'org' | 'global'): Promise<Registry[] | null> {
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<string, Registry & { edit?: boolean; level: 'org' | 'global' }> = {};

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) {
Expand Down
47 changes: 44 additions & 3 deletions web/src/views/repo/settings/Registries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,52 @@ const repo = requiredInject('repo');
const selectedRegistry = ref<Partial<Registry>>();
const isEditingRegistry = computed(() => !!selectedRegistry.value?.id);

async function loadRegistries(page: number): Promise<Registry[] | null> {
return apiClient.getRegistryList(repo.value.id, { page });
async function loadRegistries(page: number, level: 'repo' | 'org' | 'global'): Promise<Registry[] | null> {
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<string, Registry & { edit?: boolean; level: 'repo' | 'org' | 'global' }> = {};

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