From e07a0f2e5221d5abe02a8a00f7ef4a6c494bc976 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Fri, 31 Jan 2025 09:04:25 -0500 Subject: [PATCH] Modal fixes --- src/extension/Makefile | 2 +- src/extension/ui/src/App.tsx | 41 ++++++++++++------- .../src/components/ClaudeConfigSyncStatus.tsx | 7 +--- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/extension/Makefile b/src/extension/Makefile index 6b8d320..2165f56 100644 --- a/src/extension/Makefile +++ b/src/extension/Makefile @@ -1,5 +1,5 @@ IMAGE?=docker/labs-ai-tools-for-devs -TAG?=0.1.2 +TAG?=0.1.4 BUILDER=buildx-multi-arch diff --git a/src/extension/ui/src/App.tsx b/src/extension/ui/src/App.tsx index 3fc0a59..0f81263 100644 --- a/src/extension/ui/src/App.tsx +++ b/src/extension/ui/src/App.tsx @@ -1,14 +1,16 @@ import React, { useEffect, useState } from 'react'; import AddIcon from '@mui/icons-material/Add'; import { createDockerDesktopClient } from '@docker/extension-api-client'; -import { Stack, Typography, Button, ButtonGroup, Grid, debounce, Card, CardContent, IconButton, Alert } from '@mui/material'; +import { Stack, Typography, Button, ButtonGroup, Grid, debounce, Card, CardContent, IconButton, Alert, DialogTitle, Dialog, DialogContent, FormControlLabel, Checkbox } from '@mui/material'; import { CatalogItem, CatalogItemCard, CatalogItemWithName } from './components/PromptCard'; import { parse, stringify } from 'yaml'; import { Ref } from './Refs'; import { RegistrySyncStatus } from './components/RegistrySyncStatus'; import { getRegistry } from './Registry'; -import { ClaudeConfigSyncStatus } from './components/ClaudeConfigSyncStatus'; -import { FolderOpen, FolderOpenOutlined, FolderOpenRounded, VolumeUp } from '@mui/icons-material'; +import { ClaudeConfigSyncStatus, setNeverShowAgain } from './components/ClaudeConfigSyncStatus'; +import { FolderOpenRounded, } from '@mui/icons-material'; + +const NEVER_SHOW_AGAIN_KEY = 'registry-sync-never-show-again'; type RegistryItem = { ref: string; @@ -24,25 +26,16 @@ export function App() { const [catalogItems, setCatalogItems] = useState([]); const [canRegister, setCanRegister] = useState(false); const [registryItems, setRegistryItems] = useState<{ [key: string]: { ref: string } }>({}); - const [status, setStatus] = useState<{ - status: 'idle' | 'loading' | 'error', - message: string - }>({ - status: 'idle', - message: '' - }); - + const [showReloadModal, setShowReloadModal] = useState(false); const [hasConfig, setHasConfig] = useState(false); const loadCatalog = async () => { - setStatus({ status: 'loading', message: 'Grabbing latest prompt catalog...' }); try { const response = await fetch(CATALOG_URL); const catalog = await response.text(); const items = parse(catalog)['registry'] as { [key: string]: CatalogItem } const itemsWithName = Object.entries(items).map(([name, item]) => ({ name, ...item })); setCatalogItems(itemsWithName); - setStatus({ status: 'idle', message: '' }); } catch (error) { client.desktopUI.toast.error('Failed to get latest catalog: ' + error); @@ -52,11 +45,9 @@ export function App() { const loadRegistry = async () => { setRegistryLoaded(false); setCanRegister(false); - setStatus({ status: 'loading', message: 'Grabbing prompt registry...' }); try { const result = await getRegistry(client) setRegistryItems(result || {}); - setStatus({ status: 'idle', message: '' }); setRegistryLoaded(true); } @@ -83,6 +74,7 @@ export function App() { await client.docker.cli.exec('run', ['--rm', '-v', 'docker-prompts:/docker-prompts', '--workdir', '/docker-prompts', 'vonwig/function_write_files:latest', `'${payload}'`]) client.desktopUI.toast.success('Prompt registered successfully. Restart Claude Desktop to apply.'); await loadRegistry(); + setShowReloadModal(!localStorage.getItem(NEVER_SHOW_AGAIN_KEY)); } catch (error) { client.desktopUI.toast.error('Failed to register prompt: ' + error); @@ -102,10 +94,12 @@ export function App() { await client.docker.cli.exec('run', ['--rm', '-v', 'docker-prompts:/docker-prompts', '--workdir', '/docker-prompts', 'vonwig/function_write_files:latest', `'${payload}'`]) client.desktopUI.toast.success('Prompt unregistered successfully. Restart Claude Desktop to apply.'); await loadRegistry(); + setShowReloadModal(!localStorage.getItem(NEVER_SHOW_AGAIN_KEY)); } catch (error) { client.desktopUI.toast.error('Failed to unregister prompt: ' + error) } + } useEffect(() => { @@ -126,8 +120,25 @@ export function App() { return (
+ setShowReloadModal(false)}> + Registry Updated + + + You have updated the registry. + Use the keybind {client.host.platform === 'win32' ? 'Ctrl' : '⌘'} + R to refresh MCP servers in Claude Desktop. + + + + localStorage.setItem(NEVER_SHOW_AGAIN_KEY, e.target.checked.toString())} />} label="Don't show this again" /> + + + +
+ diff --git a/src/extension/ui/src/components/ClaudeConfigSyncStatus.tsx b/src/extension/ui/src/components/ClaudeConfigSyncStatus.tsx index 1e97640..3654fb2 100644 --- a/src/extension/ui/src/components/ClaudeConfigSyncStatus.tsx +++ b/src/extension/ui/src/components/ClaudeConfigSyncStatus.tsx @@ -50,7 +50,7 @@ const getClaudeConfig = async (client: v1.DockerDesktopClient) => { return result.stdout } -const setNeverShowAgain = (value: boolean) => { +export const setNeverShowAgain = (value: boolean) => { localStorage.setItem('claude-config-sync-status-never-show-again', value.toString()) } @@ -93,7 +93,6 @@ export const ClaudeConfigSyncStatus = ({ client, setHasConfig }: { client: v1.Do const servers = claudeConfig.mcpServers if (!servers) { setStatus({ state: 'invalid', message: 'No servers found in Claude Desktop Config', color: 'error' }) - } else { const hasDocker = Object.keys(servers).some(key => key === 'mcp_docker') @@ -151,11 +150,9 @@ export const ClaudeConfigSyncStatus = ({ client, setHasConfig }: { client: v1.Do - Use the keybind {client.host.platform === 'win32' ? 'Ctrl' : '⌘'} + R to refresh MCP servers in Claude Desktop. + Claude config has been updated. Please restart Claude Desktop to apply the changes. setNeverShowAgain(e.target.checked)} />} label="Don't show this again" /> - -