Skip to content

Commit 0de3c17

Browse files
committed
Add UI indicators for credentials with missing tools
1 parent d71220c commit 0de3c17

File tree

1 file changed

+57
-15
lines changed

1 file changed

+57
-15
lines changed

client/src/components/User/Credentials/ServiceCredentialsGroupsList.vue

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* <ServiceCredentialsGroupsList :service-groups="groups" />
1919
*/
2020
21-
import { faKey, faPencilAlt, faTrash, faWrench } from "@fortawesome/free-solid-svg-icons";
21+
import { faExclamationTriangle, faKey, faPencilAlt, faTrash, faWrench } from "@fortawesome/free-solid-svg-icons";
2222
import { BModal } from "bootstrap-vue";
2323
import { faCheck } from "font-awesome-6";
2424
import { storeToRefs } from "pinia";
@@ -71,7 +71,7 @@ const props = defineProps<Props>();
7171
7272
const { confirm } = useConfirmDialog();
7373
74-
const { getToolNameById } = useToolStore();
74+
const { getToolForId, getToolNameById } = useToolStore();
7575
7676
const userToolsServiceCredentialsStore = useUserToolsServiceCredentialsStore();
7777
const { userToolsServicesCurrentGroupIds } = storeToRefs(userToolsServiceCredentialsStore);
@@ -111,6 +111,27 @@ const isGroupInUse = computed(() => (group: ServiceCredentialsGroupDetails) => {
111111
return false;
112112
});
113113
114+
/**
115+
* Checks if the source tool for a credential group is missing/deleted.
116+
* @param {ServiceCredentialsGroupDetails} group - The credential group to check.
117+
* @returns {boolean} True if the tool is no longer available.
118+
*/
119+
const isToolMissing = computed(() => (group: ServiceCredentialsGroupDetails) => {
120+
return !getToolForId(group.sourceId);
121+
});
122+
123+
/**
124+
* Gets the display name for a tool, with a fallback for missing/deleted tools.
125+
* @param {ServiceCredentialsGroupDetails} group - The credential group.
126+
* @returns {string} The tool name or a fallback indicator.
127+
*/
128+
const getToolDisplayName = computed(() => (group: ServiceCredentialsGroupDetails) => {
129+
if (isToolMissing.value(group)) {
130+
return `${group.sourceId} (deleted)`;
131+
}
132+
return getToolNameById(group.sourceId);
133+
});
134+
114135
/**
115136
* Deletes a credential group after user confirmation.
116137
* @param {ServiceCredentialsGroupDetails} groupToDelete - The group to delete.
@@ -120,7 +141,9 @@ const isGroupInUse = computed(() => (group: ServiceCredentialsGroupDetails) => {
120141
async function deleteGroup(groupToDelete: ServiceCredentialsGroupDetails): Promise<void> {
121142
let message = `Are you sure you want to delete the credentials group "${groupToDelete.name}"?`;
122143
123-
if (isGroupInUse.value(groupToDelete)) {
144+
if (isToolMissing.value(groupToDelete)) {
145+
message = message.concat(` The associated tool is no longer available.`);
146+
} else if (isGroupInUse.value(groupToDelete)) {
124147
message = message.concat(` This group is currently in use by '${getToolNameById(groupToDelete.sourceId)}'.`);
125148
}
126149
@@ -221,23 +244,40 @@ async function onSaveChanges(): Promise<void> {
221244
* @returns {CardBadge[]} Array of badge configurations.
222245
*/
223246
function getBadgesFor(group: ServiceCredentialsGroupDetails): CardBadge[] {
224-
const badges: CardBadge[] = [
225-
{
226-
id: `tool-${group.sourceId}`,
227-
icon: faWrench,
228-
title: "This tool is using this credentials group. Click to view.",
229-
label: getToolNameById(group.sourceId),
230-
to: `/root?tool_id=${group.sourceId}&tool_version=${group.sourceVersion}`,
231-
},
232-
{
247+
const toolMissing = isToolMissing.value(group);
248+
const badges: CardBadge[] = [];
249+
250+
if (toolMissing) {
251+
badges.push({
252+
id: `tool-missing-${group.id}`,
253+
icon: faExclamationTriangle,
254+
title: "The tool associated with these credentials is no longer available. You cannot edit or use this group.",
255+
label: "Tool Unavailable",
256+
variant: "warning",
257+
});
258+
}
259+
260+
badges.push({
261+
id: `tool-${group.sourceId}`,
262+
icon: faWrench,
263+
title: toolMissing
264+
? "This tool is no longer available."
265+
: "This tool is using this credentials group. Click to view.",
266+
label: getToolDisplayName.value(group),
267+
to: toolMissing ? undefined : `/root?tool_id=${group.sourceId}&tool_version=${group.sourceVersion}`,
268+
});
269+
270+
if (!toolMissing) {
271+
badges.push({
233272
id: `in-use-${group.id}`,
234273
icon: faCheck,
235274
title: "This group is currently in use.",
236275
label: "In Use",
237276
variant: "success",
238277
visible: isGroupInUse.value(group),
239-
},
240-
];
278+
});
279+
}
280+
241281
return badges;
242282
}
243283
@@ -247,6 +287,7 @@ function getBadgesFor(group: ServiceCredentialsGroupDetails): CardBadge[] {
247287
* @returns {CardAction[]} Array of action configurations
248288
*/
249289
function getPrimaryActions(group: ServiceCredentialsGroupDetails): CardAction[] {
290+
const toolMissing = isToolMissing.value(group);
250291
const primaryActions: CardAction[] = [
251292
{
252293
id: `delete-${group.id}`,
@@ -259,10 +300,11 @@ function getPrimaryActions(group: ServiceCredentialsGroupDetails): CardAction[]
259300
{
260301
id: `edit-${group.id}`,
261302
label: "Edit",
262-
title: "Edit this group",
303+
title: !toolMissing ? "Cannot edit - tool definition not available" : "Edit this group",
263304
icon: faPencilAlt,
264305
variant: "outline-info",
265306
handler: () => editGroup(group),
307+
disabled: toolMissing,
266308
},
267309
];
268310
return primaryActions;

0 commit comments

Comments
 (0)