mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-12 12:47:42 +02:00
[eric] apps: card History action + grid-level branch toast
This commit is contained in:
@@ -6,6 +6,7 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||
import HistoryIcon from '@mui/icons-material/History';
|
||||
import Icon from '@mui/material/Icon';
|
||||
import { Output } from '@/shared/state/outputsSlice';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
@@ -16,9 +17,10 @@ interface Props {
|
||||
onClick: () => void;
|
||||
onDelete: () => void;
|
||||
onRun: () => void;
|
||||
onHistory: () => void;
|
||||
}
|
||||
|
||||
const ViewCard: React.FC<Props> = ({ output, onClick, onDelete, onRun }) => {
|
||||
const ViewCard: React.FC<Props> = ({ output, onClick, onDelete, onRun, onHistory }) => {
|
||||
const c = useClaudeTokens();
|
||||
|
||||
return (
|
||||
@@ -108,6 +110,20 @@ const ViewCard: React.FC<Props> = ({ output, onClick, onDelete, onRun }) => {
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<ShareButton target={{ kind: 'app', id: output.id, name: output.name }} tone="chip" iconFontSize={16} />
|
||||
<Tooltip title="History">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(e) => { e.stopPropagation(); onHistory(); }}
|
||||
sx={{
|
||||
bgcolor: c.bg.surface,
|
||||
color: c.text.secondary,
|
||||
boxShadow: c.shadow.sm,
|
||||
'&:hover': { bgcolor: c.bg.elevated },
|
||||
}}
|
||||
>
|
||||
<HistoryIcon sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Delete">
|
||||
<IconButton
|
||||
size="small"
|
||||
|
||||
@@ -3,6 +3,9 @@ import { useParams, useNavigate } from 'react-router-dom';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Button from '@mui/material/Button';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import Snackbar from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
|
||||
import { fetchOutputs, deleteOutput, Output } from '@/shared/state/outputsSlice';
|
||||
@@ -11,6 +14,7 @@ import { byPreviewRecency } from '@/shared/previewOrder';
|
||||
import ViewCard from './ViewCard';
|
||||
import { Skeleton } from '@/app/components/feedback/Loading';
|
||||
import ViewRunDialog from './ViewRunDialog';
|
||||
import HistoryPanel from './HistoryPanel';
|
||||
// Lazy: pulls CodeMirror (~600KB) + 1600 lines of form scaffolding, only needed when an editor opens.
|
||||
const ViewEditor = lazy(() => import('./ViewEditor'));
|
||||
|
||||
@@ -27,6 +31,10 @@ const Views: React.FC = () => {
|
||||
const [editorOpen, setEditorOpen] = useState(false);
|
||||
const [editingOutput, setEditingOutput] = useState<Output | null>(null);
|
||||
const [runOutput, setRunOutput] = useState<Output | null>(null);
|
||||
const [historyOutput, setHistoryOutput] = useState<Output | null>(null);
|
||||
// Branch closes the history modal, which would unmount the panel before its own
|
||||
// flash renders; surface the confirmation at the grid level so it survives.
|
||||
const [branchToast, setBranchToast] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchOutputs());
|
||||
@@ -161,6 +169,7 @@ const Views: React.FC = () => {
|
||||
onClick={() => handleEditView(output)}
|
||||
onDelete={() => handleDeleteView(output.id)}
|
||||
onRun={() => setRunOutput(output)}
|
||||
onHistory={() => setHistoryOutput(output)}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
@@ -174,6 +183,34 @@ const Views: React.FC = () => {
|
||||
onClose={() => setRunOutput(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{historyOutput && (
|
||||
<Dialog
|
||||
open
|
||||
onClose={() => setHistoryOutput(null)}
|
||||
PaperProps={{ sx: { borderRadius: 3, bgcolor: c.bg.surface, width: 480, maxWidth: '92vw', height: '72vh' } }}
|
||||
>
|
||||
<HistoryPanel
|
||||
outputId={historyOutput.id}
|
||||
onBranched={() => { setHistoryOutput(null); setBranchToast(true); }}
|
||||
/>
|
||||
</Dialog>
|
||||
)}
|
||||
|
||||
<Snackbar
|
||||
open={branchToast}
|
||||
autoHideDuration={3000}
|
||||
onClose={() => setBranchToast(false)}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
>
|
||||
<Alert
|
||||
onClose={() => setBranchToast(false)}
|
||||
severity="success"
|
||||
sx={{ bgcolor: c.status.successBg, color: c.status.success, border: `1px solid rgba(38,91,25,0.25)` }}
|
||||
>
|
||||
Saved as a new app. Find it at the top of your apps.
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user