@nospt/plugin-dev-ai-hub 0.2.2 → 0.2.3

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.
@@ -1,9 +1,8 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useState, useMemo } from 'react';
3
3
  import { useSearchParams } from 'react-router-dom';
4
- import { Flex, Text, Box, Skeleton, TablePagination } from '@backstage/ui';
4
+ import { Box, Text, Skeleton, Flex, TablePagination } from '@backstage/ui';
5
5
  import { RiArticleLine, RiRobot2Line, RiToolsLine, RiGitBranchLine } from '@remixicon/react';
6
- import SmartToyIcon from '@mui/icons-material/SmartToy';
7
6
  import { AssetCard } from '../AssetCard/AssetCard.esm.js';
8
7
  import { AssetFilters } from '../AssetFilters/AssetFilters.esm.js';
9
8
  import { AssetDetailPanel } from '../AssetDetailPanel/AssetDetailPanel.esm.js';
@@ -102,10 +101,6 @@ function DevAiHubPage() {
102
101
  return Array.from(tagSet).sort();
103
102
  }, [result]);
104
103
  return /* @__PURE__ */ jsxs("div", { className: styles.pageRoot, children: [
105
- /* @__PURE__ */ jsx("div", { className: styles.pageHeader, children: /* @__PURE__ */ jsxs(Flex, { gap: "3", align: "center", children: [
106
- /* @__PURE__ */ jsx(SmartToyIcon, { className: styles.pageHeaderIcon }),
107
- /* @__PURE__ */ jsx(Text, { variant: "title-large", weight: "bold", children: "Dev AI Hub" })
108
- ] }) }),
109
104
  /* @__PURE__ */ jsxs("div", { className: styles.content, children: [
110
105
  /* @__PURE__ */ jsx("div", { className: styles.statsGrid, children: STATS_CONFIG.map(({ key, label, Icon, gradient, shadow }) => {
111
106
  const isActive = filters.types[0] === key;
@@ -1 +1 @@
1
- {"version":3,"file":"DevAiHubPage.esm.js","sources":["../../../src/components/DevAiHubPage/DevAiHubPage.tsx"],"sourcesContent":["import { useState, useMemo, type ElementType } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Box, Flex, Text, Skeleton, TablePagination } from '@backstage/ui';\nimport { RiArticleLine, RiRobot2Line, RiToolsLine, RiGitBranchLine } from '@remixicon/react';\nimport SmartToyIcon from '@mui/icons-material/SmartToy';\nimport type { AssetType, AiTool } from '@nospt/plugin-dev-ai-hub-common';\nimport { AssetCard } from '../AssetCard';\nimport { AssetFilters } from '../AssetFilters';\nimport type { AssetFiltersValue } from '../AssetFilters';\nimport { AssetDetailPanel } from '../AssetDetailPanel';\nimport { AssetInstallDialog } from '../AssetInstallDialog';\nimport { useAssets, useStats, useProviders } from '../../hooks';\nimport styles from './DevAiHubPage.module.css';\n\nconst DEFAULT_FILTERS: AssetFiltersValue = {\n types: [],\n tools: [],\n search: '',\n tags: [],\n providerId: undefined,\n};\n\nconst PAGE_SIZE = 24;\n\nconst STATS_CONFIG: { key: AssetType; label: string; Icon: ElementType; gradient: string; shadow: string }[] = [\n { key: 'instruction', label: 'Instructions', Icon: RiArticleLine,\n gradient: 'linear-gradient(135deg, #54A0FF 0%, #2980FF 100%)', shadow: '#54A0FF40' },\n { key: 'agent', label: 'Agents', Icon: RiRobot2Line,\n gradient: 'linear-gradient(135deg, #FF6B9D 0%, #E0507A 100%)', shadow: '#FF6B9D40' },\n { key: 'skill', label: 'Skills', Icon: RiToolsLine,\n gradient: 'linear-gradient(135deg, #6AB04C 0%, #4A8F2E 100%)', shadow: '#6AB04C40' },\n { key: 'workflow', label: 'Workflows', Icon: RiGitBranchLine,\n gradient: 'linear-gradient(135deg, #F9CA24 0%, #D4A800 100%)', shadow: '#F9CA2440' },\n];\n\nexport function DevAiHubPage() {\n const [filters, setFilters] = useState<AssetFiltersValue>(DEFAULT_FILTERS);\n const [page, setPage] = useState(1);\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedAssetId = searchParams.get('assetId');\n const installAssetId = searchParams.get('installId');\n\n const handleViewAsset = (id: string) =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.set('assetId', id); return n; });\n\n const handleCloseDetail = () =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.delete('assetId'); return n; });\n\n const handleInstallAsset = (id: string) =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.set('installId', id); return n; });\n\n const handleCloseInstall = () =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.delete('installId'); return n; });\n\n const { stats } = useStats();\n const { providers } = useProviders();\n\n const apiFilter = useMemo(\n () => ({\n type: filters.types.length === 1 ? (filters.types[0] as AssetType) : undefined,\n tool: filters.tools.length === 1 ? (filters.tools[0] as AiTool) : undefined,\n search: filters.search || undefined,\n tags: filters.tags.length > 0 ? filters.tags : undefined,\n providerId: filters.providerId || undefined,\n page,\n pageSize: PAGE_SIZE,\n }),\n [filters, page],\n );\n\n const { result, loading } = useAssets(apiFilter);\n\n const handleFiltersChange = (next: AssetFiltersValue) => {\n setFilters(next);\n setPage(1);\n };\n\n const totalPages = result ? Math.ceil(result.totalCount / PAGE_SIZE) : 0;\n\n const availableTags = useMemo(() => {\n if (!result) return [];\n const tagSet = new Set<string>();\n result.items.forEach(a => a.tags.forEach(t => tagSet.add(t)));\n return Array.from(tagSet).sort();\n }, [result]);\n\n return (\n <div className={styles.pageRoot}>\n <div className={styles.pageHeader}>\n <Flex gap=\"3\" align=\"center\">\n <SmartToyIcon className={styles.pageHeaderIcon} />\n <Text variant=\"title-large\" weight=\"bold\">Dev AI Hub</Text>\n </Flex>\n </div>\n <div className={styles.content}>\n {/* Stats row */}\n <div className={styles.statsGrid}>\n {STATS_CONFIG.map(({ key, label, Icon, gradient, shadow }) => {\n const isActive = filters.types[0] === key;\n return (\n <div\n key={key}\n className={styles.statCard}\n onClick={() => handleFiltersChange({ ...filters, types: isActive ? [] : [key] })}\n style={{\n background: gradient,\n boxShadow: isActive ? `0 8px 24px ${shadow}` : `0 2px 8px ${shadow}`,\n transform: isActive ? 'translateY(-2px)' : 'none',\n outline: isActive ? '2px solid rgba(255,255,255,0.6)' : 'none',\n outlineOffset: 2,\n }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={e => { if (e.key === 'Enter') handleFiltersChange({ ...filters, types: isActive ? [] : [key] }); }}\n >\n <div className={styles.statCardInner}>\n <Box>\n <Text variant=\"title-large\" weight=\"bold\" className={styles.statValue}>\n {stats ? (stats.byType[key] ?? 0) : <Skeleton style={{ width: 32 }} />}\n </Text>\n <Text variant=\"body-small\" className={styles.statLabel}>\n {label}\n </Text>\n </Box>\n <div className={styles.statIconBox}>\n <Icon size={22} style={{ color: '#fff' }} />\n </div>\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Filters */}\n <AssetFilters\n value={filters}\n onChange={handleFiltersChange}\n availableTags={availableTags}\n providers={providers.length > 1 ? providers : undefined}\n />\n\n {/* Results summary */}\n {result && !loading && (\n <Text variant=\"body-x-small\" color=\"secondary\" style={{ marginBottom: 'var(--bui-space-4)', display: 'block' }}>\n {result.totalCount} asset{result.totalCount !== 1 ? 's' : ''} found\n </Text>\n )}\n\n {/* Asset grid — 4 columns on large screens */}\n <div className={styles.assetGrid}>\n {loading\n ? Array.from({ length: 8 }).map((_, i) => (\n <Skeleton key={i} style={{ height: 150, borderRadius: 'var(--bui-radius-2)' }} />\n ))\n : result?.items.map(asset => (\n <AssetCard\n key={asset.id}\n asset={asset}\n onView={handleViewAsset}\n onInstall={handleInstallAsset}\n />\n ))}\n </div>\n\n {/* Empty state */}\n {!loading && result?.items.length === 0 && (\n <div className={styles.emptyState}>\n <div className={styles.emptyEmoji}>🤖</div>\n <Text variant=\"title-small\" color=\"secondary\" weight=\"bold\">No assets found</Text>\n <Text variant=\"body-small\" color=\"secondary\" style={{ marginTop: 'var(--bui-space-1)' }}>\n Try adjusting your filters or search terms.\n </Text>\n </div>\n )}\n\n {/* Pagination */}\n {totalPages > 1 && (\n <Flex className={styles.paginationRow}>\n <TablePagination\n pageSize={PAGE_SIZE}\n offset={(page - 1) * PAGE_SIZE}\n totalCount={result?.totalCount ?? 0}\n hasNextPage={page < totalPages}\n hasPreviousPage={page > 1}\n onNextPage={() => setPage(p => p + 1)}\n onPreviousPage={() => setPage(p => p - 1)}\n />\n </Flex>\n )}\n </div>\n\n <AssetDetailPanel\n assetId={selectedAssetId}\n onClose={handleCloseDetail}\n />\n\n <AssetInstallDialog\n assetId={installAssetId}\n onClose={handleCloseInstall}\n />\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAcA,MAAM,eAAA,GAAqC;AAAA,EACzC,OAAO,EAAC;AAAA,EACR,OAAO,EAAC;AAAA,EACR,MAAA,EAAQ,EAAA;AAAA,EACR,MAAM,EAAC;AAAA,EACP,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,SAAA,GAAY,EAAA;AAElB,MAAM,YAAA,GAAyG;AAAA,EAC7G;AAAA,IAAE,GAAA,EAAK,aAAA;AAAA,IAAe,KAAA,EAAO,cAAA;AAAA,IAAgB,IAAA,EAAM,aAAA;AAAA,IACjD,QAAA,EAAU,mDAAA;AAAA,IAAqD,MAAA,EAAQ;AAAA,GAAY;AAAA,EACrF;AAAA,IAAE,GAAA,EAAK,OAAA;AAAA,IAAe,KAAA,EAAO,QAAA;AAAA,IAAgB,IAAA,EAAM,YAAA;AAAA,IACjD,QAAA,EAAU,mDAAA;AAAA,IAAqD,MAAA,EAAQ;AAAA,GAAY;AAAA,EACrF;AAAA,IAAE,GAAA,EAAK,OAAA;AAAA,IAAe,KAAA,EAAO,QAAA;AAAA,IAAgB,IAAA,EAAM,WAAA;AAAA,IACjD,QAAA,EAAU,mDAAA;AAAA,IAAqD,MAAA,EAAQ;AAAA,GAAY;AAAA,EACrF;AAAA,IAAE,GAAA,EAAK,UAAA;AAAA,IAAe,KAAA,EAAO,WAAA;AAAA,IAAgB,IAAA,EAAM,eAAA;AAAA,IACjD,QAAA,EAAU,mDAAA;AAAA,IAAqD,MAAA,EAAQ;AAAA;AAC3E,CAAA;AAEO,SAAS,YAAA,GAAe;AAC7B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAA4B,eAAe,CAAA;AACzE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAElC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,eAAA,EAAgB;AACxD,EAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,GAAA,CAAI,SAAS,CAAA;AAClD,EAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AAEnD,EAAA,MAAM,eAAA,GAAkB,CAAC,EAAA,KACvB,eAAA,CAAgB,CAAA,CAAA,KAAK;AAAE,IAAA,MAAM,CAAA,GAAI,IAAI,eAAA,CAAgB,CAAC,CAAA;AAAG,IAAA,CAAA,CAAE,GAAA,CAAI,WAAW,EAAE,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAAG,CAAC,CAAA;AAE5F,EAAA,MAAM,iBAAA,GAAoB,MACxB,eAAA,CAAgB,CAAA,CAAA,KAAK;AAAE,IAAA,MAAM,CAAA,GAAI,IAAI,eAAA,CAAgB,CAAC,CAAA;AAAG,IAAA,CAAA,CAAE,OAAO,SAAS,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAAG,CAAC,CAAA;AAE3F,EAAA,MAAM,kBAAA,GAAqB,CAAC,EAAA,KAC1B,eAAA,CAAgB,CAAA,CAAA,KAAK;AAAE,IAAA,MAAM,CAAA,GAAI,IAAI,eAAA,CAAgB,CAAC,CAAA;AAAG,IAAA,CAAA,CAAE,GAAA,CAAI,aAAa,EAAE,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAAG,CAAC,CAAA;AAE9F,EAAA,MAAM,kBAAA,GAAqB,MACzB,eAAA,CAAgB,CAAA,CAAA,KAAK;AAAE,IAAA,MAAM,CAAA,GAAI,IAAI,eAAA,CAAgB,CAAC,CAAA;AAAG,IAAA,CAAA,CAAE,OAAO,WAAW,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAAG,CAAC,CAAA;AAE7F,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,QAAA,EAAS;AAC3B,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,YAAA,EAAa;AAEnC,EAAA,MAAM,SAAA,GAAY,OAAA;AAAA,IAChB,OAAO;AAAA,MACL,IAAA,EAAM,QAAQ,KAAA,CAAM,MAAA,KAAW,IAAK,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,GAAkB,MAAA;AAAA,MACrE,IAAA,EAAM,QAAQ,KAAA,CAAM,MAAA,KAAW,IAAK,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,GAAe,MAAA;AAAA,MAClE,MAAA,EAAQ,QAAQ,MAAA,IAAU,MAAA;AAAA,MAC1B,MAAM,OAAA,CAAQ,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,QAAQ,IAAA,GAAO,MAAA;AAAA,MAC/C,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;AAAA,MAClC,IAAA;AAAA,MACA,QAAA,EAAU;AAAA,KACZ,CAAA;AAAA,IACA,CAAC,SAAS,IAAI;AAAA,GAChB;AAEA,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAQ,GAAI,UAAU,SAAS,CAAA;AAE/C,EAAA,MAAM,mBAAA,GAAsB,CAAC,IAAA,KAA4B;AACvD,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,EACX,CAAA;AAEA,EAAA,MAAM,aAAa,MAAA,GAAS,IAAA,CAAK,KAAK,MAAA,CAAO,UAAA,GAAa,SAAS,CAAA,GAAI,CAAA;AAEvE,EAAA,MAAM,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AACrB,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,IAAA,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,CAAK,OAAA,CAAQ,CAAA,CAAA,KAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAC,CAAC,CAAA;AAC5D,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,CAAE,IAAA,EAAK;AAAA,EACjC,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,QAAA,EACrB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAW,MAAA,CAAO,UAAA,EACrB,+BAAC,IAAA,EAAA,EAAK,GAAA,EAAI,GAAA,EAAI,KAAA,EAAM,QAAA,EAClB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAW,MAAA,CAAO,cAAA,EAAgB,CAAA;AAAA,0BAC/C,IAAA,EAAA,EAAK,OAAA,EAAQ,aAAA,EAAc,MAAA,EAAO,QAAO,QAAA,EAAA,YAAA,EAAU;AAAA,KAAA,EACtD,CAAA,EACF,CAAA;AAAA,oBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,OAAA,EAErB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,SAAA,EACpB,QAAA,EAAA,YAAA,CAAa,GAAA,CAAI,CAAC,EAAE,GAAA,EAAK,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,QAAO,KAAM;AAC5D,QAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,KAAM,GAAA;AACtC,QAAA,uBACE,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YAEC,WAAW,MAAA,CAAO,QAAA;AAAA,YAClB,OAAA,EAAS,MAAM,mBAAA,CAAoB,EAAE,GAAG,OAAA,EAAS,KAAA,EAAO,QAAA,GAAW,EAAC,GAAI,CAAC,GAAG,GAAG,CAAA;AAAA,YAC/E,KAAA,EAAO;AAAA,cACL,UAAA,EAAY,QAAA;AAAA,cACZ,WAAW,QAAA,GAAW,CAAA,WAAA,EAAc,MAAM,CAAA,CAAA,GAAK,aAAa,MAAM,CAAA,CAAA;AAAA,cAClE,SAAA,EAAW,WAAW,kBAAA,GAAqB,MAAA;AAAA,cAC3C,OAAA,EAAS,WAAW,iCAAA,GAAoC,MAAA;AAAA,cACxD,aAAA,EAAe;AAAA,aACjB;AAAA,YACA,IAAA,EAAK,QAAA;AAAA,YACL,QAAA,EAAU,CAAA;AAAA,YACV,WAAW,CAAA,CAAA,KAAK;AAAE,cAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,OAAA,EAAS,mBAAA,CAAoB,EAAE,GAAG,OAAA,EAAS,KAAA,EAAO,QAAA,GAAW,EAAC,GAAI,CAAC,GAAG,GAAG,CAAA;AAAA,YAAG,CAAA;AAAA,YAE5G,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,aAAA,EACrB,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAQ,aAAA,EAAc,MAAA,EAAO,QAAO,SAAA,EAAW,MAAA,CAAO,WACzD,QAAA,EAAA,KAAA,GAAS,KAAA,CAAM,OAAO,GAAG,CAAA,IAAK,oBAAK,GAAA,CAAC,QAAA,EAAA,EAAS,OAAO,EAAE,KAAA,EAAO,EAAA,EAAG,EAAG,CAAA,EACtE,CAAA;AAAA,oCACC,IAAA,EAAA,EAAK,OAAA,EAAQ,cAAa,SAAA,EAAW,MAAA,CAAO,WAC1C,QAAA,EAAA,KAAA,EACH;AAAA,eAAA,EACF,CAAA;AAAA,8BACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,aACrB,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,IAAU,CAAA,EAC5C;AAAA,aAAA,EACF;AAAA,WAAA;AAAA,UA1BK;AAAA,SA2BP;AAAA,MAEJ,CAAC,CAAA,EACH,CAAA;AAAA,sBAGA,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,OAAA;AAAA,UACP,QAAA,EAAU,mBAAA;AAAA,UACV,aAAA;AAAA,UACA,SAAA,EAAW,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,SAAA,GAAY;AAAA;AAAA,OAChD;AAAA,MAGC,MAAA,IAAU,CAAC,OAAA,oBACV,IAAA,CAAC,QAAK,OAAA,EAAQ,cAAA,EAAe,KAAA,EAAM,WAAA,EAAY,OAAO,EAAE,YAAA,EAAc,oBAAA,EAAsB,OAAA,EAAS,SAAQ,EAC1G,QAAA,EAAA;AAAA,QAAA,MAAA,CAAO,UAAA;AAAA,QAAW,QAAA;AAAA,QAAO,MAAA,CAAO,UAAA,KAAe,CAAA,GAAI,GAAA,GAAM,EAAA;AAAA,QAAG;AAAA,OAAA,EAC/D,CAAA;AAAA,sBAIF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,WACpB,QAAA,EAAA,OAAA,GACG,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA,EAAG,CAAA,CAAE,IAAI,CAAC,CAAA,EAAG,CAAA,qBAChC,GAAA,CAAC,QAAA,EAAA,EAAiB,KAAA,EAAO,EAAE,MAAA,EAAQ,KAAK,YAAA,EAAc,qBAAA,EAAsB,EAAA,EAA7D,CAAgE,CAChF,CAAA,GACD,MAAA,EAAQ,KAAA,CAAM,IAAI,CAAA,KAAA,qBAChB,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UAEC,KAAA;AAAA,UACA,MAAA,EAAQ,eAAA;AAAA,UACR,SAAA,EAAW;AAAA,SAAA;AAAA,QAHN,KAAA,CAAM;AAAA,OAKd,CAAA,EACP,CAAA;AAAA,MAGC,CAAC,OAAA,IAAW,MAAA,EAAQ,KAAA,CAAM,MAAA,KAAW,qBACpC,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,UAAA,EACrB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,UAAA,EAAY,QAAA,EAAA,WAAA,EAAE,CAAA;AAAA,wBACrC,GAAA,CAAC,QAAK,OAAA,EAAQ,aAAA,EAAc,OAAM,WAAA,EAAY,MAAA,EAAO,QAAO,QAAA,EAAA,iBAAA,EAAe,CAAA;AAAA,wBAC3E,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EAAa,KAAA,EAAM,WAAA,EAAY,KAAA,EAAO,EAAE,SAAA,EAAW,oBAAA,EAAqB,EAAG,QAAA,EAAA,6CAAA,EAEzF;AAAA,OAAA,EACF,CAAA;AAAA,MAID,aAAa,CAAA,oBACZ,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,OAAO,aAAA,EACtB,QAAA,kBAAA,GAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,QAAA,EAAU,SAAA;AAAA,UACV,MAAA,EAAA,CAAS,OAAO,CAAA,IAAK,SAAA;AAAA,UACrB,UAAA,EAAY,QAAQ,UAAA,IAAc,CAAA;AAAA,UAClC,aAAa,IAAA,GAAO,UAAA;AAAA,UACpB,iBAAiB,IAAA,GAAO,CAAA;AAAA,UACxB,UAAA,EAAY,MAAM,OAAA,CAAQ,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA;AAAA,UACpC,cAAA,EAAgB,MAAM,OAAA,CAAQ,CAAA,CAAA,KAAK,IAAI,CAAC;AAAA;AAAA,OAC1C,EACF;AAAA,KAAA,EAEJ,CAAA;AAAA,oBAEA,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,eAAA;AAAA,QACT,OAAA,EAAS;AAAA;AAAA,KACX;AAAA,oBAEA,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,cAAA;AAAA,QACT,OAAA,EAAS;AAAA;AAAA;AACX,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"DevAiHubPage.esm.js","sources":["../../../src/components/DevAiHubPage/DevAiHubPage.tsx"],"sourcesContent":["import { useState, useMemo, type ElementType } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Box, Flex, Text, Skeleton, TablePagination } from '@backstage/ui';\nimport { RiArticleLine, RiRobot2Line, RiToolsLine, RiGitBranchLine } from '@remixicon/react';\nimport type { AssetType, AiTool } from '@nospt/plugin-dev-ai-hub-common';\nimport { AssetCard } from '../AssetCard';\nimport { AssetFilters } from '../AssetFilters';\nimport type { AssetFiltersValue } from '../AssetFilters';\nimport { AssetDetailPanel } from '../AssetDetailPanel';\nimport { AssetInstallDialog } from '../AssetInstallDialog';\nimport { useAssets, useStats, useProviders } from '../../hooks';\nimport styles from './DevAiHubPage.module.css';\n\nconst DEFAULT_FILTERS: AssetFiltersValue = {\n types: [],\n tools: [],\n search: '',\n tags: [],\n providerId: undefined,\n};\n\nconst PAGE_SIZE = 24;\n\nconst STATS_CONFIG: { key: AssetType; label: string; Icon: ElementType; gradient: string; shadow: string }[] = [\n { key: 'instruction', label: 'Instructions', Icon: RiArticleLine,\n gradient: 'linear-gradient(135deg, #54A0FF 0%, #2980FF 100%)', shadow: '#54A0FF40' },\n { key: 'agent', label: 'Agents', Icon: RiRobot2Line,\n gradient: 'linear-gradient(135deg, #FF6B9D 0%, #E0507A 100%)', shadow: '#FF6B9D40' },\n { key: 'skill', label: 'Skills', Icon: RiToolsLine,\n gradient: 'linear-gradient(135deg, #6AB04C 0%, #4A8F2E 100%)', shadow: '#6AB04C40' },\n { key: 'workflow', label: 'Workflows', Icon: RiGitBranchLine,\n gradient: 'linear-gradient(135deg, #F9CA24 0%, #D4A800 100%)', shadow: '#F9CA2440' },\n];\n\nexport function DevAiHubPage() {\n const [filters, setFilters] = useState<AssetFiltersValue>(DEFAULT_FILTERS);\n const [page, setPage] = useState(1);\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedAssetId = searchParams.get('assetId');\n const installAssetId = searchParams.get('installId');\n\n const handleViewAsset = (id: string) =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.set('assetId', id); return n; });\n\n const handleCloseDetail = () =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.delete('assetId'); return n; });\n\n const handleInstallAsset = (id: string) =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.set('installId', id); return n; });\n\n const handleCloseInstall = () =>\n setSearchParams(p => { const n = new URLSearchParams(p); n.delete('installId'); return n; });\n\n const { stats } = useStats();\n const { providers } = useProviders();\n\n const apiFilter = useMemo(\n () => ({\n type: filters.types.length === 1 ? (filters.types[0] as AssetType) : undefined,\n tool: filters.tools.length === 1 ? (filters.tools[0] as AiTool) : undefined,\n search: filters.search || undefined,\n tags: filters.tags.length > 0 ? filters.tags : undefined,\n providerId: filters.providerId || undefined,\n page,\n pageSize: PAGE_SIZE,\n }),\n [filters, page],\n );\n\n const { result, loading } = useAssets(apiFilter);\n\n const handleFiltersChange = (next: AssetFiltersValue) => {\n setFilters(next);\n setPage(1);\n };\n\n const totalPages = result ? Math.ceil(result.totalCount / PAGE_SIZE) : 0;\n\n const availableTags = useMemo(() => {\n if (!result) return [];\n const tagSet = new Set<string>();\n result.items.forEach(a => a.tags.forEach(t => tagSet.add(t)));\n return Array.from(tagSet).sort();\n }, [result]);\n\n return (\n <div className={styles.pageRoot}>\n <div className={styles.content}>\n {/* Stats row */}\n <div className={styles.statsGrid}>\n {STATS_CONFIG.map(({ key, label, Icon, gradient, shadow }) => {\n const isActive = filters.types[0] === key;\n return (\n <div\n key={key}\n className={styles.statCard}\n onClick={() => handleFiltersChange({ ...filters, types: isActive ? [] : [key] })}\n style={{\n background: gradient,\n boxShadow: isActive ? `0 8px 24px ${shadow}` : `0 2px 8px ${shadow}`,\n transform: isActive ? 'translateY(-2px)' : 'none',\n outline: isActive ? '2px solid rgba(255,255,255,0.6)' : 'none',\n outlineOffset: 2,\n }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={e => { if (e.key === 'Enter') handleFiltersChange({ ...filters, types: isActive ? [] : [key] }); }}\n >\n <div className={styles.statCardInner}>\n <Box>\n <Text variant=\"title-large\" weight=\"bold\" className={styles.statValue}>\n {stats ? (stats.byType[key] ?? 0) : <Skeleton style={{ width: 32 }} />}\n </Text>\n <Text variant=\"body-small\" className={styles.statLabel}>\n {label}\n </Text>\n </Box>\n <div className={styles.statIconBox}>\n <Icon size={22} style={{ color: '#fff' }} />\n </div>\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Filters */}\n <AssetFilters\n value={filters}\n onChange={handleFiltersChange}\n availableTags={availableTags}\n providers={providers.length > 1 ? providers : undefined}\n />\n\n {/* Results summary */}\n {result && !loading && (\n <Text variant=\"body-x-small\" color=\"secondary\" style={{ marginBottom: 'var(--bui-space-4)', display: 'block' }}>\n {result.totalCount} asset{result.totalCount !== 1 ? 's' : ''} found\n </Text>\n )}\n\n {/* Asset grid — 4 columns on large screens */}\n <div className={styles.assetGrid}>\n {loading\n ? Array.from({ length: 8 }).map((_, i) => (\n <Skeleton key={i} style={{ height: 150, borderRadius: 'var(--bui-radius-2)' }} />\n ))\n : result?.items.map(asset => (\n <AssetCard\n key={asset.id}\n asset={asset}\n onView={handleViewAsset}\n onInstall={handleInstallAsset}\n />\n ))}\n </div>\n\n {/* Empty state */}\n {!loading && result?.items.length === 0 && (\n <div className={styles.emptyState}>\n <div className={styles.emptyEmoji}>🤖</div>\n <Text variant=\"title-small\" color=\"secondary\" weight=\"bold\">No assets found</Text>\n <Text variant=\"body-small\" color=\"secondary\" style={{ marginTop: 'var(--bui-space-1)' }}>\n Try adjusting your filters or search terms.\n </Text>\n </div>\n )}\n\n {/* Pagination */}\n {totalPages > 1 && (\n <Flex className={styles.paginationRow}>\n <TablePagination\n pageSize={PAGE_SIZE}\n offset={(page - 1) * PAGE_SIZE}\n totalCount={result?.totalCount ?? 0}\n hasNextPage={page < totalPages}\n hasPreviousPage={page > 1}\n onNextPage={() => setPage(p => p + 1)}\n onPreviousPage={() => setPage(p => p - 1)}\n />\n </Flex>\n )}\n </div>\n\n <AssetDetailPanel\n assetId={selectedAssetId}\n onClose={handleCloseDetail}\n />\n\n <AssetInstallDialog\n assetId={installAssetId}\n onClose={handleCloseInstall}\n />\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
2
 
3
- var css_248z = "@layer components {\n .DevAiHubPage_pageRoot__dbf26b481d {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .DevAiHubPage_pageHeader__dbf26b481d {\n padding: var(--bui-space-6) var(--bui-space-6) 0;\n flex-shrink: 0;\n }\n\n .DevAiHubPage_pageHeaderIcon__dbf26b481d {\n font-size: 28px;\n opacity: 0.85;\n }\n\n .DevAiHubPage_content__dbf26b481d {\n flex: 1;\n padding: var(--bui-space-6);\n overflow-y: auto;\n }\n\n .DevAiHubPage_statsGrid__dbf26b481d {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--bui-space-4);\n margin-bottom: var(--bui-space-6);\n }\n\n @media (max-width: 600px) {\n .DevAiHubPage_statsGrid__dbf26b481d {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n .DevAiHubPage_statCard__dbf26b481d {\n border-radius: var(--bui-radius-3);\n padding: var(--bui-space-4);\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .DevAiHubPage_statCard__dbf26b481d:hover {\n transform: translateY(-2px);\n }\n\n .DevAiHubPage_statCardInner__dbf26b481d {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .DevAiHubPage_statValue__dbf26b481d {\n color: #fff;\n line-height: 1;\n }\n\n .DevAiHubPage_statLabel__dbf26b481d {\n color: rgba(255, 255, 255, 0.85);\n font-weight: 500;\n margin-top: var(--bui-space-1);\n }\n\n .DevAiHubPage_statIconBox__dbf26b481d {\n width: 40px;\n height: 40px;\n border-radius: var(--bui-radius-2);\n background-color: rgba(255, 255, 255, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .DevAiHubPage_assetGrid__dbf26b481d {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--bui-space-3);\n }\n\n @media (max-width: 1200px) {\n .DevAiHubPage_assetGrid__dbf26b481d {\n grid-template-columns: repeat(3, 1fr);\n }\n }\n\n @media (max-width: 900px) {\n .DevAiHubPage_assetGrid__dbf26b481d {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 600px) {\n .DevAiHubPage_assetGrid__dbf26b481d {\n grid-template-columns: 1fr;\n }\n }\n\n .DevAiHubPage_emptyState__dbf26b481d {\n padding: 96px 0;\n text-align: center;\n }\n\n .DevAiHubPage_emptyEmoji__dbf26b481d {\n margin-bottom: var(--bui-space-4);\n opacity: 0.15;\n font-size: 5rem;\n }\n\n .DevAiHubPage_paginationRow__dbf26b481d {\n display: flex;\n justify-content: center;\n margin-top: var(--bui-space-8);\n }\n}\n";
4
- var styles = {"pageRoot":"DevAiHubPage_pageRoot__dbf26b481d","pageHeader":"DevAiHubPage_pageHeader__dbf26b481d","pageHeaderIcon":"DevAiHubPage_pageHeaderIcon__dbf26b481d","content":"DevAiHubPage_content__dbf26b481d","statsGrid":"DevAiHubPage_statsGrid__dbf26b481d","statCard":"DevAiHubPage_statCard__dbf26b481d","statCardInner":"DevAiHubPage_statCardInner__dbf26b481d","statValue":"DevAiHubPage_statValue__dbf26b481d","statLabel":"DevAiHubPage_statLabel__dbf26b481d","statIconBox":"DevAiHubPage_statIconBox__dbf26b481d","assetGrid":"DevAiHubPage_assetGrid__dbf26b481d","emptyState":"DevAiHubPage_emptyState__dbf26b481d","emptyEmoji":"DevAiHubPage_emptyEmoji__dbf26b481d","paginationRow":"DevAiHubPage_paginationRow__dbf26b481d"};
3
+ var css_248z = "@layer components {\n .DevAiHubPage_pageRoot__58eb18b1eb {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .DevAiHubPage_content__58eb18b1eb {\n flex: 1;\n padding: var(--bui-space-6);\n overflow-y: auto;\n }\n\n .DevAiHubPage_statsGrid__58eb18b1eb {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--bui-space-4);\n margin-bottom: var(--bui-space-6);\n }\n\n @media (max-width: 600px) {\n .DevAiHubPage_statsGrid__58eb18b1eb {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n .DevAiHubPage_statCard__58eb18b1eb {\n border-radius: var(--bui-radius-3);\n padding: var(--bui-space-4);\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .DevAiHubPage_statCard__58eb18b1eb:hover {\n transform: translateY(-2px);\n }\n\n .DevAiHubPage_statCardInner__58eb18b1eb {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .DevAiHubPage_statValue__58eb18b1eb {\n color: #fff;\n line-height: 1;\n }\n\n .DevAiHubPage_statLabel__58eb18b1eb {\n color: rgba(255, 255, 255, 0.85);\n font-weight: 500;\n margin-top: var(--bui-space-1);\n }\n\n .DevAiHubPage_statIconBox__58eb18b1eb {\n width: 40px;\n height: 40px;\n border-radius: var(--bui-radius-2);\n background-color: rgba(255, 255, 255, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .DevAiHubPage_assetGrid__58eb18b1eb {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--bui-space-3);\n }\n\n @media (max-width: 1200px) {\n .DevAiHubPage_assetGrid__58eb18b1eb {\n grid-template-columns: repeat(3, 1fr);\n }\n }\n\n @media (max-width: 900px) {\n .DevAiHubPage_assetGrid__58eb18b1eb {\n grid-template-columns: repeat(2, 1fr);\n }\n }\n\n @media (max-width: 600px) {\n .DevAiHubPage_assetGrid__58eb18b1eb {\n grid-template-columns: 1fr;\n }\n }\n\n .DevAiHubPage_emptyState__58eb18b1eb {\n padding: 96px 0;\n text-align: center;\n }\n\n .DevAiHubPage_emptyEmoji__58eb18b1eb {\n margin-bottom: var(--bui-space-4);\n opacity: 0.15;\n font-size: 5rem;\n }\n\n .DevAiHubPage_paginationRow__58eb18b1eb {\n display: flex;\n justify-content: center;\n margin-top: var(--bui-space-8);\n }\n}\n";
4
+ var styles = {"pageRoot":"DevAiHubPage_pageRoot__58eb18b1eb","content":"DevAiHubPage_content__58eb18b1eb","statsGrid":"DevAiHubPage_statsGrid__58eb18b1eb","statCard":"DevAiHubPage_statCard__58eb18b1eb","statCardInner":"DevAiHubPage_statCardInner__58eb18b1eb","statValue":"DevAiHubPage_statValue__58eb18b1eb","statLabel":"DevAiHubPage_statLabel__58eb18b1eb","statIconBox":"DevAiHubPage_statIconBox__58eb18b1eb","assetGrid":"DevAiHubPage_assetGrid__58eb18b1eb","emptyState":"DevAiHubPage_emptyState__58eb18b1eb","emptyEmoji":"DevAiHubPage_emptyEmoji__58eb18b1eb","paginationRow":"DevAiHubPage_paginationRow__58eb18b1eb"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
package/dist/index.d.ts CHANGED
@@ -16,27 +16,6 @@ declare const devAiHubPlugin: _backstage_frontend_plugin_api.OverridableFrontend
16
16
  inputs: {};
17
17
  params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
18
18
  }>;
19
- "nav-item:dev-ai-hub": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
20
- kind: "nav-item";
21
- name: undefined;
22
- config: {
23
- title: string | undefined;
24
- };
25
- configInput: {
26
- title?: string | undefined;
27
- };
28
- output: _backstage_frontend_plugin_api.ExtensionDataRef<{
29
- title: string;
30
- icon: _backstage_frontend_plugin_api.IconComponent;
31
- routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
32
- }, "core.nav-item.target", {}>;
33
- inputs: {};
34
- params: {
35
- title: string;
36
- icon: _backstage_frontend_plugin_api.IconComponent;
37
- routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
38
- };
39
- }>;
40
19
  "page:dev-ai-hub": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
41
20
  kind: "page";
42
21
  name: undefined;
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createFrontendPlugin, ApiBlueprint, createApiFactory, fetchApiRef, discoveryApiRef, PageBlueprint, SubPageBlueprint, NavItemBlueprint } from '@backstage/frontend-plugin-api';
2
+ import { createFrontendPlugin, ApiBlueprint, createApiFactory, fetchApiRef, discoveryApiRef, PageBlueprint, SubPageBlueprint } from '@backstage/frontend-plugin-api';
3
3
  import SmartToyIcon from '@mui/icons-material/SmartToy';
4
4
  import { DevAiHubClient, devAiHubApiRef } from './api/DevAiHubClient.esm.js';
5
5
  import { mcpConfigRouteRef, rootRouteRef } from './routes.esm.js';
@@ -24,6 +24,7 @@ const devAiHubPlugin = createFrontendPlugin({
24
24
  params: {
25
25
  path: "/dev-ai-hub",
26
26
  title: "Dev AI Hub",
27
+ icon: /* @__PURE__ */ jsx(SmartToyIcon, {}),
27
28
  routeRef: rootRouteRef
28
29
  }
29
30
  }),
@@ -43,13 +44,6 @@ const devAiHubPlugin = createFrontendPlugin({
43
44
  routeRef: mcpConfigRouteRef,
44
45
  loader: () => import('./components/McpConfigPage/index.esm.js').then((m) => /* @__PURE__ */ jsx(m.McpConfigPage, {}))
45
46
  }
46
- }),
47
- NavItemBlueprint.make({
48
- params: {
49
- title: "AI Hub",
50
- routeRef: rootRouteRef,
51
- icon: SmartToyIcon
52
- }
53
47
  })
54
48
  ]
55
49
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n SubPageBlueprint,\n ApiBlueprint,\n NavItemBlueprint,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport SmartToyIcon from '@mui/icons-material/SmartToy';\nimport { devAiHubApiRef, DevAiHubClient } from './api/DevAiHubClient';\nimport { rootRouteRef, mcpConfigRouteRef } from './routes';\n\nexport const devAiHubPlugin = createFrontendPlugin({\n pluginId: 'dev-ai-hub',\n routes: {\n root: rootRouteRef,\n mcpConfig: mcpConfigRouteRef,\n },\n extensions: [\n ApiBlueprint.make({\n params: defineParams =>\n defineParams(\n createApiFactory({\n api: devAiHubApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new DevAiHubClient(discoveryApi, fetchApi),\n }),\n ),\n }),\n PageBlueprint.make({\n params: {\n path: '/dev-ai-hub',\n title: 'Dev AI Hub',\n routeRef: rootRouteRef,\n },\n }),\n SubPageBlueprint.make({\n name: 'browse',\n params: {\n path: 'browse',\n title: 'Browse',\n loader: () =>\n import('./components/DevAiHubPage').then(m => <m.DevAiHubPage />),\n },\n }),\n SubPageBlueprint.make({\n name: 'mcp-config',\n params: {\n path: 'mcp-config',\n title: 'Configure MCP',\n routeRef: mcpConfigRouteRef,\n loader: () =>\n import('./components/McpConfigPage').then(m => <m.McpConfigPage />),\n },\n }),\n NavItemBlueprint.make({\n params: {\n title: 'AI Hub',\n routeRef: rootRouteRef,\n icon: SmartToyIcon,\n },\n }),\n ],\n});\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,iBAAiB,oBAAA,CAAqB;AAAA,EACjD,QAAA,EAAU,YAAA;AAAA,EACV,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,SAAA,EAAW;AAAA,GACb;AAAA,EACA,UAAA,EAAY;AAAA,IACV,aAAa,IAAA,CAAK;AAAA,MAChB,QAAQ,CAAA,YAAA,KACN,YAAA;AAAA,QACE,gBAAA,CAAiB;AAAA,UACf,GAAA,EAAK,cAAA;AAAA,UACL,IAAA,EAAM,EAAE,YAAA,EAAc,eAAA,EAAiB,UAAU,WAAA,EAAY;AAAA,UAC7D,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,UAAS,KACjC,IAAI,cAAA,CAAe,YAAA,EAAc,QAAQ;AAAA,SAC5C;AAAA;AACH,KACH,CAAA;AAAA,IACD,cAAc,IAAA,CAAK;AAAA,MACjB,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,KAAA,EAAO,YAAA;AAAA,QACP,QAAA,EAAU;AAAA;AACZ,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,MAAA,EAAQ,MACN,OAAO,wCAA2B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,YAAA,EAAF,EAAe,CAAE;AAAA;AACpE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,YAAA;AAAA,QACN,KAAA,EAAO,eAAA;AAAA,QACP,QAAA,EAAU,iBAAA;AAAA,QACV,MAAA,EAAQ,MACN,OAAO,yCAA4B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,aAAA,EAAF,EAAgB,CAAE;AAAA;AACtE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,YAAA;AAAA,QACV,IAAA,EAAM;AAAA;AACR,KACD;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n SubPageBlueprint,\n ApiBlueprint,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport SmartToyIcon from '@mui/icons-material/SmartToy';\nimport { devAiHubApiRef, DevAiHubClient } from './api/DevAiHubClient';\nimport { rootRouteRef, mcpConfigRouteRef } from './routes';\n\nexport const devAiHubPlugin = createFrontendPlugin({\n pluginId: 'dev-ai-hub',\n routes: {\n root: rootRouteRef,\n mcpConfig: mcpConfigRouteRef,\n },\n extensions: [\n ApiBlueprint.make({\n params: defineParams =>\n defineParams(\n createApiFactory({\n api: devAiHubApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new DevAiHubClient(discoveryApi, fetchApi),\n }),\n ),\n }),\n PageBlueprint.make({\n params: {\n path: '/dev-ai-hub',\n title: 'Dev AI Hub',\n icon: <SmartToyIcon />,\n routeRef: rootRouteRef,\n },\n }),\n SubPageBlueprint.make({\n name: 'browse',\n params: {\n path: 'browse',\n title: 'Browse',\n loader: () =>\n import('./components/DevAiHubPage').then(m => <m.DevAiHubPage />),\n },\n }),\n SubPageBlueprint.make({\n name: 'mcp-config',\n params: {\n path: 'mcp-config',\n title: 'Configure MCP',\n routeRef: mcpConfigRouteRef,\n loader: () =>\n import('./components/McpConfigPage').then(m => <m.McpConfigPage />),\n },\n }),\n ],\n});\n"],"names":[],"mappings":";;;;;;AAaO,MAAM,iBAAiB,oBAAA,CAAqB;AAAA,EACjD,QAAA,EAAU,YAAA;AAAA,EACV,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,SAAA,EAAW;AAAA,GACb;AAAA,EACA,UAAA,EAAY;AAAA,IACV,aAAa,IAAA,CAAK;AAAA,MAChB,QAAQ,CAAA,YAAA,KACN,YAAA;AAAA,QACE,gBAAA,CAAiB;AAAA,UACf,GAAA,EAAK,cAAA;AAAA,UACL,IAAA,EAAM,EAAE,YAAA,EAAc,eAAA,EAAiB,UAAU,WAAA,EAAY;AAAA,UAC7D,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,UAAS,KACjC,IAAI,cAAA,CAAe,YAAA,EAAc,QAAQ;AAAA,SAC5C;AAAA;AACH,KACH,CAAA;AAAA,IACD,cAAc,IAAA,CAAK;AAAA,MACjB,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,KAAA,EAAO,YAAA;AAAA,QACP,IAAA,sBAAO,YAAA,EAAA,EAAa,CAAA;AAAA,QACpB,QAAA,EAAU;AAAA;AACZ,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,MAAA,EAAQ,MACN,OAAO,wCAA2B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,YAAA,EAAF,EAAe,CAAE;AAAA;AACpE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,YAAA;AAAA,QACN,KAAA,EAAO,eAAA;AAAA,QACP,QAAA,EAAU,iBAAA;AAAA,QACV,MAAA,EAAQ,MACN,OAAO,yCAA4B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,aAAA,EAAF,EAAgB,CAAE;AAAA;AACtE,KACD;AAAA;AAEL,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nospt/plugin-dev-ai-hub",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Frontend plugin for Dev AI Hub",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.esm.js",
@@ -58,7 +58,7 @@
58
58
  "@backstage/ui": "^0.14.3",
59
59
  "@mui/icons-material": "^5.15.0",
60
60
  "@mui/material": "^5.15.0",
61
- "@nospt/plugin-dev-ai-hub-common": "^0.2.2",
61
+ "@nospt/plugin-dev-ai-hub-common": "^0.2.3",
62
62
  "@remixicon/react": "^4.6.0",
63
63
  "react-markdown": "^9.0.0",
64
64
  "react-syntax-highlighter": "^16.1.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nospt/plugin-dev-ai-hub",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Frontend plugin for Dev AI Hub",
5
5
  "license": "Apache-2.0",
6
6
  "main": "src/index.ts",
@@ -5,16 +5,6 @@
5
5
  height: 100%;
6
6
  }
7
7
 
8
- .pageHeader {
9
- padding: var(--bui-space-6) var(--bui-space-6) 0;
10
- flex-shrink: 0;
11
- }
12
-
13
- .pageHeaderIcon {
14
- font-size: 28px;
15
- opacity: 0.85;
16
- }
17
-
18
8
  .content {
19
9
  flex: 1;
20
10
  padding: var(--bui-space-6);
@@ -2,7 +2,6 @@ import { useState, useMemo, type ElementType } from 'react';
2
2
  import { useSearchParams } from 'react-router-dom';
3
3
  import { Box, Flex, Text, Skeleton, TablePagination } from '@backstage/ui';
4
4
  import { RiArticleLine, RiRobot2Line, RiToolsLine, RiGitBranchLine } from '@remixicon/react';
5
- import SmartToyIcon from '@mui/icons-material/SmartToy';
6
5
  import type { AssetType, AiTool } from '@nospt/plugin-dev-ai-hub-common';
7
6
  import { AssetCard } from '../AssetCard';
8
7
  import { AssetFilters } from '../AssetFilters';
@@ -87,12 +86,6 @@ export function DevAiHubPage() {
87
86
 
88
87
  return (
89
88
  <div className={styles.pageRoot}>
90
- <div className={styles.pageHeader}>
91
- <Flex gap="3" align="center">
92
- <SmartToyIcon className={styles.pageHeaderIcon} />
93
- <Text variant="title-large" weight="bold">Dev AI Hub</Text>
94
- </Flex>
95
- </div>
96
89
  <div className={styles.content}>
97
90
  {/* Stats row */}
98
91
  <div className={styles.statsGrid}>
package/src/plugin.tsx CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  PageBlueprint,
4
4
  SubPageBlueprint,
5
5
  ApiBlueprint,
6
- NavItemBlueprint,
7
6
  createApiFactory,
8
7
  discoveryApiRef,
9
8
  fetchApiRef,
@@ -34,6 +33,7 @@ export const devAiHubPlugin = createFrontendPlugin({
34
33
  params: {
35
34
  path: '/dev-ai-hub',
36
35
  title: 'Dev AI Hub',
36
+ icon: <SmartToyIcon />,
37
37
  routeRef: rootRouteRef,
38
38
  },
39
39
  }),
@@ -56,12 +56,5 @@ export const devAiHubPlugin = createFrontendPlugin({
56
56
  import('./components/McpConfigPage').then(m => <m.McpConfigPage />),
57
57
  },
58
58
  }),
59
- NavItemBlueprint.make({
60
- params: {
61
- title: 'AI Hub',
62
- routeRef: rootRouteRef,
63
- icon: SmartToyIcon,
64
- },
65
- }),
66
59
  ],
67
60
  });