Skip to content

Commit 605fcb9

Browse files
author
colinmcneil
committed
Start on query migration
1 parent e6df7f3 commit 605fcb9

File tree

18 files changed

+126
-221
lines changed

18 files changed

+126
-221
lines changed

src/extension/ui/src/App.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState, Suspense } from 'react';
22
import { createDockerDesktopClient } from '@docker/extension-api-client';
33
import { Typography, Button, IconButton, Alert, DialogTitle, Dialog, DialogContent, CircularProgress, Paper, Box, SvgIcon, useTheme } from '@mui/material';
4-
import { CatalogItemWithName } from './types/catalog';
4+
import { CatalogItemRichened } from './types/catalog';
55
import { Close } from '@mui/icons-material';
66
import { CatalogGrid } from './components/CatalogGrid';
77
import { POLL_INTERVAL } from './Constants';
@@ -11,6 +11,7 @@ import { useCatalogAll } from './hooks/useCatalog';
1111
import { useRequiredImages } from './hooks/useRequiredImages';
1212
import { useMCPClient } from './hooks/useMCPClient';
1313
import { useConfig } from './hooks/useConfig';
14+
import { useSecrets } from './hooks/useSecrets';
1415

1516
export const client = createDockerDesktopClient();
1617

@@ -21,13 +22,14 @@ const DEFAULT_SETTINGS = {
2122

2223
export function App() {
2324
const [settings, setSettings] = useState<{ showModal: boolean, pollIntervalSeconds: number }>(localStorage.getItem('settings') ? JSON.parse(localStorage.getItem('settings') || '{}') : DEFAULT_SETTINGS);
24-
const [configuringItem, setConfiguringItem] = useState<CatalogItemWithName | null>(null);
25+
const [configuringItem, setConfiguringItem] = useState<CatalogItemRichened | null>(null);
2526

2627
// Use hooks directly in the component
2728
const catalogAll = useCatalogAll(client);
2829
const requiredImages = useRequiredImages(client);
2930
const mcpClient = useMCPClient(client);
3031
const config = useConfig(client);
32+
const secrets = useSecrets(client);
3133

3234
// Create a context-like combined props object to pass to children
3335
const appProps = {
@@ -44,10 +46,10 @@ export function App() {
4446
...config
4547
};
4648

47-
const isLoading = catalogAll.secretsLoading ||
48-
catalogAll.catalogLoading ||
49+
const isLoading = catalogAll.catalogLoading ||
4950
catalogAll.registryLoading ||
50-
requiredImages.isLoading;
51+
requiredImages.isLoading ||
52+
secrets.isLoading;
5153

5254
return (
5355
<>
File renamed without changes.

src/extension/ui/src/Registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { v1 } from "@docker/extension-api-client-types";
22
import { parse, stringify } from "yaml";
3-
import { readFileInPromptsVolume, writeFileToPromptsVolume } from "./FileWatcher";
3+
import { readFileInPromptsVolume, writeFileToPromptsVolume } from "./FileUtils";
44
import { mergeDeep } from "./MergeDeep";
55
import { ParsedParameters } from "./types/config";
66

src/extension/ui/src/Secrets.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// From secrets.yaml
22

33
import { v1 } from "@docker/extension-api-client-types";
4-
import { CatalogItemWithName } from "./types/catalog";
4+
import { CatalogItemRichened } from "./types/catalog";
55
import { Secret, StoredSecret, Policy } from "./types/secrets";
66

77
namespace Secrets {
@@ -55,12 +55,12 @@ namespace Secrets {
5555
}
5656

5757
// Get all relevant secrets for a given set of catalog items
58-
export function getAllSecretNames(catalogItems: CatalogItemWithName[]): string[] {
58+
export function getAllSecretNames(catalogItems: CatalogItemRichened[]): string[] {
5959
return catalogItems.map((item) => item.secrets || []).flat().map((secret) => secret.name);
6060
}
6161

6262
// Whether or not each secret has been assigned for a given catalog item
63-
export function getSecretsWithAssignment(catalogItem: CatalogItemWithName, secrets: Secret[]): { name: string, assigned: boolean }[] {
63+
export function getSecretsWithAssignment(catalogItem: CatalogItemRichened, secrets: Secret[]): { name: string, assigned: boolean }[] {
6464
return catalogItem.secrets?.map((secret) => ({ name: secret.name, assigned: secrets.some((s) => s.name === secret.name) })) || [];
6565
}
6666
}

src/extension/ui/src/components/CatalogGrid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { SwapVert, FolderOpenRounded } from '@mui/icons-material';
44
import { createDockerDesktopClient } from '@docker/extension-api-client';
55
import { ExecResult } from '@docker/extension-api-client-types/dist/v0';
66
import YourClients from './tabs/YourClients';
7-
import { CatalogItemWithName } from '../types/catalog';
7+
import { CatalogItemRichened } from '../types/catalog';
88
import { CATALOG_LAYOUT_SX } from '../Constants';
99
import { MCPClientState } from '../MCPClients';
1010

@@ -17,7 +17,7 @@ const client = createDockerDesktopClient();
1717
interface CatalogGridProps {
1818
appProps: any; // We'll use this to pass all our hook data
1919
showSettings: () => void;
20-
setConfiguringItem: (item: CatalogItemWithName) => void;
20+
setConfiguringItem: (item: CatalogItemRichened) => void;
2121
}
2222

2323
const parseDDVersion = (ddVersion: string) => {
@@ -86,7 +86,7 @@ export const CatalogGrid: React.FC<CatalogGridProps> = ({
8686
}
8787

8888
const hasOutOfCatalog = catalogItems.length > 0 && Object.keys(registryItems).length > 0 && !Object.keys(registryItems).every((i) =>
89-
catalogItems.some((c: CatalogItemWithName) => c.name === i)
89+
catalogItems.some((c: CatalogItemRichened) => c.name === i)
9090
)
9191

9292
const sortedCatalogItems = sort !== 'date-desc' ? [...catalogItems].sort((a, b) => {

src/extension/ui/src/components/tabs/ToolCatalog.tsx

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,31 @@ import { Card, CardContent, Grid2, IconButton } from '@mui/material';
33
import Tile from '../tile/Index';
44
import AddIcon from '@mui/icons-material/Add';
55
import { v1 } from "@docker/extension-api-client-types";
6-
import { CatalogItemWithName } from '../../types/catalog';
6+
import { CatalogItemRichened } from '../../types/catalog';
77
import { Secret } from '../../types/secrets';
88
import { CATALOG_LAYOUT_SX } from '../../Constants';
99

1010
interface ToolCatalogProps {
1111
search: string;
12-
catalogItems: CatalogItemWithName[];
12+
catalogItems: CatalogItemRichened[];
1313
client: v1.DockerDesktopClient;
1414
ddVersion: { version: string, build: number };
1515
canRegister: boolean;
16-
register: (item: CatalogItemWithName) => Promise<void>;
17-
unregister: (item: CatalogItemWithName) => Promise<void>;
16+
register: (item: CatalogItemRichened) => Promise<void>;
17+
unregister: (item: CatalogItemRichened) => Promise<void>;
1818
onSecretChange: (secret: { name: string, value: string }) => Promise<void>;
1919
secrets: Secret[];
2020
registryItems: { [key: string]: { ref: string, config: any } };
21-
setConfiguringItem: (item: CatalogItemWithName) => void;
21+
setConfiguringItem: (item: CatalogItemRichened) => void;
2222
config: { [key: string]: { [key: string]: any } };
2323
showMine: boolean;
2424
}
2525

26-
const ToolCatalog: React.FC<ToolCatalogProps> = ({ config, search, catalogItems, client, onSecretChange, secrets, registryItems, showMine }) => {
27-
28-
const tileIsRegistered = (item: CatalogItemWithName) => registryItems[item.name]?.ref !== undefined;
26+
const ToolCatalog: React.FC<ToolCatalogProps> = ({ config, search, catalogItems, client, registryItems, showMine }) => {
2927

3028
const filteredCatalogItems = catalogItems.filter(item => {
31-
const isRegistered = tileIsRegistered(item);
3229
const matchesSearch = item.name.toLowerCase().includes(search.toLowerCase());
33-
const hideBecauseItsNotMine = showMine && !isRegistered;
30+
const hideBecauseItsNotMine = showMine && !item.registered;
3431
return matchesSearch && !hideBecauseItsNotMine;
3532
});
3633

@@ -43,9 +40,6 @@ const ToolCatalog: React.FC<ToolCatalogProps> = ({ config, search, catalogItems,
4340
<Grid2 size={{ xs: 12, sm: 6, md: 4 }} key={catalogItem.name}>
4441
<Tile
4542
item={catalogItem}
46-
registered={tileIsRegistered(catalogItem)}
47-
onSecretChange={onSecretChange}
48-
secrets={secrets}
4943
unAssignedConfig={unAssignedConfig}
5044
client={client}
5145
/>

src/extension/ui/src/components/tabs/YourTools.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { CATALOG_LAYOUT_SX, MCP_POLICY_NAME } from '../../Constants';
55
import TileActions from '../tile/Bottom';
66
import { v1 } from '@docker/extension-api-client-types';
77
import { createDockerDesktopClient } from '@docker/extension-api-client';
8-
import { CatalogItemWithName } from '../../types/catalog';
8+
import { CatalogItemRichened } from '../../types/catalog';
99
import { Secret } from '../../types/secrets';
1010
// Initialize the Docker Desktop client
1111
const client = createDockerDesktopClient();
@@ -15,10 +15,10 @@ interface YourToolsProps {
1515
registryItems: { [key: string]: { ref: string, config: any } };
1616
config: { [key: string]: { [key: string]: any } };
1717
canRegister: boolean;
18-
unregister: (item: CatalogItemWithName) => Promise<void>;
19-
setConfiguringItem: (item: CatalogItemWithName) => void;
18+
unregister: (item: CatalogItemRichened) => Promise<void>;
19+
setConfiguringItem: (item: CatalogItemRichened) => void;
2020
secrets: Secret[];
21-
catalogItems: CatalogItemWithName[];
21+
catalogItems: CatalogItemRichened[];
2222
onSecretChange: (secret: { name: string, value: string }) => Promise<void>;
2323
ddVersion: { version: string, build: number };
2424
}
@@ -52,9 +52,6 @@ const YourTools: React.FC<YourToolsProps> = ({
5252
<Grid2 size={{ xs: 12, sm: 6, md: 4 }} key={name}>
5353
<Tile
5454
item={catalogItem}
55-
registered={true}
56-
onSecretChange={onSecretChange}
57-
secrets={secrets}
5855
client={client}
5956
unAssignedConfig={unassignedConfig}
6057
/>

src/extension/ui/src/components/tile/Center.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Tooltip, Typography } from "@mui/material";
2-
import { CatalogItemWithName } from "../../types"
2+
import { CatalogItemRichened } from "../../types"
33
import { TILE_DESCRIPTION_MAX_LENGTH } from "../../Constants";
44

55
type CenterProps = {
6-
item: CatalogItemWithName;
6+
item: CatalogItemRichened;
77
}
88

99
export default function Center({ item }: CenterProps) {

src/extension/ui/src/components/tile/ConfigEditor.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Button, CircularProgress, IconButton, TextField, Typography } from "@mui/material";
22
import { Alert, Stack } from "@mui/material";
3-
import { CatalogItemWithName } from "../../types/catalog";
3+
import { CatalogItemRichened } from "../../types/catalog";
44
import { useEffect, useState, useCallback, useMemo } from "react";
55
import * as JsonSchema from "json-schema-library";
6-
import { getTemplateForItem, useConfigContext } from "../../context/ConfigContext";
6+
import { getTemplateForItem, useConfig } from "../../hooks/useConfig";
77
import { deepFlattenObject, deepSet } from "../../MergeDeep";
88
import { CheckOutlined, CloseOutlined } from "@mui/icons-material";
9+
import { v1 } from "@docker/extension-api-client-types";
910

1011
JsonSchema.settings.GET_TEMPLATE_RECURSION_LIMIT = 1000;
1112
JsonSchema.settings.templateDefaultOptions.addOptionalProps = true;
@@ -25,10 +26,10 @@ const LoadingState = () => {
2526
)
2627
}
2728

28-
const ConfigEditor = ({ catalogItem }: { catalogItem: CatalogItemWithName }) => {
29+
const ConfigEditor = ({ catalogItem, client }: { catalogItem: CatalogItemRichened, client: v1.DockerDesktopClient }) => {
2930
const configSchema = catalogItem.config;
3031

31-
const { config: existingConfig, saveConfig: updateExistingConfig, configLoading, tryLoadConfig } = useConfigContext();
32+
const { config: existingConfig, saveConfig: updateExistingConfig, configLoading, tryLoadConfig } = useConfig(client);
3233

3334
const existingConfigForItem = existingConfig?.[catalogItem.name];
3435

src/extension/ui/src/components/tile/Index.tsx

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,36 @@
11
import { CircularProgress, Dialog, DialogContent, DialogTitle, Divider, IconButton, Stack, TextField, Typography } from "@mui/material";
22
import { Card, CardContent } from "@mui/material";
33
import { useEffect, useState } from "react";
4-
import { CatalogItemWithName } from "../../types/catalog";
4+
import { CatalogItemRichened } from "../../types/catalog";
55
import { Save, LockReset } from "@mui/icons-material";
66
import Secrets from "../../Secrets";
77
import ConfigurationModal from "./Modal";
88
import Top from "./Top";
99
import Center from "./Center";
1010
import Bottom from "./Bottom";
11-
import { Secret } from "../../types";
1211
import { v1 } from "@docker/extension-api-client-types";
12+
import { useSecrets } from "../../hooks/useSecrets";
13+
import { useCatalog, useCatalogOperations, useRegistry } from "../../hooks/useCatalog";
14+
import { MCP_POLICY_NAME } from "../../Constants";
1315

1416
type TileProps = {
15-
item: CatalogItemWithName;
16-
registered: boolean;
17-
onSecretChange: (secret: { name: string, value: string }) => Promise<void>;
18-
secrets: Secret[];
17+
item: CatalogItemRichened;
1918
client: v1.DockerDesktopClient;
2019
unAssignedConfig: { name: string; assigned: boolean }[];
2120
}
2221

23-
const Tile = ({ item, registered, onSecretChange, secrets, client, unAssignedConfig }: TileProps) => {
24-
const loadAssignedSecrets = () => {
25-
const assignedSecrets = Secrets.getSecretsWithAssignment(item, secrets);
26-
setAssignedSecrets(assignedSecrets)
27-
}
22+
const Tile = ({ item, client, unAssignedConfig }: TileProps) => {
2823

2924
const [showSecretDialog, setShowSecretDialog] = useState(false)
30-
const [assignedSecrets, setAssignedSecrets] = useState<{ name: string, assigned: boolean }[]>([])
25+
const [assignedSecrets] = useState<{ name: string, assigned: boolean }[]>([])
3126
const [changedSecrets, setChangedSecrets] = useState<{ [key: string]: string | undefined }>({})
3227
const [secretLoading, setSecretLoading] = useState(false)
33-
34-
const { registryLoading, registerCatalogItem, unregisterCatalogItem } = useCatalogContext()
3528
const [showConfigModal, setShowConfigModal] = useState(false)
29+
const { isLoading: secretsLoading, mutate: mutateSecret } = useSecrets(client)
30+
const { registryLoading } = useRegistry(client)
31+
const { registerCatalogItem, unregisterCatalogItem } = useCatalogOperations(client)
3632

37-
useEffect(() => {
38-
loadAssignedSecrets()
39-
}, [secrets])
40-
41-
if (registryLoading) {
33+
if (registryLoading || secretsLoading) {
4234
return <>
4335
<CircularProgress size={20} />
4436
<Typography>Loading registry...</Typography>
@@ -47,10 +39,6 @@ const Tile = ({ item, registered, onSecretChange, secrets, client, unAssignedCon
4739

4840
const unAssignedSecrets = assignedSecrets.filter(s => !s.assigned)
4941

50-
useEffect(() => {
51-
loadAssignedSecrets()
52-
}, [secrets])
53-
5442
return (
5543
<>
5644
<Dialog open={showSecretDialog} onClose={() => setShowSecretDialog(false)}>
@@ -72,7 +60,7 @@ const Tile = ({ item, registered, onSecretChange, secrets, client, unAssignedCon
7260
</IconButton>}
7361
{changedSecrets[secret.name] && <IconButton onClick={() => {
7462
setSecretLoading(true)
75-
onSecretChange({ name: secret.name, value: changedSecrets[secret.name] || '' }).then(() => {
63+
mutateSecret.mutateAsync({ name: secret.name, value: changedSecrets[secret.name] || '', policies: [MCP_POLICY_NAME] }).then(() => {
7664
setSecretLoading(false)
7765
const newChangedSecrets = { ...changedSecrets }
7866
delete newChangedSecrets[secret.name]
@@ -92,15 +80,6 @@ const Tile = ({ item, registered, onSecretChange, secrets, client, unAssignedCon
9280
onClose={() => setShowConfigModal(false)}
9381
catalogItem={item}
9482
client={client}
95-
registered={registered}
96-
onToggleRegister={(checked) => {
97-
if (checked) {
98-
registerCatalogItem(item)
99-
} else {
100-
unregisterCatalogItem(item)
101-
}
102-
}}
103-
onSecretChange={onSecretChange}
10483
/>
10584
<Card onClick={(e) => {
10685
if ((e.target as HTMLElement).tagName !== 'INPUT') {
@@ -115,7 +94,7 @@ const Tile = ({ item, registered, onSecretChange, secrets, client, unAssignedCon
11594
} else {
11695
unregisterCatalogItem(item)
11796
}
118-
}} item={item} unAssignedConfig={unAssignedConfig} unAssignedSecrets={unAssignedSecrets} registered={registered} />
97+
}} item={item} unAssignedConfig={unAssignedConfig} unAssignedSecrets={unAssignedSecrets} registered={true} />
11998
<Center item={item} />
12099
<Divider sx={{ marginBottom: 1 }} />
121100
<Bottom item={item} needsConfiguration={Boolean(unAssignedSecrets.length || unAssignedConfig.length)} />

0 commit comments

Comments
 (0)