Fix loading icons and add missing loading indicators (#5329)

This commit is contained in:
Anbraten 2025-07-15 07:53:22 +02:00 committed by GitHub
parent 6dafa15d4d
commit b1e54c5333
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 137 additions and 85 deletions

View File

@ -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;

View File

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

View File

@ -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>

View File

@ -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>

View File

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

View File

@ -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>

View File

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

View File

@ -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,

View File

@ -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')]));

View File

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

View File

@ -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();

View File

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

View File

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

View File

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

View File

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

View File

@ -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>

View File

@ -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>

View File

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

View File

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

View File

@ -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(() => {

View File

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

View File

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