import React, { useState, useEffect } from "react"; import { Button } from "@tremor/react"; import { Modal } from "antd"; import { getClaudeCodePluginsList, deleteClaudeCodePlugin } from "./networking"; import AddPluginForm from "./claude_code_plugins/add_plugin_form"; import PluginTable from "./claude_code_plugins/plugin_table"; import SkillDetail from "./claude_code_plugins/skill_detail"; import { isAdminRole } from "@/utils/roles"; import NotificationsManager from "./molecules/notifications_manager"; import { Plugin, ListPluginsResponse } from "./claude_code_plugins/types"; interface ClaudeCodePluginsPanelProps { accessToken: string | null; userRole?: string; } const ClaudeCodePluginsPanel: React.FC = ({ accessToken, userRole }) => { const [pluginsList, setPluginsList] = useState([]); const [isAddModalVisible, setIsAddModalVisible] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const [pluginToDelete, setPluginToDelete] = useState<{ name: string; displayName: string; } | null>(null); const [selectedSkill, setSelectedSkill] = useState(null); const isAdmin = userRole ? isAdminRole(userRole) : false; const fetchPlugins = async () => { if (!accessToken) return; setIsLoading(true); try { const response: ListPluginsResponse = await getClaudeCodePluginsList(accessToken, false); setPluginsList(response.plugins); } catch (error) { console.error("Error fetching skills:", error); } finally { setIsLoading(false); } }; useEffect(() => { fetchPlugins(); }, [accessToken]); const handleDeleteClick = (pluginName: string, displayName: string) => { setPluginToDelete({ name: pluginName, displayName }); }; const handleDeleteConfirm = async () => { if (!pluginToDelete || !accessToken) return; setIsDeleting(true); try { await deleteClaudeCodePlugin(accessToken, pluginToDelete.name); NotificationsManager.success(`Skill "${pluginToDelete.displayName}" deleted successfully`); fetchPlugins(); } catch (error) { console.error("Error deleting skill:", error); NotificationsManager.error("Failed to delete skill"); } finally { setIsDeleting(false); setPluginToDelete(null); } }; return (
{selectedSkill ? ( setSelectedSkill(null)} isAdmin={isAdmin} accessToken={accessToken} onPublishClick={fetchPlugins} /> ) : ( <>

Skills

Register Claude Code skills. Published skills appear in the Skill Hub for all users and are served via{" "} /claude-code/marketplace.json.

{ const skill = pluginsList.find((p) => p.id === id); if (skill) setSelectedSkill(skill); }} /> )} setIsAddModalVisible(false)} accessToken={accessToken} onSuccess={fetchPlugins} /> {pluginToDelete && ( setPluginToDelete(null)} confirmLoading={isDeleting} okText="Delete" okButtonProps={{ danger: true }} >

Are you sure you want to delete skill: {pluginToDelete.displayName}?

This action cannot be undone.

)}
); }; export default ClaudeCodePluginsPanel;