diff options
| author | soryu <soryu@soryu.co> | 2026-02-08 21:07:30 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-08 21:07:30 +0000 |
| commit | 3662b334dfd68cfdf00ed44ae88927c2e1b2aabe (patch) | |
| tree | bff5ae1e189fb8bcc0211d97dab3b9acb4257038 /makima/frontend/src/routes | |
| parent | 87fa8c4af66745bd30bc84b6c5ef657dd4dec002 (diff) | |
| download | soryu-3662b334dfd68cfdf00ed44ae88927c2e1b2aabe.tar.gz soryu-3662b334dfd68cfdf00ed44ae88927c2e1b2aabe.zip | |
Remove directive mechanism
Diffstat (limited to 'makima/frontend/src/routes')
| -rw-r--r-- | makima/frontend/src/routes/directives.tsx | 403 |
1 files changed, 0 insertions, 403 deletions
diff --git a/makima/frontend/src/routes/directives.tsx b/makima/frontend/src/routes/directives.tsx deleted file mode 100644 index fd3808b..0000000 --- a/makima/frontend/src/routes/directives.tsx +++ /dev/null @@ -1,403 +0,0 @@ -import { useState, useCallback, useEffect } from "react"; -import { useParams, useNavigate } from "react-router"; -import { Masthead } from "../components/Masthead"; -import { DirectiveList } from "../components/directives/DirectiveList"; -import { DirectiveDetail } from "../components/directives/DirectiveDetail"; -import { DirectoryInput } from "../components/mesh/DirectoryInput"; -import { useDirectives } from "../hooks/useDirectives"; -import { useAuth } from "../contexts/AuthContext"; -import { - getDaemonDirectories, - getRepositorySuggestions, -} from "../lib/api"; -import type { - DirectiveWithChains, - CreateDirectiveRequest, - RepositorySourceType, - DaemonDirectory, - RepositoryHistoryEntry, -} from "../lib/api"; - -export default function DirectivesPage() { - const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth(); - const navigate = useNavigate(); - - // Redirect to login if not authenticated (when auth is configured) - useEffect(() => { - if (!authLoading && isAuthConfigured && !isAuthenticated) { - navigate("/login"); - } - }, [authLoading, isAuthConfigured, isAuthenticated, navigate]); - - if (authLoading) { - return ( - <div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]"> - <Masthead showNav /> - <main className="flex-1 flex items-center justify-center"> - <p className="text-[#7788aa] font-mono text-sm">Loading...</p> - </main> - </div> - ); - } - - if (isAuthConfigured && !isAuthenticated) { - return null; - } - - return <DirectivesContent />; -} - -function DirectivesContent() { - const { id } = useParams<{ id?: string }>(); - const navigate = useNavigate(); - const { - directives, - loading, - error, - fetchDirective, - saveDirective, - removeDirective, - startDirective, - } = useDirectives(); - - const [selectedDirective, setSelectedDirective] = - useState<DirectiveWithChains | null>(null); - const [detailLoading, setDetailLoading] = useState(false); - const [showCreateForm, setShowCreateForm] = useState(false); - const [createTitle, setCreateTitle] = useState(""); - const [createGoal, setCreateGoal] = useState(""); - - // Repository state - const [repoType, setRepoType] = useState<RepositorySourceType>("remote"); - const [repoUrl, setRepoUrl] = useState(""); - const [repoPath, setRepoPath] = useState(""); - const [suggestedDirectories, setSuggestedDirectories] = useState<DaemonDirectory[]>([]); - const [repoSuggestions, setRepoSuggestions] = useState<RepositoryHistoryEntry[]>([]); - const [showRepoSuggestions, setShowRepoSuggestions] = useState(false); - - // Fetch repository suggestions when modal opens and repo type changes - useEffect(() => { - if (showCreateForm && (repoType === "remote" || repoType === "local")) { - getRepositorySuggestions(repoType, undefined, 10) - .then((res) => { - setRepoSuggestions(res.entries); - setShowRepoSuggestions(res.entries.length > 0); - }) - .catch(() => { - setRepoSuggestions([]); - setShowRepoSuggestions(false); - }); - } else { - setRepoSuggestions([]); - setShowRepoSuggestions(false); - } - }, [showCreateForm, repoType]); - - // Fetch daemon directories when "local" repo type is selected - useEffect(() => { - if (repoType === "local" && showCreateForm) { - getDaemonDirectories() - .then((res) => setSuggestedDirectories(res.directories)) - .catch(() => setSuggestedDirectories([])); - } - }, [repoType, showCreateForm]); - - // Apply a repository suggestion - const applyRepoSuggestion = useCallback((suggestion: RepositoryHistoryEntry) => { - if (suggestion.repositoryUrl) { - setRepoUrl(suggestion.repositoryUrl); - } - if (suggestion.localPath) { - setRepoPath(suggestion.localPath); - } - setShowRepoSuggestions(false); - }, []); - - // Load directive when ID changes - useEffect(() => { - if (id) { - setDetailLoading(true); - fetchDirective(id).then((d) => { - setSelectedDirective(d); - setDetailLoading(false); - }); - } else { - setSelectedDirective(null); - } - }, [id, fetchDirective]); - - const handleSelect = useCallback( - (directiveId: string) => { - navigate(`/directives/${directiveId}`); - }, - [navigate] - ); - - const handleBack = useCallback(() => { - navigate("/directives"); - }, [navigate]); - - const resetCreateForm = useCallback(() => { - setShowCreateForm(false); - setCreateTitle(""); - setCreateGoal(""); - setRepoType("remote"); - setRepoUrl(""); - setRepoPath(""); - }, []); - - const handleCreate = useCallback(async () => { - if (!createTitle.trim() || !createGoal.trim()) return; - - const data: CreateDirectiveRequest = { - title: createTitle.trim(), - goal: createGoal.trim(), - }; - if (repoType === "remote" && repoUrl.trim()) { - data.repositoryUrl = repoUrl.trim(); - } else if (repoType === "local" && repoPath.trim()) { - data.localPath = repoPath.trim(); - } - - const result = await saveDirective(data); - if (result) { - resetCreateForm(); - } - }, [createTitle, createGoal, repoType, repoUrl, repoPath, saveDirective, resetCreateForm]); - - const handleDelete = useCallback( - async (directiveId: string) => { - const ok = await removeDirective(directiveId); - if (ok && id === directiveId) { - navigate("/directives"); - } - }, - [removeDirective, id, navigate] - ); - - const handleStart = useCallback( - async (directiveId: string) => { - const ok = await startDirective(directiveId); - if (ok) { - const updated = await fetchDirective(directiveId); - if (updated) { - setSelectedDirective(updated); - } - } - }, - [startDirective, fetchDirective] - ); - - const handleRefresh = useCallback( - (updated: DirectiveWithChains) => { - setSelectedDirective(updated); - }, - [] - ); - - return ( - <div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]"> - <Masthead showNav /> - <main className="flex-1 flex flex-col p-4 pt-2 gap-4 overflow-hidden"> - {error && ( - <div className="p-3 bg-red-400/10 border border-red-400/30 text-red-400 font-mono text-sm"> - {error} - </div> - )} - - {/* Create directive modal */} - {showCreateForm && ( - <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"> - <div className="w-full max-w-lg max-h-[90vh] overflow-y-auto p-6 bg-[#0a1628] border border-[rgba(117,170,252,0.3)]"> - <h3 className="font-mono text-sm text-[#75aafc] uppercase mb-4"> - New Directive - </h3> - <div className="space-y-4"> - {/* Title */} - <div> - <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1"> - Title - </label> - <input - type="text" - placeholder="Directive title" - value={createTitle} - onChange={(e) => setCreateTitle(e.target.value)} - className="w-full px-3 py-2 font-mono text-sm text-[#dbe7ff] bg-[#0d1b2d] border border-[#3f6fb3] focus:border-[#75aafc] outline-none" - autoFocus - /> - </div> - - {/* Goal */} - <div> - <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1"> - Goal - </label> - <textarea - placeholder="What should be accomplished?" - value={createGoal} - onChange={(e) => setCreateGoal(e.target.value)} - rows={3} - className="w-full px-3 py-2 font-mono text-sm text-[#dbe7ff] bg-[#0d1b2d] border border-[#3f6fb3] focus:border-[#75aafc] outline-none resize-none" - /> - </div> - - {/* Repository Configuration */} - <div className="border-t border-[rgba(117,170,252,0.2)] pt-4"> - <label className="block font-mono text-xs text-[#75aafc] uppercase mb-3"> - Repository (optional) - </label> - - {/* Repository type selector */} - <div className="flex gap-2 mb-3"> - <button - type="button" - onClick={() => setRepoType("remote")} - className={`flex-1 px-3 py-2 font-mono text-xs uppercase transition-colors ${ - repoType === "remote" - ? "bg-[#0f3c78] text-[#dbe7ff] border border-[#75aafc]" - : "bg-[#0d1b2d] text-[#8b949e] border border-[#3f6fb3] hover:border-[#75aafc]" - }`} - > - Remote - </button> - <button - type="button" - onClick={() => setRepoType("local")} - className={`flex-1 px-3 py-2 font-mono text-xs uppercase transition-colors ${ - repoType === "local" - ? "bg-[#0f3c78] text-[#dbe7ff] border border-[#75aafc]" - : "bg-[#0d1b2d] text-[#8b949e] border border-[#3f6fb3] hover:border-[#75aafc]" - }`} - > - Local - </button> - </div> - - {/* Repository suggestions */} - {showRepoSuggestions && repoSuggestions.length > 0 && ( - <div className="mb-3"> - <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1"> - Recent Repositories - </label> - <div className="border border-[rgba(117,170,252,0.2)] bg-[#0a1525] max-h-32 overflow-y-auto"> - {repoSuggestions.map((suggestion) => ( - <button - key={suggestion.id} - type="button" - onClick={() => applyRepoSuggestion(suggestion)} - className="w-full text-left px-3 py-2 font-mono text-xs hover:bg-[rgba(117,170,252,0.1)] border-b border-[rgba(117,170,252,0.1)] last:border-b-0" - > - <div className="flex items-center justify-between"> - <span className="text-[#9bc3ff] truncate">{suggestion.name}</span> - <span className="text-[10px] text-[#556677] ml-2"> - {suggestion.useCount}× - </span> - </div> - <div className="text-[10px] text-[#556677] truncate"> - {repoType === "local" ? suggestion.localPath : suggestion.repositoryUrl} - </div> - </button> - ))} - </div> - </div> - )} - - {/* Repository URL (for remote) */} - {repoType === "remote" && ( - <div> - <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1"> - Repository URL - </label> - <input - type="text" - value={repoUrl} - onChange={(e) => setRepoUrl(e.target.value)} - placeholder="https://github.com/user/repo.git" - className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc]" - /> - </div> - )} - - {/* Repository path (for local) */} - {repoType === "local" && ( - <div> - <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1"> - Local Path - </label> - <DirectoryInput - value={repoPath} - onChange={setRepoPath} - suggestions={suggestedDirectories} - placeholder="/path/to/repository" - repoUrl={repoUrl || null} - /> - </div> - )} - </div> - - {/* Actions */} - <div className="flex gap-2 justify-end pt-2"> - <button - onClick={resetCreateForm} - className="px-4 py-2 font-mono text-xs text-[#9bc3ff] hover:text-[#dbe7ff] transition-colors" - > - Cancel - </button> - <button - onClick={handleCreate} - disabled={!createTitle.trim() || !createGoal.trim()} - className="px-4 py-2 font-mono text-xs text-[#dbe7ff] bg-[#0f3c78] border border-[#3f6fb3] hover:bg-[#153667] transition-colors disabled:opacity-50 disabled:cursor-not-allowed" - > - Create - </button> - </div> - </div> - </div> - </div> - )} - - <div className="flex-1 grid grid-cols-[350px_1fr] gap-4 min-h-0"> - {/* Directive list */} - <DirectiveList - directives={directives} - loading={loading} - onSelect={handleSelect} - onCreate={() => setShowCreateForm(true)} - onDelete={(d) => handleDelete(d.id)} - selectedId={id} - /> - - {/* Directive detail or empty state */} - {detailLoading ? ( - <div className="panel h-full flex items-center justify-center"> - <p className="text-[#7788aa] font-mono text-sm">Loading directive...</p> - </div> - ) : selectedDirective ? ( - <DirectiveDetail - directive={selectedDirective} - onBack={handleBack} - onDelete={handleDelete} - onStart={handleStart} - onRefresh={handleRefresh} - /> - ) : ( - <div className="panel h-full flex items-center justify-center"> - <div className="text-center"> - <p className="font-mono text-sm text-[#555] mb-4"> - Select a directive or create a new one - </p> - <button - onClick={() => setShowCreateForm(true)} - className="px-4 py-2 font-mono text-xs text-[#dbe7ff] bg-[#0f3c78] border border-[#3f6fb3] hover:bg-[#153667] transition-colors uppercase" - > - + New Directive - </button> - </div> - </div> - )} - </div> - </main> - </div> - ); -} |
