mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-08 22:48:14 -05:00
Fixed and improved version history
This commit is contained in:
@@ -8,6 +8,7 @@ interface HistoryDropdownItemProps {
|
||||
timestamp: number
|
||||
onClick?: () => void
|
||||
isCurrent?: boolean
|
||||
isFuture?: boolean
|
||||
id?: string
|
||||
}
|
||||
|
||||
@@ -16,25 +17,55 @@ export function HistoryDropdownItem({
|
||||
timestamp,
|
||||
onClick,
|
||||
isCurrent = false,
|
||||
isFuture = false,
|
||||
id,
|
||||
}: HistoryDropdownItemProps) {
|
||||
const timeAgo = formatDistanceToNow(timestamp, { addSuffix: true })
|
||||
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
className="flex items-start gap-2 p-3 cursor-pointer"
|
||||
className={cn(
|
||||
'flex items-start gap-2 p-3 cursor-pointer',
|
||||
isFuture && 'text-muted-foreground/50'
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
<Clock
|
||||
className={cn(
|
||||
'h-4 w-4',
|
||||
isFuture ? 'text-muted-foreground/50' : 'text-muted-foreground'
|
||||
)}
|
||||
/>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
{isCurrent ? (
|
||||
<span className="text-xs text-muted-foreground">Current</span>
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs',
|
||||
isFuture ? 'text-muted-foreground/50' : 'text-muted-foreground'
|
||||
)}
|
||||
>
|
||||
Current
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">{timeAgo}</span>
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs',
|
||||
isFuture ? 'text-muted-foreground/50' : 'text-muted-foreground'
|
||||
)}
|
||||
>
|
||||
{timeAgo}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-foreground">{action}</p>
|
||||
<p
|
||||
className={cn(
|
||||
'text-sm',
|
||||
isFuture ? 'text-muted-foreground/50' : 'text-foreground'
|
||||
)}
|
||||
>
|
||||
{action}
|
||||
</p>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
|
||||
export function ControlBar() {
|
||||
const { notifications, getWorkflowNotifications } = useNotificationStore()
|
||||
const { history, undo, redo } = useWorkflowStore()
|
||||
const { history, undo, redo, revertToHistoryState } = useWorkflowStore()
|
||||
const [, forceUpdate] = useState({})
|
||||
const { isExecuting, handleRunWorkflow } = useWorkflowExecution()
|
||||
const { workflows, removeWorkflow, activeWorkflowId } = useWorkflowRegistry()
|
||||
@@ -109,15 +109,33 @@ export function ControlBar() {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
{history.past.length === 0 ? (
|
||||
{history.past.length === 0 && history.future.length === 0 ? (
|
||||
<DropdownMenuContent align="end" className="w-40">
|
||||
<DropdownMenuItem className="text-sm text-muted-foreground">
|
||||
No history available
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
) : (
|
||||
<DropdownMenuContent align="end" className="w-60">
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
className="w-60 max-h-[300px] overflow-y-auto"
|
||||
>
|
||||
<>
|
||||
{[...history.future].reverse().map((entry, index) => (
|
||||
<HistoryDropdownItem
|
||||
key={`future-${entry.timestamp}-${index}`}
|
||||
action={entry.action}
|
||||
timestamp={entry.timestamp}
|
||||
onClick={() =>
|
||||
revertToHistoryState(
|
||||
history.past.length +
|
||||
1 +
|
||||
(history.future.length - 1 - index)
|
||||
)
|
||||
}
|
||||
isFuture={true}
|
||||
/>
|
||||
))}
|
||||
<HistoryDropdownItem
|
||||
key={`current-${history.present.timestamp}`}
|
||||
action={history.present.action}
|
||||
@@ -130,7 +148,9 @@ export function ControlBar() {
|
||||
key={`past-${entry.timestamp}-${index}`}
|
||||
action={entry.action}
|
||||
timestamp={entry.timestamp}
|
||||
onClick={undo}
|
||||
onClick={() =>
|
||||
revertToHistoryState(history.past.length - 1 - index)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
@@ -153,7 +173,10 @@ export function ControlBar() {
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
) : (
|
||||
<DropdownMenuContent align="end" className="w-60">
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
className="w-60 max-h-[300px] overflow-y-auto"
|
||||
>
|
||||
{[...workflowNotifications]
|
||||
.sort((a, b) => b.timestamp - a.timestamp)
|
||||
.map((notification) => (
|
||||
|
||||
@@ -86,6 +86,27 @@ export const withHistory = (
|
||||
set(newState)
|
||||
return newState
|
||||
},
|
||||
|
||||
revertToHistoryState: (index: number) => {
|
||||
const { history, ...state } = get()
|
||||
const allStates = [...history.past, history.present, ...history.future]
|
||||
const targetState = allStates[index]
|
||||
|
||||
if (!targetState) return
|
||||
|
||||
const newPast = allStates.slice(0, index)
|
||||
const newFuture = allStates.slice(index + 1)
|
||||
|
||||
set({
|
||||
...state,
|
||||
...targetState.state,
|
||||
history: {
|
||||
past: newPast,
|
||||
present: targetState,
|
||||
future: newFuture,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,5 @@ export interface HistoryActions {
|
||||
redo: () => void
|
||||
canUndo: () => boolean
|
||||
canRedo: () => boolean
|
||||
revertToHistoryState: (index: number) => void
|
||||
}
|
||||
Reference in New Issue
Block a user