This commit is contained in:
Anbraten
2025-12-04 00:13:24 +01:00
parent f761d166d4
commit a0d5506525
16 changed files with 102 additions and 246 deletions

View File

@@ -285,9 +285,6 @@
},
"registries": {
"desc": "Organization registry credentials can be added to use private images for all pipelines of an organization."
},
"agents": {
"desc": "Agents registered for this organization."
}
}
},
@@ -303,56 +300,6 @@
"desc": "Global registry credentials can be added to use private images for all pipelines.",
"warning": "These registry credentials are available to all users."
},
"agents": {
"agents": "Agents",
"desc": "Agents registered on this server.",
"none": "There are no agents yet.",
"id": "ID",
"add": "Add agent",
"save": "Save agent",
"show": "Show agents",
"created": "Agent created",
"saved": "Agent saved",
"deleted": "Agent deleted",
"name": {
"name": "Name",
"placeholder": "Name of the agent"
},
"no_schedule": {
"name": "Disable agent",
"placeholder": "Stop agent from taking new tasks"
},
"token": "Token",
"platform": {
"platform": "Platform",
"badge": "platform"
},
"backend": {
"backend": "Backend",
"badge": "backend"
},
"capacity": {
"capacity": "Capacity",
"desc": "The maximum amount of parallel pipelines executed by this agent.",
"badge": "capacity"
},
"custom_labels": {
"custom_labels": "Custom Labels",
"desc": "The custom labels set by the agent admin on agent startup."
},
"org": {
"badge": "org"
},
"version": "Version",
"last_contact": {
"last_contact": "Last contact",
"badge": "last contact"
},
"never": "Never",
"delete_confirm": "Do you really want to delete this agent? It will no longer be able to connect to the server.",
"edit_agent": "Edit agent",
"delete_agent": "Delete agent"
},
"queue": {
"queue": "Queue",
"desc": "Tasks waiting to be executed by agents.",
@@ -448,9 +395,6 @@
"download_cli": "Download CLI",
"reset_token": "Reset token",
"swagger_ui": "Swagger UI"
},
"agents": {
"desc": "Agents registered to your account repos."
}
}
},
@@ -589,5 +533,34 @@
"help_translating": "You can help translate Woodpecker into your language on {0}.",
"weblate": "our Weblate",
"disabled": "Disabled",
"create": "Create"
"create": "Create",
"agents_org_desc": "Agents registered for this organization.",
"agents": "Agents",
"agents_server_desc": "Agents registered on this server.",
"no_agents": "There are no agents yet.",
"id": "ID",
"add_agent": "Add agent",
"save_agent": "Save agent",
"show_agents": "Show agents",
"agent_created": "Agent created",
"agent_saved": "Agent saved",
"agent_deleted": "Agent deleted",
"name": "Name",
"agent_name_placeholder": "Name of the agent",
"agent_no_schedule": "Disable agent",
"agent_no_schedule_placeholder": "Stop agent from taking new tasks",
"token": "Token",
"platform": "Platform",
"backend": "Backend",
"capacity": "Capacity",
"capacity_desc": "The maximum amount of parallel pipelines executed by this agent.",
"custom_labels": "Custom Labels",
"custom_labels_desc": "The custom labels set by the agent admin on agent startup.",
"version": "Version",
"last_contact": "Last contact",
"never": "Never",
"agent_delete_confirm": "Do you really want to delete this agent? It will no longer be able to connect to the server.",
"edit_agent": "Edit agent",
"delete_agent": "Delete agent",
"agents_user_desc": "Agents registered to your account repos."
}

View File

