Skip to content

Commit 7ff617c

Browse files
0.2.35 (#86)
* UI Alignment p1 * Redesign catalog tiles * Adjust client settings and tile UI * Redesign tabs, add title * Cleanup some CSS vars * bumped version + saying yes Signed-off-by: Jean-Laurent de Morlhon <[email protected]> * Add final changes for 0.2.35 --------- Signed-off-by: Jean-Laurent de Morlhon <[email protected]> Co-authored-by: Jean-Laurent de Morlhon <[email protected]>
1 parent 73689cb commit 7ff617c

40 files changed

+598
-584
lines changed

src/extension/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# IMAGE?=docker/labs-ai-tools-for-devs
22
IMAGE?=docker/labs-ai-tools-for-devs
3-
TAG?=0.2.34
3+
TAG?=0.2.35
44

55
BUILDER=buildx-multi-arch
66

@@ -18,10 +18,10 @@ build-extension: cross ## Build service image to be deployed as a desktop extens
1818
docker buildx build --load --tag=$(IMAGE):$(TAG) .
1919

2020
install-extension: build-extension ## Install the extension
21-
docker extension install $(IMAGE):$(TAG)
21+
echo y | docker extension install $(IMAGE):$(TAG)
2222

2323
update-extension: build-extension ## Update the extension
24-
docker extension update $(IMAGE):$(TAG)
24+
echo y | docker extension update $(IMAGE):$(TAG)
2525

2626
prepare-buildx: ## Create buildx builder for multi-arch build, if not exists
2727
docker buildx inspect $(BUILDER) || docker buildx create --name=$(BUILDER) --driver=docker-container --driver-opt=network=host

src/extension/host-binary/cmd/main.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ type addOptions struct {
4949
Value string
5050
}
5151

52+
type deleteOptions struct {
53+
Name string
54+
}
55+
5256
func AddSecret(ctx context.Context) *cobra.Command {
5357
opts := &addOptions{}
5458
cmd := &cobra.Command{
@@ -79,6 +83,19 @@ func ListSecrets(ctx context.Context) *cobra.Command {
7983
return cmd
8084
}
8185

86+
func DeleteSecret(ctx context.Context) *cobra.Command {
87+
opts := &deleteOptions{}
88+
cmd := &cobra.Command{
89+
Use: "delete",
90+
Short: "Delete a secret",
91+
Args: cobra.NoArgs,
92+
}
93+
flags := cmd.Flags()
94+
flags.StringVarP(&opts.Name, "name", "n", "", "Name of the secret")
95+
_ = cmd.MarkFlagRequired("name")
96+
return cmd
97+
}
98+
8299
const mcpPolicyName = "MCP"
83100

84101
func runAddSecret(ctx context.Context, opts addOptions) error {
@@ -104,6 +121,14 @@ func runListSecrets(ctx context.Context) error {
104121
return json.NewEncoder(os.Stdout).Encode(secrets)
105122
}
106123

124+
func runDeleteSecret(ctx context.Context, opts deleteOptions) error {
125+
c, err := newApiClient()
126+
if err != nil {
127+
return err
128+
}
129+
return c.DeleteSecret(ctx, opts.Name)
130+
}
131+
107132
func assertMcpPolicyExists(ctx context.Context, apiClient client.ApiClient) error {
108133
return apiClient.SetPolicy(ctx, secretsapi.Policy{Name: mcpPolicyName, Images: []string{"*"}})
109134
}

src/extension/ui/src/App.tsx

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,17 @@
1-
import React, { useEffect, useState, Suspense } from 'react';
1+
import React, { useState, Suspense } from 'react';
22
import { createDockerDesktopClient } from '@docker/extension-api-client';
3-
import { Stack, Typography, Button, IconButton, Alert, DialogTitle, Dialog, DialogContent, CircularProgress, Paper, Box, SvgIcon, useTheme } from '@mui/material';
4-
import { CatalogItemWithName } from './components/tile/Tile';
3+
import { Typography, Button, IconButton, Alert, DialogTitle, Dialog, DialogContent, CircularProgress, Paper, Box, SvgIcon, useTheme } from '@mui/material';
4+
import { CatalogItemWithName } from './types/catalog';
55
import { Close } from '@mui/icons-material';
66
import { CatalogGrid } from './components/CatalogGrid';
77
import { POLL_INTERVAL } from './Constants';
88
import { CatalogProvider, useCatalogContext } from './context/CatalogContext';
99
import { ConfigProvider } from './context/ConfigContext';
1010
import { MCPClientProvider, useMCPClientContext } from './context/MCPClientContext';
1111
import ConfigurationModal from './components/ConfigurationModal';
12-
import { Settings as SettingsIcon } from '@mui/icons-material';
1312

1413
const Settings = React.lazy(() => import('./components/Settings'));
1514

16-
// Create lazy-loaded logo components
17-
const LazyDarkLogo = React.lazy(() => import('./components/DarkLogo'));
18-
const LazyLightLogo = React.lazy(() => import('./components/LightLogo'));
19-
20-
// Logo component that uses Suspense for conditional loading
21-
const Logo = () => {
22-
const theme = useTheme();
23-
const isDarkMode = theme.palette.mode === 'dark';
24-
25-
return (
26-
<Suspense fallback={<Box sx={{ height: '5em', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><CircularProgress size={24} /></Box>}>
27-
<Box sx={{ display: 'flex', alignItems: 'center', width: '100%' }}>
28-
{isDarkMode ? <LazyDarkLogo /> : <LazyLightLogo />}
29-
</Box>
30-
</Suspense>
31-
);
32-
}
33-
3415
export const client = createDockerDesktopClient();
3516

3617
const DEFAULT_SETTINGS = {
@@ -112,7 +93,7 @@ function AppContent({ settings, setSettings, configuringItem, setConfiguringItem
11293
</Paper>
11394
);
11495
}
115-
96+
const isDataFetching = imagesIsFetching || secretsLoading || catalogLoading || registryLoading || mcpFetching;
11697
return (
11798
<>
11899
{settings.showModal && (
@@ -147,39 +128,10 @@ function AppContent({ settings, setSettings, configuringItem, setConfiguringItem
147128
/>
148129
)}
149130

150-
{/* Show a small loading indicator in the corner during background refetching */}
151-
{(imagesIsFetching || secretsLoading || catalogLoading || registryLoading || mcpFetching) && (
152-
<Box
153-
sx={{
154-
position: 'fixed',
155-
bottom: 16,
156-
right: 16,
157-
zIndex: 9999,
158-
display: 'flex',
159-
alignItems: 'center',
160-
backgroundColor: 'background.paper',
161-
borderRadius: 2,
162-
padding: 1,
163-
boxShadow: 3
164-
}}
165-
>
166-
<CircularProgress size={20} sx={{ mr: 1 }} />
167-
<Typography variant="caption">Refreshing data...</Typography>
168-
</Box>
169-
)}
170-
171-
<Stack direction="column" spacing={1} justifyContent='center' alignItems='center'>
172-
<Stack direction="row" spacing={1} justifyContent='space-evenly' alignItems='center' sx={{ width: '100%', maxWidth: '1000px' }}>
173-
<Logo />
174-
<IconButton sx={{ ml: 2, alignSelf: 'flex-end', justifyContent: 'flex-end' }} onClick={() => setSettings({ ...settings, showModal: true })}>
175-
<SettingsIcon sx={{ fontSize: '1.5em' }} />
176-
</IconButton>
177-
</Stack>
178-
<CatalogGrid
179-
setConfiguringItem={setConfiguringItem}
180-
showSettings={() => setSettings({ ...settings, showModal: true })}
181-
/>
182-
</Stack>
131+
<CatalogGrid
132+
setConfiguringItem={setConfiguringItem}
133+
showSettings={() => setSettings({ ...settings, showModal: true })}
134+
/>
183135
</>
184136
);
185137
}

src/extension/ui/src/Constants.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
export const POLL_INTERVAL = 1000 * 30;
22
export const MCP_POLICY_NAME = 'MCP=*';
33
export const DD_BUILD_WITH_SECRET_SUPPORT = 184396;
4-
export const CATALOG_URL = 'https://raw.githubusercontent.com/docker/labs-ai-tools-for-devs/refs/heads/main/prompts/catalog.yaml'
4+
export const CATALOG_URL = localStorage.getItem('catalogUrl') || 'https://raw.githubusercontent.com/docker/labs-ai-tools-for-devs/refs/heads/main/prompts/catalog.yaml'
5+
6+
export const getUnsupportedSecretMessage = (ddVersion: { version: string, build: number }) =>
7+
`Secret support is not available in this version of Docker Desktop. You are on version ${ddVersion.version}, but the minimum required version is 4.40.0.`
58

6-
export const getUnsupportedSecretMessage = (ddVersion: { version: string, build: number }) => {
7-
return `Secret support is not available in this version of Docker Desktop. You are on version ${ddVersion.version}, but the minimum required version is 4.40.0.`
8-
}
99
export const DOCKER_MCP_IMAGE = 'alpine/socat'
1010
export const DOCKER_MCP_CONTAINER_ARGS = 'STDIO TCP:host.docker.internal:8811'
11-
export const DOCKER_MCP_COMMAND = `docker run -i --rm ${DOCKER_MCP_IMAGE} ${DOCKER_MCP_CONTAINER_ARGS}`
11+
export const DOCKER_MCP_COMMAND = `docker run -i --rm ${DOCKER_MCP_IMAGE} ${DOCKER_MCP_CONTAINER_ARGS}`
12+
13+
export const TILE_DESCRIPTION_MAX_LENGTH = 80;
14+
15+
export const CATALOG_LAYOUT_SX = {
16+
width: '90vw',
17+
maxWidth: '1200px',
18+
}

src/extension/ui/src/MCP Catalog_dark.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/extension/ui/src/MCP Catalog_light.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/extension/ui/src/MCPClients.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 { SUPPORTED_MCP_CLIENTS } from "./mcp-clients";
3-
import { MCPClient } from "./mcp-clients/MCPTypes";
3+
import { MCPClient } from "./types/mcp";
44

55
export type MCPClientState = {
66
client: MCPClient;

src/extension/ui/src/MergeDeep.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
/**
2-
* Type for any object with string keys
3-
*/
4-
export type DeepObject = { [key: string]: any };
1+
import { DeepObject } from './types/utils';
52

63
/**
74
* Simple object check.

src/extension/ui/src/Registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { v1 } from "@docker/extension-api-client-types";
22
import { parse, stringify } from "yaml";
33
import { readFileInPromptsVolume, writeFileToPromptsVolume } from "./FileWatcher";
4-
import { ParsedParameters } from "./components/ConfigurationModal";
54
import { mergeDeep } from "./MergeDeep";
5+
import { ParsedParameters } from "./types/config";
66

77
export const getRegistry = async (client: v1.DockerDesktopClient) => {
88
const parseRegistry = async () => {

src/extension/ui/src/Secrets.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,10 @@
11
// From secrets.yaml
22

33
import { v1 } from "@docker/extension-api-client-types";
4-
import { CatalogItemWithName } from "./components/tile/Tile";
4+
import { CatalogItemWithName } from "./types/catalog";
5+
import { Secret, StoredSecret, Policy } from "./types/secrets";
56

67
namespace Secrets {
7-
export type Secret = {
8-
name: string;
9-
value: string;
10-
policies: string[];
11-
}
12-
13-
export type StoredSecret = {
14-
name: string;
15-
policies: string[];
16-
}
17-
18-
export type Policy = {
19-
name: string;
20-
images: string[];
21-
}
22-
238
export async function getSecrets(client: v1.DockerDesktopClient): Promise<Secret[]> {
249
const response = await client.extension.host?.cli.exec('host-binary', ['list']);
2510
if (!response) {

0 commit comments

Comments
 (0)