Improve Directory pages.

This commit is contained in:
2026-05-25 22:29:47 +00:00
parent 658c7ab24c
commit a533082388
4 changed files with 19 additions and 35 deletions

View File

@@ -428,8 +428,8 @@ func (api *API) AppsGetAvailableReadme(w http.ResponseWriter, r *http.Request) {
return
}
readmePath := filepath.Join(api.appsDir, appName, "README.md")
content, err := os.ReadFile(readmePath)
appsMgr := apps.NewManager(api.dataDir, api.appsDir)
content, err := appsMgr.GetCatalogReadme(appName)
if err != nil {
if os.IsNotExist(err) {
respondError(w, http.StatusNotFound, fmt.Sprintf("README not found for app '%s'", appName))

View File

@@ -1501,6 +1501,20 @@ func (m *Manager) GetEnhancedStatus(instanceName, appName string) (*RuntimeStatu
return m.getRuntimeStatus(kubeconfigPath, namespace)
}
// GetCatalogReadme returns the README.md content for an available app from the catalog directory.
func (m *Manager) GetCatalogReadme(appName string) ([]byte, error) {
if m.appsDir == "" {
return nil, fmt.Errorf("apps directory not configured")
}
appDir, _, err := m.resolveAppDir(appName, "")
if err != nil {
return nil, err
}
return os.ReadFile(filepath.Join(appDir, "README.md"))
}
// GetAppManifest reads and parses the manifest.yaml for an app from the apps directory
func (m *Manager) GetAppManifest(appName string) (*AppManifest, error) {
if m.appsDir == "" {

View File

@@ -201,10 +201,6 @@ export function AppsComponent({ infrastructureOnly = false }: AppsComponentProps
const hasInfraApps = installedApps.some(app => app.category === 'infrastructure');
// Running count scoped to this view's filtered apps
const runningApps = baseApps
.filter(app => app.deploymentStatus === 'deployed' && liveStatuses[app.name] === 'running').length;
if (!currentInstance) {
return (
<Card className="p-8 text-center">
@@ -247,7 +243,7 @@ export function AppsComponent({ infrastructureOnly = false }: AppsComponentProps
</div>
<div className="flex gap-2">
{!infrastructureOnly && (
<Button variant="outline" asChild>
<Button asChild>
<Link to={`/instances/${currentInstance}/app-directory`}>
<LayoutGrid className="h-4 w-4 mr-2" />
Browse Directory
@@ -299,16 +295,6 @@ export function AppsComponent({ infrastructureOnly = false }: AppsComponentProps
)}
</div>
<div className="text-sm text-muted-foreground">
{isLoading ? (
<span className="flex items-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
Loading...
</span>
) : (
`${runningApps} running · ${baseApps.length} installed`
)}
</div>
</Card>
{isLoading ? (

View File

@@ -20,7 +20,7 @@ import {
Settings,
} from 'lucide-react';
import { useInstanceContext } from '../../hooks/useInstanceContext';
import { useAvailableApps, useDeployedApps, useAppStatuses } from '../../hooks/useApps';
import { useAvailableApps, useDeployedApps } from '../../hooks/useApps';
import { useSetupStatus } from '../../services/api';
import { usePageHelp } from '../../hooks/usePageHelp';
import { ErrorBoundary } from '../../components';
@@ -135,12 +135,6 @@ function AppDirectoryContent() {
appCategories.sort();
const categories = infraOnly ? ['infrastructure'] : ['all', ...appCategories];
// Stats
const installedApps = applications.filter(a => a.deploymentStatus);
const deployedAppNames = installedApps.filter(a => a.deploymentStatus === 'deployed').map(a => a.name);
const liveStatuses = useAppStatuses(currentInstance, deployedAppNames);
const runningApps = deployedAppNames.filter(name => liveStatuses[name] === 'running').length;
// Filter
const sortedApps = [...applications].sort((a, b) => a.name.localeCompare(b.name));
const filteredApps = sortedApps.filter(app => {
@@ -218,17 +212,7 @@ function AppDirectoryContent() {
</div>
</div>
<div className="flex items-center justify-between">
<div className="text-sm text-muted-foreground">
{isLoading ? (
<span className="flex items-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
Loading apps...
</span>
) : (
`${runningApps} running · ${installedApps.length} installed · ${applications.length} in directory`
)}
</div>
<div className="flex items-center justify-end">
<Button
variant={hideInstalled ? 'default' : 'outline'}
size="sm"