@@ -1,62 +1,60 @@
<template>
<form @submit.prevent="$emit('save')">
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.name.name')">
<TextField :id="id" v-model="agent.name" :placeholder="$t('admin.settings.agents.name.placeholder')" required />
<InputField v-slot="{ id }" :label="$t('name')">
<TextField :id="id" v-model="agent.name" :placeholder="$t('agent_name_placeholder')" required />
</InputField>
<InputField :label="$t('admin.settings.agents.no_schedule.name')">
<InputField :label="$t('agent_no_schedule')">
<Checkbox
:model-value="agent.no_schedule || false"
:label="$t('admin.settings.agents.no_schedule.placeholder')"
:label="$t('agent_no_schedule_placeholder')"
@update:model-value="updateAgent({ no_schedule: $event })"
/>
</InputField>
<template v-if="isEditing">
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.token')">
<TextField :id="id" v-model="agent.token" :placeholder="$t('admin.settings.agents.token')" disabled />
<InputField v-slot="{ id }" :label="$t('token')">
<TextField :id="id" v-model="agent.token" :placeholder="$t('token')" disabled />
</InputField>
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.id')">
<InputField v-slot="{ id }" :label="$t('id')">
<TextField :id="id" :model-value="agent.id?.toString()" disabled />
</InputField>
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.backend.backend')" :docs-url="backendDocsUrl">
<InputField v-slot="{ id }" :label="$t('backend')" :docs-url="backendDocsUrl">
<TextField :id="id" v-model="agent.backend" disabled />
</InputField>
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.platform.platform')">
<InputField v-slot="{ id }" :label="$t('platform')">
<TextField :id="id" v-model="agent.platform" disabled />
</InputField>
<InputField
v-if="agent.custom_labels && Object.keys(agent.custom_labels).length > 0"
v-slot="{ id }"
:label="$t('admin.settings.agents.custom_labels.custom_labels')"
:label="$t('custom_labels')"
>
<span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.custom_labels.desc') }}</span>
<span class="text-wp-text-alt-100">{{ $t('custom_labels_desc') }}</span>
<TextField :id="id" :model-value="formatCustomLabels(agent.custom_labels)" disabled />
</InputField>
<InputField
v-slot="{ id }"
:label="$t('admin.settings.agents.capacity.capacity')"
:label="$t('capacity')"
docs-url="docs/administration/configuration/agent#max_workflows"
>
<span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.capacity.desc') }}</span>
<span class="text-wp-text-alt-100">{{ $t('capacity_desc') }}</span>
<TextField :id="id" :model-value="agent.capacity?.toString()" disabled />
</InputField>
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.version')">
<InputField v-slot="{ id }" :label="$t('version')">
<TextField :id="id" :model-value="agent.version" disabled />
</InputField>
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.last_contact.last_contact')">
<InputField v-slot="{ id }" :label="$t('last_contact')">
<TextField
:id="id"
:model-value="
agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('admin.settings.agents.never')
"
:model-value="agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('never')"
disabled
/>
</InputField>
@@ -68,7 +66,7 @@
:is-loading="isSaving"
type="submit"
color="green"
:text="isEditing ? $t('admin.settings.agents.save') : $t('admin.settings.agents.add')"
:text="isEditing ? $t('save_agent') : $t('add_agent')"
/>
</div>
</form>

View File

@@ -8,29 +8,20 @@
<span>{{ agent.name || `Agent ${agent.id}` }}</span>
<span class="ml-auto flex gap-2">
<Badge v-if="agent.no_schedule" :value="$t('disabled')" />
<Badge v-if="isAdmin === true && agent.org_id !== -1" :label="$t('org').toLowerCase()" :value="agent.org_id" />
<Badge v-if="agent.platform" :label="$t('platform')" :value="agent.platform" />
<Badge v-if="agent.backend" :label="$t('backend')" :value="agent.backend" />
<Badge v-if="agent.capacity" :label="$t('capacity')" :value="agent.capacity" />
<Badge
v-if="isAdmin === true && agent.org_id !== -1"
:label="$t('admin.settings.agents.org.badge')"
:value="agent.org_id"
/>
<Badge v-if="agent.platform" :label="$t('admin.settings.agents.platform.badge')" :value="agent.platform" />
<Badge v-if="agent.backend" :label="$t('admin.settings.agents.backend.badge')" :value="agent.backend" />
<Badge v-if="agent.capacity" :label="$t('admin.settings.agents.capacity.badge')" :value="agent.capacity" />
<Badge
:label="$t('admin.settings.agents.last_contact.badge')"
:value="agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('admin.settings.agents.never')"
:label="$t('last_contact')"
:value="agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('never')"
/>
</span>
<div class="ml-2 flex items-center gap-2">
<IconButton
icon="edit"
:title="$t('admin.settings.agents.edit_agent')"
class="h-8 w-8"
@click="$emit('edit', agent)"
/>
<IconButton icon="edit" :title="$t('edit_agent')" class="h-8 w-8" @click="$emit('edit', agent)" />
<IconButton
icon="trash"
:title="$t('admin.settings.agents.delete_agent')"
:title="$t('delete_agent')"
class="hover:text-wp-error-100 h-8 w-8"
:is-loading="isDeleting"
@click="$emit('delete', agent)"
@@ -41,7 +32,7 @@
<div v-if="loading" class="flex justify-center">
<Icon name="spinner" class="animate-spin" />
</div>
<div v-else-if="agents?.length === 0" class="ml-2">{{ $t('admin.settings.agents.none') }}</div>
<div v-else-if="agents?.length === 0" class="ml-2">{{ $t('no_agents') }}</div>
</div>
</template>

