@julianpedro/plugin-dev-ai-hub 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/DevAiHubClient.esm.js +5 -0
- package/dist/api/DevAiHubClient.esm.js.map +1 -1
- package/dist/components/AdminPage/AdminPage.esm.js +106 -0
- package/dist/components/AdminPage/AdminPage.esm.js.map +1 -0
- package/dist/components/AdminPage/index.esm.js +6 -0
- package/dist/components/AdminPage/index.esm.js.map +1 -0
- package/dist/components/AssetCard/AssetCard.esm.js +36 -17
- package/dist/components/AssetCard/AssetCard.esm.js.map +1 -1
- package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js +10 -13
- package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js.map +1 -1
- package/dist/components/AssetFilters/AssetFilters.esm.js +5 -3
- package/dist/components/AssetFilters/AssetFilters.esm.js.map +1 -1
- package/dist/components/AssetHelpDialog/AssetHelpDialog.esm.js +1 -1
- package/dist/components/AssetHelpDialog/AssetHelpDialog.esm.js.map +1 -1
- package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js +3 -3
- package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js.map +1 -1
- package/dist/components/AssetsTab/AssetsTab.esm.js +221 -0
- package/dist/components/AssetsTab/AssetsTab.esm.js.map +1 -0
- package/dist/components/AssetsTab/index.esm.js +6 -0
- package/dist/components/AssetsTab/index.esm.js.map +1 -0
- package/dist/components/DevAiHubPage/DevAiHubPage.esm.js +194 -111
- package/dist/components/DevAiHubPage/DevAiHubPage.esm.js.map +1 -1
- package/dist/components/McpConfigDialog/McpConfigDialog.esm.js +3 -581
- package/dist/components/McpConfigDialog/McpConfigDialog.esm.js.map +1 -1
- package/dist/components/McpPage/McpPage.esm.js +478 -0
- package/dist/components/McpPage/McpPage.esm.js.map +1 -0
- package/dist/components/McpPage/index.esm.js +6 -0
- package/dist/components/McpPage/index.esm.js.map +1 -0
- package/dist/components/ModelIcon/ModelBadge.esm.js +73 -0
- package/dist/components/ModelIcon/ModelBadge.esm.js.map +1 -0
- package/dist/components/ModelIcon/ModelIcon.esm.js +45 -0
- package/dist/components/ModelIcon/ModelIcon.esm.js.map +1 -0
- package/dist/components/ToolIcon/ToolIcon.esm.js +1 -1
- package/dist/components/ToolIcon/ToolIcon.esm.js.map +1 -1
- package/dist/context/UiConfigContext.esm.js +79 -0
- package/dist/context/UiConfigContext.esm.js.map +1 -0
- package/dist/hooks/index.esm.js +22 -1
- package/dist/hooks/index.esm.js.map +1 -1
- package/dist/index.d.ts +140 -20
- package/dist/index.esm.js +1 -1
- package/dist/locales/es.esm.js +18 -9
- package/dist/locales/es.esm.js.map +1 -1
- package/dist/locales/pt-BR.esm.js +18 -9
- package/dist/locales/pt-BR.esm.js.map +1 -1
- package/dist/plugin.esm.js +35 -6
- package/dist/plugin.esm.js.map +1 -1
- package/dist/translation.esm.js +27 -11
- package/dist/translation.esm.js.map +1 -1
- package/package.json +15 -5
|
@@ -8,6 +8,8 @@ class DevAiHubClient {
|
|
|
8
8
|
this.discoveryApi = discoveryApi;
|
|
9
9
|
this.fetchApi = fetchApi;
|
|
10
10
|
}
|
|
11
|
+
discoveryApi;
|
|
12
|
+
fetchApi;
|
|
11
13
|
async baseUrl() {
|
|
12
14
|
return this.discoveryApi.getBaseUrl("dev-ai-hub");
|
|
13
15
|
}
|
|
@@ -78,6 +80,9 @@ class DevAiHubClient {
|
|
|
78
80
|
async getMcpCatalog() {
|
|
79
81
|
return this.fetch("/mcp-catalog");
|
|
80
82
|
}
|
|
83
|
+
async getUiConfig() {
|
|
84
|
+
return this.fetch("/ui-config");
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
export { DevAiHubClient, devAiHubApiRef };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DevAiHubClient.esm.js","sources":["../../src/api/DevAiHubClient.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport type {\n AiAsset,\n AiAssetListResponse,\n AiHubProvider,\n AiHubStats,\n AssetListFilter,\n McpCatalogEntry,\n} from '@julianpedro/plugin-dev-ai-hub-common';\n\nexport const devAiHubApiRef = createApiRef<DevAiHubApi>({\n id: 'plugin.dev-ai-hub.service',\n});\n\nexport interface DevAiHubApi {\n listAssets(filter?: AssetListFilter): Promise<AiAssetListResponse>;\n getAsset(id: string): Promise<AiAsset>;\n getAssetRaw(id: string): Promise<string>;\n /** Returns the absolute URL for the download endpoint (zip for skills/bundles, md for others). */\n getDownloadUrl(id: string, tool?: string): Promise<string>;\n /** Returns the absolute URL for the .agent.md endpoint used in VSCode deep links. */\n getAgentMdUrl(id: string): Promise<string>;\n trackInstall(id: string): Promise<void>;\n listProviders(): Promise<AiHubProvider[]>;\n getProviderStatus(id: string): Promise<AiHubProvider>;\n triggerSync(id: string): Promise<void>;\n getStats(): Promise<AiHubStats>;\n getMcpCatalog(): Promise<McpCatalogEntry[]>;\n}\n\nexport class DevAiHubClient implements DevAiHubApi {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n ) {}\n\n private async baseUrl(): Promise<string> {\n return this.discoveryApi.getBaseUrl('dev-ai-hub');\n }\n\n private async fetch<T>(path: string, init?: RequestInit): Promise<T> {\n const base = await this.baseUrl();\n const response = await this.fetchApi.fetch(`${base}${path}`, init);\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Dev AI Hub API error ${response.status}: ${text}`,\n );\n }\n return response.json() as Promise<T>;\n }\n\n async listAssets(filter?: AssetListFilter): Promise<AiAssetListResponse> {\n const params = new URLSearchParams();\n if (filter?.type) params.set('type', filter.type);\n if (filter?.tool) params.set('tool', filter.tool);\n if (filter?.search) params.set('search', filter.search);\n if (filter?.providerId) params.set('provider', filter.providerId);\n if (filter?.tags?.length) params.set('tags', filter.tags.join(','));\n if (filter?.page) params.set('page', String(filter.page));\n if (filter?.pageSize) params.set('pageSize', String(filter.pageSize));\n\n const qs = params.toString();\n return this.fetch<AiAssetListResponse>(`/assets${qs ? `?${qs}` : ''}`);\n }\n\n async getAsset(id: string): Promise<AiAsset> {\n return this.fetch<AiAsset>(`/assets/${encodeURIComponent(id)}`);\n }\n\n async getAssetRaw(id: string): Promise<string> {\n const base = await this.baseUrl();\n const response = await this.fetchApi.fetch(\n `${base}/assets/${encodeURIComponent(id)}/raw`,\n );\n if (!response.ok) throw new Error(`Failed to fetch raw asset: ${response.status}`);\n return response.text();\n }\n\n async getDownloadUrl(id: string, tool?: string): Promise<string> {\n const base = await this.baseUrl();\n const url = `${base}/assets/${encodeURIComponent(id)}/download`;\n return tool ? `${url}?tool=${encodeURIComponent(tool)}` : url;\n }\n\n async getAgentMdUrl(id: string): Promise<string> {\n const base = await this.baseUrl();\n return `${base}/assets/${encodeURIComponent(id)}/agent-md`;\n }\n\n async trackInstall(id: string): Promise<void> {\n await this.fetch(`/assets/${encodeURIComponent(id)}/track-install`, {\n method: 'POST',\n });\n }\n\n async listProviders(): Promise<AiHubProvider[]> {\n return this.fetch<AiHubProvider[]>('/providers');\n }\n\n async getProviderStatus(id: string): Promise<AiHubProvider> {\n return this.fetch<AiHubProvider>(\n `/providers/${encodeURIComponent(id)}/status`,\n );\n }\n\n async triggerSync(id: string): Promise<void> {\n await this.fetch(`/providers/${encodeURIComponent(id)}/sync`, {\n method: 'POST',\n });\n }\n\n async getStats(): Promise<AiHubStats> {\n return this.fetch<AiHubStats>('/stats');\n }\n\n async getMcpCatalog(): Promise<McpCatalogEntry[]> {\n return this.fetch<McpCatalogEntry[]>('/mcp-catalog');\n }\n}\n"],"names":[],"mappings":";;AAcO,MAAM,iBAAiB,YAAA,CAA0B;AAAA,EACtD,EAAA,EAAI;AACN,CAAC;
|
|
1
|
+
{"version":3,"file":"DevAiHubClient.esm.js","sources":["../../src/api/DevAiHubClient.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport type {\n AiAsset,\n AiAssetListResponse,\n AiHubProvider,\n AiHubStats,\n AssetListFilter,\n McpCatalogEntry,\n} from '@julianpedro/plugin-dev-ai-hub-common';\n\nexport const devAiHubApiRef = createApiRef<DevAiHubApi>({\n id: 'plugin.dev-ai-hub.service',\n});\n\nexport interface UiConfig {\n typeColors: Partial<Record<string, string>>;\n statsCards: string[];\n}\n\nexport interface DevAiHubApi {\n listAssets(filter?: AssetListFilter): Promise<AiAssetListResponse>;\n getAsset(id: string): Promise<AiAsset>;\n getAssetRaw(id: string): Promise<string>;\n /** Returns the absolute URL for the download endpoint (zip for skills/bundles, md for others). */\n getDownloadUrl(id: string, tool?: string): Promise<string>;\n /** Returns the absolute URL for the .agent.md endpoint used in VSCode deep links. */\n getAgentMdUrl(id: string): Promise<string>;\n trackInstall(id: string): Promise<void>;\n listProviders(): Promise<AiHubProvider[]>;\n getProviderStatus(id: string): Promise<AiHubProvider>;\n triggerSync(id: string): Promise<void>;\n getStats(): Promise<AiHubStats>;\n getMcpCatalog(): Promise<McpCatalogEntry[]>;\n getUiConfig(): Promise<UiConfig>;\n}\n\nexport class DevAiHubClient implements DevAiHubApi {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n ) {}\n\n private async baseUrl(): Promise<string> {\n return this.discoveryApi.getBaseUrl('dev-ai-hub');\n }\n\n private async fetch<T>(path: string, init?: RequestInit): Promise<T> {\n const base = await this.baseUrl();\n const response = await this.fetchApi.fetch(`${base}${path}`, init);\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Dev AI Hub API error ${response.status}: ${text}`,\n );\n }\n return response.json() as Promise<T>;\n }\n\n async listAssets(filter?: AssetListFilter): Promise<AiAssetListResponse> {\n const params = new URLSearchParams();\n if (filter?.type) params.set('type', filter.type);\n if (filter?.tool) params.set('tool', filter.tool);\n if (filter?.search) params.set('search', filter.search);\n if (filter?.providerId) params.set('provider', filter.providerId);\n if (filter?.tags?.length) params.set('tags', filter.tags.join(','));\n if (filter?.page) params.set('page', String(filter.page));\n if (filter?.pageSize) params.set('pageSize', String(filter.pageSize));\n\n const qs = params.toString();\n return this.fetch<AiAssetListResponse>(`/assets${qs ? `?${qs}` : ''}`);\n }\n\n async getAsset(id: string): Promise<AiAsset> {\n return this.fetch<AiAsset>(`/assets/${encodeURIComponent(id)}`);\n }\n\n async getAssetRaw(id: string): Promise<string> {\n const base = await this.baseUrl();\n const response = await this.fetchApi.fetch(\n `${base}/assets/${encodeURIComponent(id)}/raw`,\n );\n if (!response.ok) throw new Error(`Failed to fetch raw asset: ${response.status}`);\n return response.text();\n }\n\n async getDownloadUrl(id: string, tool?: string): Promise<string> {\n const base = await this.baseUrl();\n const url = `${base}/assets/${encodeURIComponent(id)}/download`;\n return tool ? `${url}?tool=${encodeURIComponent(tool)}` : url;\n }\n\n async getAgentMdUrl(id: string): Promise<string> {\n const base = await this.baseUrl();\n return `${base}/assets/${encodeURIComponent(id)}/agent-md`;\n }\n\n async trackInstall(id: string): Promise<void> {\n await this.fetch(`/assets/${encodeURIComponent(id)}/track-install`, {\n method: 'POST',\n });\n }\n\n async listProviders(): Promise<AiHubProvider[]> {\n return this.fetch<AiHubProvider[]>('/providers');\n }\n\n async getProviderStatus(id: string): Promise<AiHubProvider> {\n return this.fetch<AiHubProvider>(\n `/providers/${encodeURIComponent(id)}/status`,\n );\n }\n\n async triggerSync(id: string): Promise<void> {\n await this.fetch(`/providers/${encodeURIComponent(id)}/sync`, {\n method: 'POST',\n });\n }\n\n async getStats(): Promise<AiHubStats> {\n return this.fetch<AiHubStats>('/stats');\n }\n\n async getMcpCatalog(): Promise<McpCatalogEntry[]> {\n return this.fetch<McpCatalogEntry[]>('/mcp-catalog');\n }\n\n async getUiConfig(): Promise<UiConfig> {\n return this.fetch<UiConfig>('/ui-config');\n }\n}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import Button from '@mui/material/Button';
|
|
5
|
+
import CircularProgress from '@mui/material/CircularProgress';
|
|
6
|
+
import Divider from '@mui/material/Divider';
|
|
7
|
+
import IconButton from '@mui/material/IconButton';
|
|
8
|
+
import Snackbar from '@mui/material/Snackbar';
|
|
9
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
10
|
+
import Typography from '@mui/material/Typography';
|
|
11
|
+
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
|
12
|
+
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
|
13
|
+
import SyncIcon from '@mui/icons-material/Sync';
|
|
14
|
+
import { Content } from '@backstage/core-components';
|
|
15
|
+
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
|
16
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
17
|
+
import { devAiHubSyncPermission } from '@julianpedro/plugin-dev-ai-hub-common';
|
|
18
|
+
import { devAiHubTranslationRef } from '../../translation.esm.js';
|
|
19
|
+
import { useProviders, useSyncProvider } from '../../hooks/index.esm.js';
|
|
20
|
+
|
|
21
|
+
function timeAgo(iso, translate) {
|
|
22
|
+
const diff = Math.floor((Date.now() - new Date(iso).getTime()) / 1e3);
|
|
23
|
+
if (diff < 60) return translate("devAiHubPage.timeJustNow") ?? "";
|
|
24
|
+
if (diff < 3600) return translate("devAiHubPage.timeMinutesAgo", { count: Math.floor(diff / 60) }) ?? "";
|
|
25
|
+
if (diff < 86400) return translate("devAiHubPage.timeHoursAgo", { count: Math.floor(diff / 3600) }) ?? "";
|
|
26
|
+
return translate("devAiHubPage.timeDaysAgo", { count: Math.floor(diff / 86400) }) ?? "";
|
|
27
|
+
}
|
|
28
|
+
function AdminPage() {
|
|
29
|
+
const { t } = useTranslationRef(devAiHubTranslationRef);
|
|
30
|
+
const [syncSnackbar, setSyncSnackbar] = useState(false);
|
|
31
|
+
const { allowed: canSync } = usePermission({ permission: devAiHubSyncPermission });
|
|
32
|
+
const { providers } = useProviders();
|
|
33
|
+
const { syncing, triggerSync, triggerSyncAll } = useSyncProvider();
|
|
34
|
+
return /* @__PURE__ */ jsxs(Content, { children: [
|
|
35
|
+
/* @__PURE__ */ jsxs(Box, { sx: { maxWidth: 720 }, children: [
|
|
36
|
+
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 3 }, children: [
|
|
37
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
38
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h6", fontWeight: 700, children: t("devAiHubPage.providersSectionTitle") }),
|
|
39
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t(providers.length === 1 ? "devAiHubPage.providerCountOne" : "devAiHubPage.providerCountOther", { n: String(providers.length) }) })
|
|
40
|
+
] }),
|
|
41
|
+
canSync && providers.length > 1 && /* @__PURE__ */ jsx(
|
|
42
|
+
Button,
|
|
43
|
+
{
|
|
44
|
+
size: "small",
|
|
45
|
+
variant: "outlined",
|
|
46
|
+
startIcon: providers.some((p) => syncing[p.id]) ? /* @__PURE__ */ jsx(CircularProgress, { size: 14 }) : /* @__PURE__ */ jsx(SyncIcon, {}),
|
|
47
|
+
disabled: providers.some((p) => syncing[p.id]),
|
|
48
|
+
onClick: async () => {
|
|
49
|
+
await triggerSyncAll(providers.map((p) => p.id));
|
|
50
|
+
setSyncSnackbar(true);
|
|
51
|
+
},
|
|
52
|
+
children: t("devAiHubPage.syncAllButton")
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
] }),
|
|
56
|
+
providers.length === 0 ? /* @__PURE__ */ jsx(Box, { sx: { border: "1px dashed", borderColor: "divider", borderRadius: 2, py: 6, textAlign: "center" }, children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t("devAiHubPage.noProvidersConfigured") }) }) : /* @__PURE__ */ jsx(Box, { sx: { border: "1px solid", borderColor: "divider", borderRadius: 2, overflow: "hidden" }, children: providers.map((provider, idx) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
57
|
+
/* @__PURE__ */ jsxs(Box, { sx: { px: 2.5, py: 2, display: "flex", alignItems: "center", gap: 1.5 }, children: [
|
|
58
|
+
provider.status === "error" && /* @__PURE__ */ jsx(Tooltip, { title: provider.error ?? t("devAiHubPage.providerStatusError"), children: /* @__PURE__ */ jsx(ErrorOutlineIcon, { sx: { fontSize: "1.1rem", color: "error.main", flexShrink: 0 } }) }),
|
|
59
|
+
provider.status === "syncing" && /* @__PURE__ */ jsx(CircularProgress, { size: 16, sx: { flexShrink: 0 } }),
|
|
60
|
+
provider.status !== "error" && provider.status !== "syncing" && /* @__PURE__ */ jsx(CheckCircleOutlineIcon, { sx: { fontSize: "1.1rem", color: "success.main", flexShrink: 0 } }),
|
|
61
|
+
/* @__PURE__ */ jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
Typography,
|
|
64
|
+
{
|
|
65
|
+
variant: "body2",
|
|
66
|
+
fontWeight: 600,
|
|
67
|
+
noWrap: true,
|
|
68
|
+
title: provider.target,
|
|
69
|
+
sx: { fontFamily: "monospace", fontSize: "0.8rem" },
|
|
70
|
+
children: provider.target
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
provider.lastSync && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", children: timeAgo(provider.lastSync, t) }),
|
|
74
|
+
provider.status === "error" && provider.error && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", sx: { display: "block" }, noWrap: true, title: provider.error, children: provider.error })
|
|
75
|
+
] }),
|
|
76
|
+
canSync && /* @__PURE__ */ jsx(Tooltip, { title: t("devAiHubPage.syncButton"), children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
|
|
77
|
+
IconButton,
|
|
78
|
+
{
|
|
79
|
+
size: "small",
|
|
80
|
+
"aria-label": t("devAiHubPage.syncButton"),
|
|
81
|
+
disabled: !!syncing[provider.id],
|
|
82
|
+
onClick: async () => {
|
|
83
|
+
await triggerSync(provider.id);
|
|
84
|
+
setSyncSnackbar(true);
|
|
85
|
+
},
|
|
86
|
+
children: syncing[provider.id] ? /* @__PURE__ */ jsx(CircularProgress, { size: 16 }) : /* @__PURE__ */ jsx(SyncIcon, { fontSize: "small" })
|
|
87
|
+
}
|
|
88
|
+
) }) })
|
|
89
|
+
] }),
|
|
90
|
+
idx < providers.length - 1 && /* @__PURE__ */ jsx(Divider, {})
|
|
91
|
+
] }, provider.id)) })
|
|
92
|
+
] }),
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
Snackbar,
|
|
95
|
+
{
|
|
96
|
+
open: syncSnackbar,
|
|
97
|
+
autoHideDuration: 3e3,
|
|
98
|
+
onClose: () => setSyncSnackbar(false),
|
|
99
|
+
message: t("devAiHubPage.syncTriggered")
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { AdminPage };
|
|
106
|
+
//# sourceMappingURL=AdminPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminPage.esm.js","sources":["../../../src/components/AdminPage/AdminPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Divider from '@mui/material/Divider';\nimport IconButton from '@mui/material/IconButton';\nimport Snackbar from '@mui/material/Snackbar';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';\nimport ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';\nimport SyncIcon from '@mui/icons-material/Sync';\nimport { Content } from '@backstage/core-components';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { devAiHubSyncPermission } from '@julianpedro/plugin-dev-ai-hub-common';\nimport { devAiHubTranslationRef } from '../../translation';\nimport { useProviders, useSyncProvider } from '../../hooks';\n\ntype TFunc = (key: string, params?: Record<string, unknown>) => string | undefined;\n\nfunction timeAgo(iso: string, translate: TFunc): string {\n const diff = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);\n if (diff < 60) return (translate('devAiHubPage.timeJustNow') ?? '') as string;\n if (diff < 3600) return (translate('devAiHubPage.timeMinutesAgo', { count: Math.floor(diff / 60) }) ?? '') as string;\n if (diff < 86400) return (translate('devAiHubPage.timeHoursAgo', { count: Math.floor(diff / 3600) }) ?? '') as string;\n return (translate('devAiHubPage.timeDaysAgo', { count: Math.floor(diff / 86400) }) ?? '') as string;\n}\n\nexport function AdminPage() {\n const { t } = useTranslationRef(devAiHubTranslationRef);\n const [syncSnackbar, setSyncSnackbar] = useState(false);\n const { allowed: canSync } = usePermission({ permission: devAiHubSyncPermission });\n const { providers } = useProviders();\n const { syncing, triggerSync, triggerSyncAll } = useSyncProvider();\n\n return (\n <Content>\n <Box sx={{ maxWidth: 720 }}>\n {/* Section header */}\n <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 3 }}>\n <Box>\n <Typography variant=\"h6\" fontWeight={700}>\n {t('devAiHubPage.providersSectionTitle')}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {t(providers.length === 1 ? 'devAiHubPage.providerCountOne' : 'devAiHubPage.providerCountOther', { n: String(providers.length) })}\n </Typography>\n </Box>\n {canSync && providers.length > 1 && (\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={providers.some(p => syncing[p.id]) ? <CircularProgress size={14} /> : <SyncIcon />}\n disabled={providers.some(p => syncing[p.id])}\n onClick={async () => {\n await triggerSyncAll(providers.map(p => p.id));\n setSyncSnackbar(true);\n }}\n >\n {t('devAiHubPage.syncAllButton')}\n </Button>\n )}\n </Box>\n\n {/* Provider list */}\n {providers.length === 0 ? (\n <Box sx={{ border: '1px dashed', borderColor: 'divider', borderRadius: 2, py: 6, textAlign: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {t('devAiHubPage.noProvidersConfigured')}\n </Typography>\n </Box>\n ) : (\n <Box sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 2, overflow: 'hidden' }}>\n {providers.map((provider, idx) => (\n <Box key={provider.id}>\n <Box sx={{ px: 2.5, py: 2, display: 'flex', alignItems: 'center', gap: 1.5 }}>\n {provider.status === 'error' && (\n <Tooltip title={provider.error ?? t('devAiHubPage.providerStatusError')}>\n <ErrorOutlineIcon sx={{ fontSize: '1.1rem', color: 'error.main', flexShrink: 0 }} />\n </Tooltip>\n )}\n {provider.status === 'syncing' && (\n <CircularProgress size={16} sx={{ flexShrink: 0 }} />\n )}\n {provider.status !== 'error' && provider.status !== 'syncing' && (\n <CheckCircleOutlineIcon sx={{ fontSize: '1.1rem', color: 'success.main', flexShrink: 0 }} />\n )}\n\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Typography\n variant=\"body2\" fontWeight={600} noWrap title={provider.target}\n sx={{ fontFamily: 'monospace', fontSize: '0.8rem' }}\n >\n {provider.target}\n </Typography>\n {provider.lastSync && (\n <Typography variant=\"caption\" color=\"text.disabled\">\n {timeAgo(provider.lastSync, t as TFunc)}\n </Typography>\n )}\n {provider.status === 'error' && provider.error && (\n <Typography variant=\"caption\" color=\"error\" sx={{ display: 'block' }} noWrap title={provider.error}>\n {provider.error}\n </Typography>\n )}\n </Box>\n\n {canSync && (\n <Tooltip title={t('devAiHubPage.syncButton')}>\n <span>\n <IconButton\n size=\"small\"\n aria-label={t('devAiHubPage.syncButton') as string}\n disabled={!!syncing[provider.id]}\n onClick={async () => {\n await triggerSync(provider.id);\n setSyncSnackbar(true);\n }}\n >\n {syncing[provider.id]\n ? <CircularProgress size={16} />\n : <SyncIcon fontSize=\"small\" />}\n </IconButton>\n </span>\n </Tooltip>\n )}\n </Box>\n {idx < providers.length - 1 && <Divider />}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n\n <Snackbar\n open={syncSnackbar}\n autoHideDuration={3000}\n onClose={() => setSyncSnackbar(false)}\n message={t('devAiHubPage.syncTriggered')}\n />\n </Content>\n );\n}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -15,11 +15,17 @@ import ArticleIcon from '@mui/icons-material/Article';
|
|
|
15
15
|
import SmartToyIcon from '@mui/icons-material/SmartToy';
|
|
16
16
|
import BuildIcon from '@mui/icons-material/Build';
|
|
17
17
|
import AccountTreeIcon from '@mui/icons-material/AccountTree';
|
|
18
|
+
import ChatIcon from '@mui/icons-material/Chat';
|
|
18
19
|
import Inventory2Icon from '@mui/icons-material/Inventory2';
|
|
19
|
-
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
|
|
20
20
|
import StorageIcon from '@mui/icons-material/Storage';
|
|
21
|
+
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
|
21
22
|
import { ToolIcon } from '../ToolIcon/ToolIcon.esm.js';
|
|
23
|
+
import { ModelBadge } from '../ModelIcon/ModelBadge.esm.js';
|
|
22
24
|
import { devAiHubTranslationRef } from '../../translation.esm.js';
|
|
25
|
+
import 'react';
|
|
26
|
+
import '@backstage/core-plugin-api';
|
|
27
|
+
import '../../api/DevAiHubClient.esm.js';
|
|
28
|
+
import { useTypeConfig } from '../../context/UiConfigContext.esm.js';
|
|
23
29
|
|
|
24
30
|
const POPULAR_THRESHOLD = 5;
|
|
25
31
|
const NEW_DAYS_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
@@ -31,12 +37,21 @@ const TOOL_LABELS = {
|
|
|
31
37
|
"google-gemini": "Google Gemini",
|
|
32
38
|
"cursor": "Cursor"
|
|
33
39
|
};
|
|
34
|
-
const
|
|
35
|
-
instruction:
|
|
36
|
-
agent:
|
|
37
|
-
skill:
|
|
38
|
-
workflow:
|
|
39
|
-
|
|
40
|
+
const TYPE_LABELS = {
|
|
41
|
+
instruction: "Instruction",
|
|
42
|
+
agent: "Agent",
|
|
43
|
+
skill: "Skill",
|
|
44
|
+
workflow: "Workflow",
|
|
45
|
+
prompt: "Prompt",
|
|
46
|
+
bundle: "Bundle"
|
|
47
|
+
};
|
|
48
|
+
const TYPE_ICONS = {
|
|
49
|
+
instruction: ArticleIcon,
|
|
50
|
+
agent: SmartToyIcon,
|
|
51
|
+
skill: BuildIcon,
|
|
52
|
+
workflow: AccountTreeIcon,
|
|
53
|
+
prompt: ChatIcon,
|
|
54
|
+
bundle: Inventory2Icon
|
|
40
55
|
};
|
|
41
56
|
function resolveMcp(req, catalog) {
|
|
42
57
|
const entry = catalog.find((e) => e.id === req.id);
|
|
@@ -48,9 +63,10 @@ function resolveMcp(req, catalog) {
|
|
|
48
63
|
function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCatalog = [] }) {
|
|
49
64
|
const { t } = useTranslationRef(devAiHubTranslationRef);
|
|
50
65
|
const theme = useTheme();
|
|
66
|
+
const { typeColors } = useTypeConfig();
|
|
51
67
|
const isDark = theme.palette.mode === "dark" || theme.palette.type === "dark";
|
|
52
|
-
const
|
|
53
|
-
const TypeIcon =
|
|
68
|
+
const color = typeColors[asset.type];
|
|
69
|
+
const TypeIcon = TYPE_ICONS[asset.type];
|
|
54
70
|
const isPopular = asset.installCount >= POPULAR_THRESHOLD;
|
|
55
71
|
const isNew = Date.now() - new Date(asset.createdAt).getTime() < NEW_DAYS_MS;
|
|
56
72
|
const isUpdated = !isNew && Date.now() - new Date(asset.updatedAt).getTime() < UPDATED_DAYS_MS;
|
|
@@ -65,11 +81,11 @@ function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCata
|
|
|
65
81
|
borderRadius: 2,
|
|
66
82
|
border: "1px solid",
|
|
67
83
|
borderColor: "divider",
|
|
68
|
-
borderLeft: `3px solid ${
|
|
84
|
+
borderLeft: `3px solid ${color}`,
|
|
69
85
|
transition: "all 0.18s ease",
|
|
70
86
|
"&:hover": {
|
|
71
|
-
boxShadow: `0 6px 24px ${
|
|
72
|
-
borderColor:
|
|
87
|
+
boxShadow: `0 6px 24px ${color}30`,
|
|
88
|
+
borderColor: color,
|
|
73
89
|
transform: "translateY(-2px)"
|
|
74
90
|
}
|
|
75
91
|
},
|
|
@@ -83,12 +99,12 @@ function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCata
|
|
|
83
99
|
width: 40,
|
|
84
100
|
height: 40,
|
|
85
101
|
borderRadius: 1.5,
|
|
86
|
-
backgroundColor: alpha(
|
|
102
|
+
backgroundColor: alpha(color, 0.12),
|
|
87
103
|
display: "flex",
|
|
88
104
|
alignItems: "center",
|
|
89
105
|
justifyContent: "center",
|
|
90
106
|
flexShrink: 0,
|
|
91
|
-
boxShadow: `0 2px 8px ${
|
|
107
|
+
boxShadow: `0 2px 8px ${color}25`
|
|
92
108
|
},
|
|
93
109
|
children: asset.icon ? /* @__PURE__ */ jsx(
|
|
94
110
|
Box,
|
|
@@ -101,7 +117,7 @@ function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCata
|
|
|
101
117
|
e.target.style.display = "none";
|
|
102
118
|
}
|
|
103
119
|
}
|
|
104
|
-
) : /* @__PURE__ */ jsx(TypeIcon, { sx: { color
|
|
120
|
+
) : /* @__PURE__ */ jsx(TypeIcon, { sx: { color, fontSize: "1.3rem" } })
|
|
105
121
|
}
|
|
106
122
|
),
|
|
107
123
|
/* @__PURE__ */ jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [
|
|
@@ -147,7 +163,10 @@ function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCata
|
|
|
147
163
|
}
|
|
148
164
|
)
|
|
149
165
|
] }),
|
|
150
|
-
/* @__PURE__ */
|
|
166
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
167
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", sx: { color, fontWeight: 600 }, children: TYPE_LABELS[asset.type] }),
|
|
168
|
+
asset.type === "agent" && asset.model && /* @__PURE__ */ jsx(Box, { sx: { mt: 0.3 }, children: /* @__PURE__ */ jsx(ModelBadge, { model: asset.model }) })
|
|
169
|
+
] })
|
|
151
170
|
] })
|
|
152
171
|
] }),
|
|
153
172
|
/* @__PURE__ */ jsx(
|
|
@@ -251,7 +270,7 @@ function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCata
|
|
|
251
270
|
] }),
|
|
252
271
|
/* @__PURE__ */ jsxs(CardActions, { sx: { px: 1.5, py: 1, justifyContent: "space-between", mt: "auto", borderTop: "1px solid", borderColor: "divider" }, children: [
|
|
253
272
|
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
|
|
254
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", sx: { fontSize: "0.65rem" }, children: asset.type === "bundle" && asset.itemCount !== void 0 ? t("assetCard.bundleFooter", {
|
|
273
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", sx: { fontSize: "0.65rem" }, children: asset.type === "bundle" && asset.itemCount !== void 0 ? t("assetCard.bundleFooter", { itemCount: String(asset.itemCount), author: asset.author }) : t("assetCard.versionFooter", { version: asset.version, author: asset.author }) }),
|
|
255
274
|
asset.installCount > 0 && /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.25 }, children: [
|
|
256
275
|
/* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.65rem", lineHeight: 1 }, children: isPopular ? "\u{1F525}" : "\u2193" }),
|
|
257
276
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", sx: { fontSize: "0.65rem" }, children: asset.installCount })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetCard.esm.js","sources":["../../../src/components/AssetCard/AssetCard.tsx"],"sourcesContent":["import type { ElementType } from 'react';\nimport { alpha, useTheme } from '@mui/material/styles';\nimport Box from '@mui/material/Box';\nimport Card from '@mui/material/Card';\nimport CardActions from '@mui/material/CardActions';\nimport CardContent from '@mui/material/CardContent';\nimport Chip from '@mui/material/Chip';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport DownloadIcon from '@mui/icons-material/Download';\nimport HelpOutlineIcon from '@mui/icons-material/HelpOutline';\nimport ArticleIcon from '@mui/icons-material/Article';\nimport SmartToyIcon from '@mui/icons-material/SmartToy';\nimport BuildIcon from '@mui/icons-material/Build';\nimport AccountTreeIcon from '@mui/icons-material/AccountTree';\nimport Inventory2Icon from '@mui/icons-material/Inventory2';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport StorageIcon from '@mui/icons-material/Storage';\nimport type { AiAssetSummary, AssetType, AiTool, McpCatalogEntry, McpRequirement } from '@julianpedro/plugin-dev-ai-hub-common';\nimport { ToolIcon } from '../ToolIcon';\nimport { devAiHubTranslationRef } from '../../translation';\n\nconst POPULAR_THRESHOLD = 5;\nconst NEW_DAYS_MS = 14 * 24 * 60 * 60 * 1000;\nconst UPDATED_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\n\nconst TOOL_LABELS: Record<AiTool, string> = {\n 'all': 'Universal',\n 'claude-code': 'Claude Code',\n 'github-copilot': 'GitHub Copilot',\n 'google-gemini': 'Google Gemini',\n 'cursor': 'Cursor',\n};\n\nconst TYPE_CONFIG: Record<AssetType, { label: string; color: string; Icon: ElementType }> = {\n instruction: { label: 'Instruction', color: '#2563EB', Icon: ArticleIcon },\n agent: { label: 'Agent', color: '#7C3AED', Icon: SmartToyIcon },\n skill: { label: 'Skill', color: '#059669', Icon: BuildIcon },\n workflow: { label: 'Workflow', color: '#D97706', Icon: AccountTreeIcon },\n bundle: { label: 'Bundle', color: '#8B5CF6', Icon: Inventory2Icon },\n};\n\nfunction resolveMcp(req: McpRequirement, catalog: McpCatalogEntry[]): { name: string; icon?: string } {\n const entry = catalog.find(e => e.id === req.id);\n return {\n name: req.name ?? entry?.name ?? req.id,\n icon: req.icon ?? entry?.icon,\n };\n}\n\ninterface AssetCardProps {\n asset: AiAssetSummary;\n onView: (id: string) => void;\n onInstall: (id: string) => void;\n onHelp?: (id: string) => void;\n onOpenMcpCatalog?: () => void;\n mcpCatalog?: McpCatalogEntry[];\n}\n\nexport function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCatalog = [] }: AssetCardProps) {\n const { t } = useTranslationRef(devAiHubTranslationRef);\n const theme = useTheme();\n const isDark = (theme.palette as any).mode === 'dark' || (theme.palette as any).type === 'dark';\n const cfg = TYPE_CONFIG[asset.type];\n const TypeIcon = cfg.Icon;\n const isPopular = asset.installCount >= POPULAR_THRESHOLD;\n const isNew = Date.now() - new Date(asset.createdAt).getTime() < NEW_DAYS_MS;\n const isUpdated = !isNew && Date.now() - new Date(asset.updatedAt).getTime() < UPDATED_DAYS_MS;\n\n return (\n <Card\n variant=\"outlined\"\n sx={{\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n borderRadius: 2,\n border: '1px solid',\n borderColor: 'divider',\n borderLeft: `3px solid ${cfg.color}`,\n transition: 'all 0.18s ease',\n '&:hover': {\n boxShadow: `0 6px 24px ${cfg.color}30`,\n borderColor: cfg.color,\n transform: 'translateY(-2px)',\n },\n }}\n >\n <CardContent sx={{ p: 1.5, pb: '0 !important', flex: 1 }}>\n {/* Header */}\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1, mb: 1 }}>\n <Box\n sx={{\n width: 40,\n height: 40,\n borderRadius: 1.5,\n backgroundColor: alpha(cfg.color, 0.12),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: `0 2px 8px ${cfg.color}25`,\n }}\n >\n {asset.icon ? (\n <Box\n component=\"img\"\n src={asset.icon}\n alt={asset.label ?? asset.name}\n sx={{ width: 26, height: 26, objectFit: 'contain' }}\n onError={e => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n ) : (\n <TypeIcon sx={{ color: cfg.color, fontSize: '1.3rem' }} />\n )}\n </Box>\n\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mb: 0.2 }}>\n <Typography variant=\"body2\" fontWeight={700} noWrap title={asset.label ?? asset.name} sx={{ lineHeight: 1.2, flex: 1 }}>\n {asset.label ?? asset.name}\n </Typography>\n {isNew && (\n <Chip\n label={t('assetCard.newBadge')}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.6rem',\n fontWeight: 700,\n backgroundColor: alpha('#059669', isDark ? 0.25 : 0.14),\n backdropFilter: 'blur(8px)',\n color: isDark ? '#6ee7b7' : '#059669',\n border: '1px solid',\n borderColor: alpha('#059669', isDark ? 0.5 : 0.3),\n borderRadius: 1,\n flexShrink: 0,\n '& .MuiChip-label': { px: '6px' },\n }}\n />\n )}\n {isUpdated && (\n <Chip\n label={t('assetCard.updatedBadge')}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.6rem',\n fontWeight: 700,\n backgroundColor: alpha('#D97706', isDark ? 0.25 : 0.12),\n color: isDark ? '#fcd34d' : '#D97706',\n border: '1px solid',\n borderColor: alpha('#D97706', isDark ? 0.5 : 0.3),\n borderRadius: 1,\n flexShrink: 0,\n '& .MuiChip-label': { px: '6px' },\n }}\n />\n )}\n </Box>\n <Typography variant=\"caption\" sx={{ color: cfg.color, fontWeight: 600 }}>\n {cfg.label}\n </Typography>\n </Box>\n </Box>\n\n {/* Description */}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n title={asset.description}\n sx={{\n mb: 1,\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n lineHeight: 1.4,\n }}\n >\n {asset.description}\n </Typography>\n\n {/* Tools */}\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mb: asset.tags.length > 0 ? 0.75 : 0 }}>\n {asset.tools.map(tool => (\n <Chip\n key={tool}\n icon={<ToolIcon tool={tool as AiTool} sx={{ fontSize: '0.75rem !important' }} />}\n label={TOOL_LABELS[tool as AiTool] ?? tool}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.65rem',\n fontWeight: 600,\n backgroundColor: 'action.hover',\n color: 'text.secondary',\n borderRadius: 1,\n '& .MuiChip-icon': { ml: '4px' },\n }}\n />\n ))}\n </Box>\n\n {/* Tags */}\n {asset.tags.length > 0 && (\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>\n {asset.tags.slice(0, 3).map(tag => (\n <Chip\n key={tag}\n label={`#${tag}`}\n size=\"small\"\n sx={{\n height: 16,\n fontSize: '0.6rem',\n color: 'text.disabled',\n backgroundColor: 'transparent',\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: 1,\n }}\n />\n ))}\n {asset.tags.length > 3 && (\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ alignSelf: 'center' }}>\n +{asset.tags.length - 3}\n </Typography>\n )}\n </Box>\n )}\n\n {/* Required MCPs — circular icon-only badges, below tags */}\n {asset.mcps && asset.mcps.length > 0 && (\n <Box sx={{ mt: 0.75, mb: 1 }}>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.6rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.4, display: 'block', mb: 0.5 }}>\n {t('assetCard.mcpsRequired')}\n </Typography>\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>\n {asset.mcps.map(req => {\n const { name, icon } = resolveMcp(req, mcpCatalog);\n return (\n <Box\n key={req.id}\n title={name}\n onClick={onOpenMcpCatalog}\n sx={{\n width: 26,\n height: 26,\n borderRadius: '50%',\n backgroundColor: 'action.hover',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n overflow: 'hidden',\n cursor: onOpenMcpCatalog ? 'pointer' : 'default',\n transition: 'background-color 0.15s ease',\n '&:hover': onOpenMcpCatalog ? { backgroundColor: 'action.selected' } : {},\n }}\n >\n {icon ? (\n <Box\n component=\"img\"\n src={icon}\n alt={name}\n sx={{ width: 18, height: 18, objectFit: 'contain' }}\n onError={e => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n ) : (\n <StorageIcon sx={{ fontSize: '0.9rem', color: 'text.secondary' }} />\n )}\n </Box>\n );\n })}\n </Box>\n </Box>\n )}\n </CardContent>\n\n <CardActions sx={{ px: 1.5, py: 1, justifyContent: 'space-between', mt: 'auto', borderTop: '1px solid', borderColor: 'divider' }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.65rem' }}>\n {asset.type === 'bundle' && asset.itemCount !== undefined\n ? t('assetCard.bundleFooter', { count: asset.itemCount, author: asset.author })\n : t('assetCard.versionFooter', { version: asset.version, author: asset.author })}\n </Typography>\n {asset.installCount > 0 && (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.25 }}>\n <Typography sx={{ fontSize: '0.65rem', lineHeight: 1 }}>\n {isPopular ? '🔥' : '↓'}\n </Typography>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.65rem' }}>\n {asset.installCount}\n </Typography>\n </Box>\n )}\n </Box>\n <Box sx={{ display: 'flex', gap: 0.25 }}>\n <Tooltip title={t('assetCard.installTooltip')}>\n <IconButton size=\"small\" onClick={() => onInstall(asset.id)} color=\"primary\">\n <DownloadIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip title={t('assetCard.detailsTooltip')}>\n <IconButton size=\"small\" onClick={() => onView(asset.id)}>\n <OpenInNewIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n {asset.helpText && onHelp && (\n <Tooltip title={t('assetCard.helpTooltip')}>\n <IconButton size=\"small\" onClick={() => onHelp(asset.id)}>\n <HelpOutlineIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </Box>\n </CardActions>\n </Card>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssetCard.esm.js","sources":["../../../src/components/AssetCard/AssetCard.tsx"],"sourcesContent":["import type { ElementType } from 'react';\nimport { alpha, useTheme } from '@mui/material/styles';\nimport Box from '@mui/material/Box';\nimport Card from '@mui/material/Card';\nimport CardActions from '@mui/material/CardActions';\nimport CardContent from '@mui/material/CardContent';\nimport Chip from '@mui/material/Chip';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport DownloadIcon from '@mui/icons-material/Download';\nimport HelpOutlineIcon from '@mui/icons-material/HelpOutline';\nimport ArticleIcon from '@mui/icons-material/Article';\nimport SmartToyIcon from '@mui/icons-material/SmartToy';\nimport BuildIcon from '@mui/icons-material/Build';\nimport AccountTreeIcon from '@mui/icons-material/AccountTree';\nimport ChatIcon from '@mui/icons-material/Chat';\nimport Inventory2Icon from '@mui/icons-material/Inventory2';\nimport StorageIcon from '@mui/icons-material/Storage';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport type { AiAssetSummary, AssetType, AiTool, McpCatalogEntry, McpRequirement } from '@julianpedro/plugin-dev-ai-hub-common';\nimport { ToolIcon } from '../ToolIcon';\nimport { ModelBadge } from '../ModelIcon';\nimport { devAiHubTranslationRef } from '../../translation';\nimport { useTypeConfig } from '../../hooks';\n\nconst POPULAR_THRESHOLD = 5;\nconst NEW_DAYS_MS = 14 * 24 * 60 * 60 * 1000;\nconst UPDATED_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\n\nconst TOOL_LABELS: Record<AiTool, string> = {\n 'all': 'Universal',\n 'claude-code': 'Claude Code',\n 'github-copilot': 'GitHub Copilot',\n 'google-gemini': 'Google Gemini',\n 'cursor': 'Cursor',\n};\n\nconst TYPE_LABELS: Record<AssetType, string> = {\n instruction: 'Instruction',\n agent: 'Agent',\n skill: 'Skill',\n workflow: 'Workflow',\n prompt: 'Prompt',\n bundle: 'Bundle',\n};\n\nconst TYPE_ICONS: Record<AssetType, ElementType> = {\n instruction: ArticleIcon,\n agent: SmartToyIcon,\n skill: BuildIcon,\n workflow: AccountTreeIcon,\n prompt: ChatIcon,\n bundle: Inventory2Icon,\n};\n\nfunction resolveMcp(req: McpRequirement, catalog: McpCatalogEntry[]): { name: string; icon?: string } {\n const entry = catalog.find(e => e.id === req.id);\n return {\n name: req.name ?? entry?.name ?? req.id,\n icon: req.icon ?? entry?.icon,\n };\n}\n\ninterface AssetCardProps {\n asset: AiAssetSummary;\n onView: (id: string) => void;\n onInstall: (id: string) => void;\n onHelp?: (id: string) => void;\n onOpenMcpCatalog?: () => void;\n mcpCatalog?: McpCatalogEntry[];\n}\n\nexport function AssetCard({ asset, onView, onInstall, onHelp, onOpenMcpCatalog, mcpCatalog = [] }: AssetCardProps) {\n const { t } = useTranslationRef(devAiHubTranslationRef);\n const theme = useTheme();\n const { typeColors } = useTypeConfig();\n const isDark = (theme.palette as any).mode === 'dark' || (theme.palette as any).type === 'dark';\n const color = typeColors[asset.type];\n const TypeIcon = TYPE_ICONS[asset.type];\n const isPopular = asset.installCount >= POPULAR_THRESHOLD;\n const isNew = Date.now() - new Date(asset.createdAt).getTime() < NEW_DAYS_MS;\n const isUpdated = !isNew && Date.now() - new Date(asset.updatedAt).getTime() < UPDATED_DAYS_MS;\n\n return (\n <Card\n variant=\"outlined\"\n sx={{\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n borderRadius: 2,\n border: '1px solid',\n borderColor: 'divider',\n borderLeft: `3px solid ${color}`,\n transition: 'all 0.18s ease',\n '&:hover': {\n boxShadow: `0 6px 24px ${color}30`,\n borderColor: color,\n transform: 'translateY(-2px)',\n },\n }}\n >\n <CardContent sx={{ p: 1.5, pb: '0 !important', flex: 1 }}>\n {/* Header */}\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1, mb: 1 }}>\n <Box\n sx={{\n width: 40,\n height: 40,\n borderRadius: 1.5,\n backgroundColor: alpha(color, 0.12),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: `0 2px 8px ${color}25`,\n }}\n >\n {asset.icon ? (\n <Box\n component=\"img\"\n src={asset.icon}\n alt={asset.label ?? asset.name}\n sx={{ width: 26, height: 26, objectFit: 'contain' }}\n onError={e => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n ) : (\n <TypeIcon sx={{ color, fontSize: '1.3rem' }} />\n )}\n </Box>\n\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mb: 0.2 }}>\n <Typography variant=\"body2\" fontWeight={700} noWrap title={asset.label ?? asset.name} sx={{ lineHeight: 1.2, flex: 1 }}>\n {asset.label ?? asset.name}\n </Typography>\n {isNew && (\n <Chip\n label={t('assetCard.newBadge')}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.6rem',\n fontWeight: 700,\n backgroundColor: alpha('#059669', isDark ? 0.25 : 0.14),\n backdropFilter: 'blur(8px)',\n color: isDark ? '#6ee7b7' : '#059669',\n border: '1px solid',\n borderColor: alpha('#059669', isDark ? 0.5 : 0.3),\n borderRadius: 1,\n flexShrink: 0,\n '& .MuiChip-label': { px: '6px' },\n }}\n />\n )}\n {isUpdated && (\n <Chip\n label={t('assetCard.updatedBadge')}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.6rem',\n fontWeight: 700,\n backgroundColor: alpha('#D97706', isDark ? 0.25 : 0.12),\n color: isDark ? '#fcd34d' : '#D97706',\n border: '1px solid',\n borderColor: alpha('#D97706', isDark ? 0.5 : 0.3),\n borderRadius: 1,\n flexShrink: 0,\n '& .MuiChip-label': { px: '6px' },\n }}\n />\n )}\n </Box>\n <Box>\n <Typography variant=\"caption\" sx={{ color, fontWeight: 600 }}>\n {TYPE_LABELS[asset.type]}\n </Typography>\n {asset.type === 'agent' && asset.model && (\n <Box sx={{ mt: 0.3 }}>\n <ModelBadge model={asset.model} />\n </Box>\n )}\n </Box>\n </Box>\n </Box>\n\n {/* Description */}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n title={asset.description}\n sx={{\n mb: 1,\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n lineHeight: 1.4,\n }}\n >\n {asset.description}\n </Typography>\n\n {/* Tools */}\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mb: asset.tags.length > 0 ? 0.75 : 0 }}>\n {asset.tools.map(tool => (\n <Chip\n key={tool}\n icon={<ToolIcon tool={tool as AiTool} sx={{ fontSize: '0.75rem !important' }} />}\n label={TOOL_LABELS[tool as AiTool] ?? tool}\n size=\"small\"\n sx={{\n height: 18,\n fontSize: '0.65rem',\n fontWeight: 600,\n backgroundColor: 'action.hover',\n color: 'text.secondary',\n borderRadius: 1,\n '& .MuiChip-icon': { ml: '4px' },\n }}\n />\n ))}\n </Box>\n\n {/* Tags */}\n {asset.tags.length > 0 && (\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>\n {asset.tags.slice(0, 3).map(tag => (\n <Chip\n key={tag}\n label={`#${tag}`}\n size=\"small\"\n sx={{\n height: 16,\n fontSize: '0.6rem',\n color: 'text.disabled',\n backgroundColor: 'transparent',\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: 1,\n }}\n />\n ))}\n {asset.tags.length > 3 && (\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ alignSelf: 'center' }}>\n +{asset.tags.length - 3}\n </Typography>\n )}\n </Box>\n )}\n\n {/* Required MCPs — circular icon-only badges, below tags */}\n {asset.mcps && asset.mcps.length > 0 && (\n <Box sx={{ mt: 0.75, mb: 1 }}>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.6rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.4, display: 'block', mb: 0.5 }}>\n {t('assetCard.mcpsRequired')}\n </Typography>\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>\n {asset.mcps.map(req => {\n const { name, icon } = resolveMcp(req, mcpCatalog);\n return (\n <Box\n key={req.id}\n title={name}\n onClick={onOpenMcpCatalog}\n sx={{\n width: 26,\n height: 26,\n borderRadius: '50%',\n backgroundColor: 'action.hover',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n overflow: 'hidden',\n cursor: onOpenMcpCatalog ? 'pointer' : 'default',\n transition: 'background-color 0.15s ease',\n '&:hover': onOpenMcpCatalog ? { backgroundColor: 'action.selected' } : {},\n }}\n >\n {icon ? (\n <Box\n component=\"img\"\n src={icon}\n alt={name}\n sx={{ width: 18, height: 18, objectFit: 'contain' }}\n onError={e => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n ) : (\n <StorageIcon sx={{ fontSize: '0.9rem', color: 'text.secondary' }} />\n )}\n </Box>\n );\n })}\n </Box>\n </Box>\n )}\n </CardContent>\n\n <CardActions sx={{ px: 1.5, py: 1, justifyContent: 'space-between', mt: 'auto', borderTop: '1px solid', borderColor: 'divider' }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.65rem' }}>\n {asset.type === 'bundle' && asset.itemCount !== undefined\n ? t('assetCard.bundleFooter', { itemCount: String(asset.itemCount), author: asset.author })\n : t('assetCard.versionFooter', { version: asset.version, author: asset.author })}\n </Typography>\n {asset.installCount > 0 && (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.25 }}>\n <Typography sx={{ fontSize: '0.65rem', lineHeight: 1 }}>\n {isPopular ? '🔥' : '↓'}\n </Typography>\n <Typography variant=\"caption\" color=\"text.disabled\" sx={{ fontSize: '0.65rem' }}>\n {asset.installCount}\n </Typography>\n </Box>\n )}\n </Box>\n <Box sx={{ display: 'flex', gap: 0.25 }}>\n <Tooltip title={t('assetCard.installTooltip')}>\n <IconButton size=\"small\" onClick={() => onInstall(asset.id)} color=\"primary\">\n <DownloadIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip title={t('assetCard.detailsTooltip')}>\n <IconButton size=\"small\" onClick={() => onView(asset.id)}>\n <OpenInNewIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n {asset.helpText && onHelp && (\n <Tooltip title={t('assetCard.helpTooltip')}>\n <IconButton size=\"small\" onClick={() => onHelp(asset.id)}>\n <HelpOutlineIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </Box>\n </CardActions>\n </Card>\n );\n}"],"names":[],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
|
23
23
|
import FolderZipIcon from '@mui/icons-material/FolderZip';
|
|
24
24
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
25
25
|
import Inventory2Icon from '@mui/icons-material/Inventory2';
|
|
26
|
-
import { useTranslationRef } from '@backstage/
|
|
26
|
+
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
|
27
27
|
import { useAssetDetail } from '../../hooks/index.esm.js';
|
|
28
28
|
import { devAiHubTranslationRef } from '../../translation.esm.js';
|
|
29
29
|
|
|
@@ -44,6 +44,7 @@ const TYPE_COLORS = {
|
|
|
44
44
|
agent: "#7b1fa2",
|
|
45
45
|
skill: "#388e3c",
|
|
46
46
|
workflow: "#f57c00",
|
|
47
|
+
prompt: "#EC4899",
|
|
47
48
|
bundle: "#8B5CF6"
|
|
48
49
|
};
|
|
49
50
|
function AssetDetailPanel({ assetId, onClose }) {
|
|
@@ -97,11 +98,9 @@ function AssetDetailPanel({ assetId, onClose }) {
|
|
|
97
98
|
label: asset.type,
|
|
98
99
|
size: "small",
|
|
99
100
|
sx: {
|
|
100
|
-
backgroundColor:
|
|
101
|
-
color:
|
|
102
|
-
|
|
103
|
-
borderColor: `${TYPE_COLORS[asset.type]}55`,
|
|
104
|
-
fontWeight: 600
|
|
101
|
+
backgroundColor: TYPE_COLORS[asset.type],
|
|
102
|
+
color: "#fff",
|
|
103
|
+
fontWeight: 700
|
|
105
104
|
}
|
|
106
105
|
}
|
|
107
106
|
)
|
|
@@ -131,7 +130,7 @@ function AssetDetailPanel({ assetId, onClose }) {
|
|
|
131
130
|
tab === 0 && asset.type === "bundle" && /* @__PURE__ */ jsxs(Box, { children: [
|
|
132
131
|
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75, mb: 1.5 }, children: [
|
|
133
132
|
/* @__PURE__ */ jsx(Inventory2Icon, { sx: { fontSize: "1rem", color: "#8B5CF6" } }),
|
|
134
|
-
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", fontWeight: 600, color: "text.secondary", children: t("assetDetailPanel.bundlePreviewTitle", {
|
|
133
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", fontWeight: 600, color: "text.secondary", children: t("assetDetailPanel.bundlePreviewTitle", { total: String(asset.items?.length ?? 0) }) })
|
|
135
134
|
] }),
|
|
136
135
|
asset.description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: asset.description }),
|
|
137
136
|
/* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.75 }, children: (asset.items ?? []).map((item, idx) => /* @__PURE__ */ jsx(
|
|
@@ -158,11 +157,9 @@ function AssetDetailPanel({ assetId, onClose }) {
|
|
|
158
157
|
sx: {
|
|
159
158
|
height: 18,
|
|
160
159
|
fontSize: "0.65rem",
|
|
161
|
-
bgcolor:
|
|
162
|
-
color:
|
|
163
|
-
|
|
164
|
-
borderColor: `${TYPE_COLORS[item.type] ?? "#666"}55`,
|
|
165
|
-
fontWeight: 600,
|
|
160
|
+
bgcolor: TYPE_COLORS[item.type] ?? "#64748b",
|
|
161
|
+
color: "#fff",
|
|
162
|
+
fontWeight: 700,
|
|
166
163
|
flexShrink: 0
|
|
167
164
|
}
|
|
168
165
|
}
|
|
@@ -333,7 +330,7 @@ function AssetDetailPanel({ assetId, onClose }) {
|
|
|
333
330
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
334
331
|
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75, mb: 1 }, children: [
|
|
335
332
|
/* @__PURE__ */ jsx(Inventory2Icon, { sx: { fontSize: "0.85rem", color: "#8B5CF6" } }),
|
|
336
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", fontWeight: 600, children: t("assetDetailPanel.bundleContents", {
|
|
333
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", fontWeight: 600, children: t("assetDetailPanel.bundleContents", { total: String(asset.items.length) }) })
|
|
337
334
|
] }),
|
|
338
335
|
/* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.75 }, children: asset.items.map((item, idx) => /* @__PURE__ */ jsx(
|
|
339
336
|
Box,
|