mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-08-21 14:53:44 +00:00
Fix loading icons and add missing loading indicators (#5329)
This commit is contained in:
parent
6dafa15d4d
commit
b1e54c5333
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div v-if="!props.loading" class="text-wp-text-100 space-y-4">
|
||||
<div class="text-wp-text-100 space-y-4">
|
||||
<ListItem
|
||||
v-for="agent in props.agents"
|
||||
v-for="agent in agents"
|
||||
:key="agent.id"
|
||||
class="bg-wp-background-200! dark:bg-wp-background-100! items-center"
|
||||
>
|
||||
@ -9,7 +9,7 @@
|
||||
<span class="ml-auto">
|
||||
<span class="hidden space-x-2 md:inline-block">
|
||||
<Badge
|
||||
v-if="props.isAdmin === true && agent.org_id !== -1"
|
||||
v-if="isAdmin === true && agent.org_id !== -1"
|
||||
:label="$t('admin.settings.agents.org.badge')"
|
||||
:value="agent.org_id"
|
||||
/>
|
||||
@ -31,15 +31,15 @@
|
||||
icon="trash"
|
||||
:title="$t('admin.settings.agents.delete_agent')"
|
||||
class="hover:text-wp-error-100 ml-2 h-8 w-8"
|
||||
:is-loading="props.isDeleting"
|
||||
:is-loading="isDeleting"
|
||||
@click="$emit('delete', agent)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="props.agents?.length === 0" class="ml-2">{{ $t('admin.settings.agents.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else class="flex justify-center">
|
||||
<Icon name="loading" class="animate-spin" />
|
||||
<div v-else-if="agents?.length === 0" class="ml-2">{{ $t('admin.settings.agents.none') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -51,7 +51,7 @@ import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import { useDate } from '~/compositions/useDate';
|
||||
import type { Agent } from '~/lib/api/types';
|
||||
|
||||
const props = defineProps<{
|
||||
defineProps<{
|
||||
agents: Agent[];
|
||||
isDeleting: boolean;
|
||||
loading: boolean;
|
||||
|
@ -77,7 +77,7 @@ const { doSubmit: saveAgent, isLoading: isSaving } = useAsyncAction(async () =>
|
||||
title: isEditingAgent.value ? t('admin.settings.agents.saved') : t('admin.settings.agents.created'),
|
||||
type: 'success',
|
||||
});
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (_agent: Agent) => {
|
||||
@ -88,7 +88,7 @@ const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (_
|
||||
|
||||
await props.deleteAgent(_agent);
|
||||
notifications.notify({ title: t('admin.settings.agents.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editAgent(agent: Agent) {
|
||||
|
@ -93,6 +93,8 @@
|
||||
</svg>
|
||||
|
||||
<div v-else-if="name === 'blank'" class="h-6 w-6" />
|
||||
|
||||
<div v-else>{{ throwNotFound() }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -192,7 +194,6 @@ export type IconNames =
|
||||
| 'forgejo'
|
||||
| 'question'
|
||||
| 'list'
|
||||
| 'loading'
|
||||
| 'plus'
|
||||
| 'blank'
|
||||
| 'heal'
|
||||
@ -228,7 +229,11 @@ export type IconNames =
|
||||
| 'cron'
|
||||
| 'toolbox';
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
name: IconNames;
|
||||
}>();
|
||||
|
||||
function throwNotFound() {
|
||||
throw new Error(`Icon "${props.name}" not found`);
|
||||
}
|
||||
</script>
|
||||
|
@ -22,7 +22,7 @@
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
</slot>
|
||||
<div v-if="isLoading" class="absolute top-0 right-0 bottom-0 left-0 flex items-center justify-center">
|
||||
<Icon name="loading" class="animate-spin" />
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
@ -22,7 +22,10 @@
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="registries?.length === 0" class="ml-2">{{ $t('registries.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="registries?.length === 0" class="ml-2">{{ $t('registries.none') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -30,6 +33,7 @@
|
||||
import { toRef } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import type { Registry } from '~/lib/api/types';
|
||||
@ -37,6 +41,7 @@ import type { Registry } from '~/lib/api/types';
|
||||
const props = defineProps<{
|
||||
modelValue: (Registry & { edit?: boolean })[];
|
||||
isDeleting: boolean;
|
||||
loading: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-if="pipelines" class="space-y-4">
|
||||
<div class="space-y-4">
|
||||
<PipelineItem
|
||||
v-for="pipeline in pipelines"
|
||||
:key="pipeline.id"
|
||||
@ -9,18 +9,23 @@
|
||||
}"
|
||||
:pipeline="pipeline"
|
||||
/>
|
||||
<Panel v-if="pipelines.length === 0">
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<Panel v-else-if="pipelines?.length === 0">
|
||||
<span class="text-wp-text-100">{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
</Panel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import Panel from '~/components/layout/Panel.vue';
|
||||
import PipelineItem from '~/components/repo/pipeline/PipelineItem.vue';
|
||||
import type { Pipeline } from '~/lib/api/types';
|
||||
|
||||
defineProps<{
|
||||
pipelines: Pipeline[] | undefined;
|
||||
loading?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
@ -31,7 +31,10 @@
|
||||
</template>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="secrets?.length === 0" class="ml-2">{{ $t('secrets.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="secrets?.length === 0" class="ml-2">{{ $t('secrets.none') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -40,6 +43,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';
|
||||
import type { Secret } from '~/lib/api/types';
|
||||
@ -47,6 +51,7 @@ import type { Secret } from '~/lib/api/types';
|
||||
const props = defineProps<{
|
||||
modelValue: (Secret & { edit?: boolean })[];
|
||||
isDeleting: boolean;
|
||||
loading: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -34,11 +34,12 @@ export const usePipelineStore = defineStore('pipelines', () => {
|
||||
const repoStore = useRepoStore();
|
||||
|
||||
const pipelines: Map<number, Map<number, Pipeline>> = reactive(new Map());
|
||||
const loading = ref(false);
|
||||
|
||||
function setPipeline(repoId: number, pipeline: Pipeline) {
|
||||
const repoPipelines = pipelines.get(repoId) || new Map<number, Pipeline>();
|
||||
repoPipelines.set(pipeline.number, {
|
||||
...(repoPipelines.get(pipeline.number) || {}),
|
||||
...repoPipelines.get(pipeline.number),
|
||||
...pipeline,
|
||||
});
|
||||
|
||||
@ -82,15 +83,19 @@ export const usePipelineStore = defineStore('pipelines', () => {
|
||||
}
|
||||
|
||||
async function loadRepoPipelines(repoId: number, page?: number) {
|
||||
loading.value = true;
|
||||
const _pipelines = await apiClient.getPipelineList(repoId, { page });
|
||||
_pipelines.forEach((pipeline) => {
|
||||
setPipeline(repoId, pipeline);
|
||||
});
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
async function loadPipeline(repoId: number, pipelinesNumber: number) {
|
||||
loading.value = true;
|
||||
const pipeline = await apiClient.getPipeline(repoId, pipelinesNumber);
|
||||
setPipeline(repoId, pipeline);
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
const pipelineFeed = computed(() =>
|
||||
@ -117,14 +122,17 @@ export const usePipelineStore = defineStore('pipelines', () => {
|
||||
async function loadPipelineFeed() {
|
||||
await repoStore.loadRepos();
|
||||
|
||||
loading.value = true;
|
||||
const _pipelines = await apiClient.getPipelineFeed();
|
||||
_pipelines.forEach((pipeline) => {
|
||||
setPipeline(pipeline.repo_id, pipeline);
|
||||
});
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
pipelines,
|
||||
loading,
|
||||
setPipeline,
|
||||
setWorkflow,
|
||||
getRepoPipelines,
|
||||
|
@ -28,7 +28,10 @@
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="orgs?.length === 0" class="ml-2">{{ $t('admin.settings.orgs.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="orgs?.length === 0" class="ml-2">{{ $t('admin.settings.orgs.none') }}</div>
|
||||
</div>
|
||||
</Settings>
|
||||
</template>
|
||||
@ -37,6 +40,7 @@
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import Settings from '~/components/layout/Settings.vue';
|
||||
@ -55,7 +59,7 @@ async function loadOrgs(page: number): Promise<Org[] | null> {
|
||||
return apiClient.getOrgs({ page });
|
||||
}
|
||||
|
||||
const { resetPage, data: orgs } = usePagination(loadOrgs);
|
||||
const { resetPage, data: orgs, loading } = usePagination(loadOrgs);
|
||||
|
||||
const { doSubmit: deleteOrg, isLoading: isDeleting } = useAsyncAction(async (_org: Org) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
@ -65,7 +69,7 @@ const { doSubmit: deleteOrg, isLoading: isDeleting } = useAsyncAction(async (_or
|
||||
|
||||
await apiClient.deleteOrg(_org);
|
||||
notifications.notify({ title: t('admin.settings.orgs.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
useWPTitle(computed(() => [t('admin.settings.orgs.orgs'), t('admin.settings.settings')]));
|
||||
|
@ -22,6 +22,7 @@
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
@ -70,7 +71,7 @@ async function loadRegistries(page: number): Promise<Registry[] | null> {
|
||||
return apiClient.getGlobalRegistryList({ page });
|
||||
}
|
||||
|
||||
const { resetPage, data: registries } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
|
||||
const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedRegistry.value) {
|
||||
@ -87,13 +88,13 @@ const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async (
|
||||
type: 'success',
|
||||
});
|
||||
selectedRegistry.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async (_registry: Registry) => {
|
||||
await apiClient.deleteGlobalRegistry(_registry.address);
|
||||
notifications.notify({ title: i18n.t('registries.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editRegistry(registry: Registry) {
|
||||
|
@ -37,7 +37,10 @@
|
||||
</div>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="repos?.length === 0" class="ml-2">{{ $t('admin.settings.repos.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="repos?.length === 0" class="ml-2">{{ $t('admin.settings.repos.none') }}</div>
|
||||
</div>
|
||||
</Settings>
|
||||
</template>
|
||||
@ -48,6 +51,7 @@ import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Badge from '~/components/atomic/Badge.vue';
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import Settings from '~/components/layout/Settings.vue';
|
||||
@ -66,7 +70,7 @@ async function loadRepos(page: number): Promise<Repo[] | null> {
|
||||
return apiClient.getAllRepos({ page });
|
||||
}
|
||||
|
||||
const { data: repos } = usePagination(loadRepos);
|
||||
const { data: repos, loading } = usePagination(loadRepos);
|
||||
|
||||
const { doSubmit: repairRepos, isLoading: isRepairingRepos } = useAsyncAction(async () => {
|
||||
await apiClient.repairAllRepos();
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
@ -67,7 +68,7 @@ async function loadSecrets(page: number): Promise<Secret[] | null> {
|
||||
return apiClient.getGlobalSecretList({ page });
|
||||
}
|
||||
|
||||
const { resetPage, data: secrets } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
const { resetPage, data: secrets, loading } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
|
||||
const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedSecret.value) {
|
||||
@ -84,13 +85,13 @@ const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async ()
|
||||
type: 'success',
|
||||
});
|
||||
selectedSecret.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (_secret: Secret) => {
|
||||
await apiClient.deleteGlobalSecret(_secret.name);
|
||||
notifications.notify({ title: i18n.t('secrets.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editSecret(secret: Secret) {
|
||||
|
@ -39,7 +39,10 @@
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="users?.length === 0" class="ml-2">{{ $t('admin.settings.users.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="users?.length === 0" class="ml-2">{{ $t('admin.settings.users.none') }}</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<form @submit.prevent="saveUser">
|
||||
@ -88,6 +91,7 @@ import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Badge from '~/components/atomic/Badge.vue';
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import Checkbox from '~/components/form/Checkbox.vue';
|
||||
@ -112,7 +116,7 @@ async function loadUsers(page: number): Promise<User[] | null> {
|
||||
return apiClient.getUsers({ page });
|
||||
}
|
||||
|
||||
const { resetPage, data: users } = usePagination(loadUsers, () => !selectedUser.value);
|
||||
const { resetPage, data: users, loading } = usePagination(loadUsers, () => !selectedUser.value);
|
||||
|
||||
const { doSubmit: saveUser, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedUser.value) {
|
||||
@ -133,7 +137,7 @@ const { doSubmit: saveUser, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
});
|
||||
}
|
||||
selectedUser.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteUser, isLoading: isDeleting } = useAsyncAction(async (_user: User) => {
|
||||
@ -144,7 +148,7 @@ const { doSubmit: deleteUser, isLoading: isDeleting } = useAsyncAction(async (_u
|
||||
|
||||
await apiClient.deleteUser(_user);
|
||||
notifications.notify({ title: t('admin.settings.users.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editUser(user: User) {
|
||||
|
@ -18,6 +18,7 @@
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
@ -67,7 +68,7 @@ async function loadRegistries(page: number): Promise<Registry[] | null> {
|
||||
return apiClient.getOrgRegistryList(org.value.id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: registries } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
|
||||
const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedRegistry.value) {
|
||||
@ -84,13 +85,13 @@ const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async (
|
||||
type: 'success',
|
||||
});
|
||||
selectedRegistry.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async (_registry: Registry) => {
|
||||
await apiClient.deleteOrgRegistry(org.value.id, _registry.address);
|
||||
notifications.notify({ title: i18n.t('registries.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editRegistry(registry: Registry) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
@ -60,7 +61,7 @@ async function loadSecrets(page: number): Promise<Secret[] | null> {
|
||||
return apiClient.getOrgSecretList(org.value.id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: secrets } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
const { resetPage, data: secrets, loading } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
|
||||
const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedSecret.value) {
|
||||
@ -77,13 +78,13 @@ const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async ()
|
||||
type: 'success',
|
||||
});
|
||||
selectedSecret.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (_secret: Secret) => {
|
||||
await apiClient.deleteOrgSecret(org.value.id, _secret.name);
|
||||
notifications.notify({ title: i18n.t('secrets.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editSecret(secret: Secret) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<template v-if="branches.length > 0">
|
||||
<ListItem
|
||||
v-for="branch in branchesWithDefaultBranchFirst"
|
||||
:key="branch"
|
||||
@ -10,11 +9,10 @@
|
||||
{{ branch }}
|
||||
<Badge v-if="branch === repo?.default_branch" :value="$t('default')" class="ml-auto" />
|
||||
</ListItem>
|
||||
</template>
|
||||
<div v-else-if="loading" class="text-wp-text-100 flex justify-center">
|
||||
<div v-if="loading" class="text-wp-text-100 flex justify-center">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
<Panel v-else class="flex justify-center">
|
||||
<Panel v-else-if="branches.length === 0" class="flex justify-center">
|
||||
{{ $t('empty_list', { entity: $t('repo.branches') }) }}
|
||||
</Panel>
|
||||
</div>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<template v-if="pullRequests.length > 0">
|
||||
<ListItem
|
||||
v-for="pullRequest in pullRequests"
|
||||
:key="pullRequest.index"
|
||||
@ -15,11 +14,10 @@
|
||||
pullRequest.title
|
||||
}}</span>
|
||||
</ListItem>
|
||||
</template>
|
||||
<div v-else-if="loading" class="text-wp-text-100 flex justify-center">
|
||||
<div v-if="loading" class="text-wp-text-100 flex justify-center">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
<Panel v-else class="flex justify-center">
|
||||
<Panel v-else-if="pullRequests.length === 0" class="flex justify-center">
|
||||
{{ $t('empty_list', { entity: $t('repo.pull_requests') }) }}
|
||||
</Panel>
|
||||
</div>
|
||||
|
@ -46,7 +46,10 @@
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<div v-if="crons?.length === 0" class="ml-2">{{ $t('repo.settings.crons.none') }}</div>
|
||||
<div v-if="loading" class="flex justify-center">
|
||||
<Icon name="spinner" class="animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="crons?.length === 0" class="ml-2">{{ $t('repo.settings.crons.none') }}</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
@ -109,6 +112,7 @@ import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import InputField from '~/components/form/InputField.vue';
|
||||
@ -137,7 +141,7 @@ async function loadCrons(page: number): Promise<Cron[] | null> {
|
||||
return apiClient.getCronList(repo.value.id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: crons } = usePagination(loadCrons, () => !selectedCron.value);
|
||||
const { resetPage, data: crons, loading } = usePagination(loadCrons, () => !selectedCron.value);
|
||||
|
||||
const { doSubmit: createCron, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedCron.value) {
|
||||
@ -154,13 +158,13 @@ const { doSubmit: createCron, isLoading: isSaving } = useAsyncAction(async () =>
|
||||
type: 'success',
|
||||
});
|
||||
selectedCron.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteCron, isLoading: isDeleting } = useAsyncAction(async (_cron: Cron) => {
|
||||
await apiClient.deleteCron(repo.value.id, _cron.id);
|
||||
notifications.notify({ title: i18n.t('repo.settings.crons.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: runCron } = useAsyncAction(async (_cron: Cron) => {
|
||||
|
@ -14,6 +14,7 @@
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
@ -63,7 +64,7 @@ async function loadRegistries(page: number): Promise<Registry[] | null> {
|
||||
return apiClient.getRegistryList(repo.value.id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: registries } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
|
||||
const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedRegistry.value) {
|
||||
@ -80,14 +81,14 @@ const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async (
|
||||
type: 'success',
|
||||
});
|
||||
selectedRegistry.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async (_registry: Registry) => {
|
||||
const registryAddress = encodeURIComponent(_registry.address);
|
||||
await apiClient.deleteRegistry(repo.value.id, registryAddress);
|
||||
notifications.notify({ title: i18n.t('registries.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editRegistry(registry: Registry) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
v-if="!selectedSecret"
|
||||
:model-value="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
@ -69,7 +70,11 @@ async function loadSecrets(page: number, level: 'repo' | 'org' | 'global'): Prom
|
||||
}
|
||||
}
|
||||
|
||||
const { resetPage, data: _secrets } = usePagination(loadSecrets, () => !selectedSecret.value, {
|
||||
const {
|
||||
resetPage,
|
||||
data: _secrets,
|
||||
loading,
|
||||
} = usePagination(loadSecrets, () => !selectedSecret.value, {
|
||||
each: ['repo', 'org', 'global'],
|
||||
});
|
||||
const secrets = computed(() => {
|
||||
|
@ -18,6 +18,7 @@
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
@ -74,7 +75,7 @@ async function loadRegistries(page: number): Promise<Registry[] | null> {
|
||||
return apiClient.getOrgRegistryList(user.org_id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: registries } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
const { resetPage, data: registries, loading } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
|
||||
const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedRegistry.value) {
|
||||
@ -91,13 +92,13 @@ const { doSubmit: createRegistry, isLoading: isSaving } = useAsyncAction(async (
|
||||
type: 'success',
|
||||
});
|
||||
selectedRegistry.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async (_registry: Registry) => {
|
||||
await apiClient.deleteOrgRegistry(user.org_id, _registry.address);
|
||||
notifications.notify({ title: i18n.t('registries.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editRegistry(registry: Registry) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
:loading="loading"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
@ -71,7 +72,7 @@ async function loadSecrets(page: number): Promise<Secret[] | null> {
|
||||
return apiClient.getOrgSecretList(user.org_id, { page });
|
||||
}
|
||||
|
||||
const { resetPage, data: secrets } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
const { resetPage, data: secrets, loading } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
|
||||
const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async () => {
|
||||
if (!selectedSecret.value) {
|
||||
@ -88,13 +89,13 @@ const { doSubmit: createSecret, isLoading: isSaving } = useAsyncAction(async ()
|
||||
type: 'success',
|
||||
});
|
||||
selectedSecret.value = undefined;
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (_secret: Secret) => {
|
||||
await apiClient.deleteOrgSecret(user.org_id, _secret.name);
|
||||
notifications.notify({ title: i18n.t('secrets.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
await resetPage();
|
||||
});
|
||||
|
||||
function editSecret(secret: Secret) {
|
||||
|
Loading…
Reference in New Issue
Block a user