View File

@@ -1,101 +0,0 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description>
<template #headerActions>
<Button
v-if="selectedAgent"
:text="$t('admin.settings.agents.show')"
start-icon="back"
@click="selectedAgent = undefined"
/>
<Button v-else :text="$t('admin.settings.agents.add')" start-icon="plus" @click="showAddAgent" />
</template>
<AgentList
v-if="!selectedAgent"
:loading="loading"
:agents="agents"
:is-deleting="isDeleting"
:is-admin="isAdmin"
@edit="editAgent"
@delete="deleteAgent"
/>
<AgentForm
v-else
v-model="selectedAgent"
:isEditing="isEditingAgent"
:is-saving="isSaving"
@save="saveAgent"
@cancel="selectedAgent = undefined"
/>
</Settings>
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import Button from '~/components/atomic/Button.vue';
import Settings from '~/components/layout/Settings.vue';
import { useAsyncAction } from '~/compositions/useAsyncAction';
import useNotifications from '~/compositions/useNotifications';
import { usePagination } from '~/compositions/usePaginate';
import type { Agent } from '~/lib/api/types';
import AgentForm from './AgentForm.vue';
import AgentList from './AgentList.vue';
const props = defineProps<{
description: string;
loadAgents: (page: number) => Promise<Agent[] | null>;
createAgent: (agent: Partial<Agent>) => Promise<Agent>;
updateAgent: (agent: Agent) => Promise<Agent | void>;
deleteAgent: (agent: Agent) => Promise<unknown>;
isAdmin?: boolean;
}>();
const notifications = useNotifications();
const { t } = useI18n();
const selectedAgent = ref<Partial<Agent>>();
const isEditingAgent = computed(() => !!selectedAgent.value?.id);
const { resetPage, data: agents, loading } = usePagination(props.loadAgents);
const { doSubmit: saveAgent, isLoading: isSaving } = useAsyncAction(async () => {
if (!selectedAgent.value) {
throw new Error("Unexpected: Can't get agent");
}
if (isEditingAgent.value) {
await props.updateAgent(selectedAgent.value as Agent);
selectedAgent.value = undefined;
} else {
selectedAgent.value = await props.createAgent(selectedAgent.value);
}
notifications.notify({
title: isEditingAgent.value ? t('admin.settings.agents.saved') : t('admin.settings.agents.created'),
type: 'success',
});
await resetPage();
});
const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (_agent: Agent) => {
// eslint-disable-next-line no-alert
if (!confirm(t('admin.settings.agents.delete_confirm'))) {
return;
}
await props.deleteAgent(_agent);
notifications.notify({ title: t('admin.settings.agents.deleted'), type: 'success' });
await resetPage();
});
function editAgent(agent: Agent) {
selectedAgent.value = cloneDeep(agent);
}
function showAddAgent() {
selectedAgent.value = { name: '' };
}
</script>

View File

@@ -9,7 +9,7 @@
<Tab icon="repo" :to="{ name: 'admin-settings-repos' }" :title="$t('admin.settings.repos.repos')" />
<Tab icon="user" :to="{ name: 'admin-settings-users' }" :title="$t('admin.settings.users.users')" />
<Tab icon="org" :to="{ name: 'admin-settings-orgs' }" :title="$t('admin.settings.orgs.orgs')" />
<Tab icon="agent" :to="{ name: 'admin-settings-agents' }" :title="$t('admin.settings.agents.agents')" />
<Tab icon="agent" :to="{ name: 'admin-settings-agents' }" :title="$t('agents')" />
<Tab icon="tray-full" :to="{ name: 'admin-settings-queue' }" :title="$t('admin.settings.queue.queue')" />
<Tab icon="forge" :to="{ name: 'admin-settings-forges' }" :title="$t('forges')" />

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_server_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'admin-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'admin-settings-agents' }" />
</template>
<AgentForm
@@ -60,12 +60,12 @@ const { doSubmit: saveAgent, isLoading: isSaving } = useAsyncAction(async () =>
await apiClient.updateAgent(agent.value);
notifications.notify({
title: t('admin.settings.agents.saved'),
title: t('agent_saved'),
type: 'success',
});
await reloadAgent();
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), agent.value?.name ?? '']));
useWPTitle(computed(() => [t('agents'), t('settings'), agent.value?.name ?? '']));
</script>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_server_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'admin-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'admin-settings-agents' }" />
</template>
<AgentForm
@@ -45,12 +45,12 @@ const { doSubmit: createAgent, isLoading: isSaving } = useAsyncAction(async () =
const createdAgent = await apiClient.createAgent(agent.value);
notifications.notify({
title: t('admin.settings.agents.created'),
title: t('agent_created'),
type: 'success',
});
await router.replace({ name: 'admin-settings-agent', params: { agentId: createdAgent.id } });
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), t('create')]));
useWPTitle(computed(() => [t('agents'), t('settings'), t('create')]));
</script>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_server_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.add')" start-icon="plus" :to="{ name: 'admin-settings-agent-create' }" />
<Button :text="$t('add_agent')" start-icon="plus" :to="{ name: 'admin-settings-agent-create' }" />
</template>
<AgentList
@@ -38,16 +38,16 @@ const { resetPage, data: agents, loading } = usePagination((page: number) => api
const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (agent: Agent) => {
// eslint-disable-next-line no-alert
if (!confirm(t('admin.settings.agents.delete_confirm'))) {
if (!confirm(t('agent_delete_confirm'))) {
return;
}
await apiClient.deleteAgent(agent);
notifications.notify({ title: t('admin.settings.agents.deleted'), type: 'success' });
notifications.notify({ title: t('agent_deleted'), type: 'success' });
await resetPage();
});
useInterval(resetPage, 5 * 1000, { immediate: false });
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings')]));
useWPTitle(computed(() => [t('agents'), t('settings')]));
</script>

View File

@@ -17,7 +17,7 @@
v-if="useConfig().userRegisteredAgents"
icon="agent"
:to="{ name: 'org-settings-agents' }"
:title="$t('admin.settings.agents.agents')"
:title="$t('agents')"
/>
<router-view />

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_org_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'org-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'org-settings-agents' }" />
</template>
<AgentForm
@@ -63,12 +63,12 @@ const { doSubmit: saveAgent, isLoading: isSaving } = useAsyncAction(async () =>
await apiClient.updateOrgAgent(org.value.id, agent.value);
notifications.notify({
title: t('admin.settings.agents.saved'),
title: t('agent_saved'),
type: 'success',
});
await reloadAgent();
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), agent.value?.name ?? '']));
useWPTitle(computed(() => [t('agents'), t('settings'), agent.value?.name ?? '']));
</script>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_org_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'org-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'org-settings-agents' }" />
</template>
<AgentForm
@@ -48,12 +48,12 @@ const { doSubmit: createAgent, isLoading: isSaving } = useAsyncAction(async () =
const createdAgent = await apiClient.createOrgAgent(org.value.id, agent.value);
notifications.notify({
title: t('admin.settings.agents.created'),
title: t('agent_created'),
type: 'success',
});
await router.replace({ name: 'org-settings-agent', params: { agentId: createdAgent.id } });
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), t('create')]));
useWPTitle(computed(() => [t('agents'), t('settings'), t('create')]));
</script>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_org_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.add')" start-icon="plus" :to="{ name: 'org-settings-agent-create' }" />
<Button :text="$t('add_agent')" start-icon="plus" :to="{ name: 'org-settings-agent-create' }" />
</template>
<AgentList
@@ -45,16 +45,16 @@ const {
const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (agent: Agent) => {
// eslint-disable-next-line no-alert
if (!confirm(t('admin.settings.agents.delete_confirm'))) {
if (!confirm(t('agent_delete_confirm'))) {
return;
}
await apiClient.deleteOrgAgent(org.value.id, agent);
notifications.notify({ title: t('admin.settings.agents.deleted'), type: 'success' });
notifications.notify({ title: t('agent_deleted'), type: 'success' });
await resetPage();
});
useInterval(resetPage, 5 * 1000, { immediate: false });
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings')]));
useWPTitle(computed(() => [t('agents'), t('settings')]));
</script>

View File

@@ -7,12 +7,7 @@
<Tab icon="secret" :to="{ name: 'user-secrets' }" :title="$t('secrets.secrets')" />
<Tab icon="docker" :to="{ name: 'user-registries' }" :title="$t('registries.registries')" />
<Tab icon="console" :to="{ name: 'user-cli-and-api' }" :title="$t('user.settings.cli_and_api.cli_and_api')" />
<Tab
v-if="useConfig().userRegisteredAgents"
icon="agent"
:to="{ name: 'user-agents' }"
:title="$t('admin.settings.agents.agents')"
/>
<Tab v-if="useConfig().userRegisteredAgents" icon="agent" :to="{ name: 'user-agents' }" :title="$t('agents')" />
<router-view />
</Scaffold>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_user_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'user-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'user-agents' }" />
</template>
<AgentForm
@@ -10,7 +10,7 @@
is-editing
:is-saving="isSaving"
@save="saveAgent"
@cancel="$router.replace({ name: 'user-settings-agents' })"
@cancel="$router.replace({ name: 'user-agents' })"
/>
<div v-else class="flex justify-center">
<Icon name="spinner" class="animate-spin" />
@@ -66,12 +66,12 @@ const { doSubmit: saveAgent, isLoading: isSaving } = useAsyncAction(async () =>
await apiClient.updateOrgAgent(user.org_id, agent.value);
notifications.notify({
title: t('admin.settings.agents.saved'),
title: t('agent_saved'),
type: 'success',
});
await reloadAgent();
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), agent.value?.name ?? '']));
useWPTitle(computed(() => [t('agents'), t('settings'), agent.value?.name ?? '']));
</script>

View File

@@ -1,14 +1,14 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_user_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.show')" start-icon="back" :to="{ name: 'user-settings-agents' }" />
<Button :text="$t('show_agents')" start-icon="back" :to="{ name: 'user-agents' }" />
</template>
<AgentForm
v-model="agent"
:is-saving="isSaving"
@save="createAgent"
@cancel="$router.replace({ name: 'user-settings-agents' })"
@cancel="$router.replace({ name: 'user-agents' })"
/>
</Settings>
</template>
@@ -51,12 +51,12 @@ const { doSubmit: createAgent, isLoading: isSaving } = useAsyncAction(async () =
const createdAgent = await apiClient.createOrgAgent(user.org_id, agent.value);
notifications.notify({
title: t('admin.settings.agents.created'),
title: t('agent_created'),
type: 'success',
});
await router.push({ name: 'user-settings-agent', params: { agentId: createdAgent.id } });
await router.push({ name: 'user-agent', params: { agentId: createdAgent.id } });
});
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings'), t('create')]));
useWPTitle(computed(() => [t('agents'), t('settings'), t('create')]));
</script>

View File

@@ -1,7 +1,7 @@
<template>
<Settings :title="$t('admin.settings.agents.agents')" :description="$t('admin.settings.agents.desc')">
<Settings :title="$t('agents')" :description="$t('agents_user_desc')">
<template #headerActions>
<Button :text="$t('admin.settings.agents.add')" start-icon="plus" :to="{ name: 'user-settings-agent-create' }" />
<Button :text="$t('add_agent')" start-icon="plus" :to="{ name: 'user-agent-create' }" />
</template>
<AgentList
@@ -9,7 +9,7 @@
:agents="agents"
:is-deleting="isDeleting"
is-admin
@edit="$router.push({ name: 'org-settings-agent', params: { agentId: $event.id } })"
@edit="$router.push({ name: 'user-agent', params: { agentId: $event.id } })"
@delete="deleteAgent"
/>
</Settings>
@@ -48,16 +48,16 @@ const {
const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (agent: Agent) => {
// eslint-disable-next-line no-alert
if (!confirm(t('admin.settings.agents.delete_confirm'))) {
if (!confirm(t('agent_delete_confirm'))) {
return;
}
await apiClient.deleteOrgAgent(user.org_id, agent);
notifications.notify({ title: t('admin.settings.agents.deleted'), type: 'success' });
notifications.notify({ title: t('agent_deleted'), type: 'success' });
await resetPage();
});
useInterval(resetPage, 5 * 1000, { immediate: false });
useWPTitle(computed(() => [t('admin.settings.agents.agents'), t('admin.settings.settings')]));
useWPTitle(computed(() => [t('agents'), t('settings')]));
</script>