Implement an undelete function to mass-undelete changes.

master
Tom Hacohen 4 years ago
parent 728ac6124f
commit b394484f3c

@ -20,6 +20,106 @@ import IconError from '@material-ui/icons/Error';
import { TaskType, EventType, ContactType, parseString } from '../pim-types'; import { TaskType, EventType, ContactType, parseString } from '../pim-types';
import * as EteSync from 'etesync'; import * as EteSync from 'etesync';
import LoadingIndicator from '../widgets/LoadingIndicator';
import { useCredentials } from '../login';
import { createJournalEntry } from '../etesync-helpers';
import { useSelector, useDispatch } from 'react-redux';
import { StoreState } from '../store';
import { addEntries } from '../store/actions';
interface RollbackToHereDialogPropsType {
journal: EteSync.Journal;
entries: Immutable.List<EteSync.SyncEntry>;
entryUid: string;
open: boolean;
onClose: () => void;
}
function RollbackToHereDialog(props: RollbackToHereDialogPropsType) {
const [loading, setLoading] = React.useState(false);
const etesync = useCredentials();
const dispatch = useDispatch();
const userInfo = useSelector((state: StoreState) => state.cache.userInfo);
async function go() {
setLoading(true);
const changes = new Map<string, EteSync.SyncEntry>();
for (const entry of props.entries.reverse()) {
const comp = parseString(entry.content);
const itemComp = comp.getFirstSubcomponent('vevent') ?? comp.getFirstSubcomponent('vtodo') ?? comp;
const itemUid = itemComp.getFirstPropertyValue('uid');
if (itemUid && !changes.has(itemUid)) {
changes.set(itemUid, entry);
}
if (entry.uid === props.entryUid) {
break;
}
}
const last = props.entries.last(null);
const lastUid = last?.uid ? last.uid : null;
// XXX implement chunked push most likely...
let prevUid = lastUid;
const journalItems = [];
for (const syncEntry of changes.values()) {
if (syncEntry.action === EteSync.SyncEntryAction.Delete) {
const ret = createJournalEntry(etesync, userInfo, props.journal, prevUid, EteSync.SyncEntryAction.Add, syncEntry.content);
journalItems.push(ret);
prevUid = ret.uid;
}
}
if (journalItems.length > 0) {
await dispatch<any>(
addEntries(etesync, props.journal.uid, journalItems, lastUid)
);
}
props.onClose();
}
return (
<Dialog
open={props.open}
onClose={props.onClose}
>
<DialogTitle>
Recover items
</DialogTitle>
<DialogContent>
{loading ? (
<LoadingIndicator style={{ display: 'block', margin: 'auto' }} />
) : (
<p>
This function restores all of the deleted items that happened after this change entry. It will not modify any items that haven't been changed since the item was deleted.
</p>
)}
</DialogContent>
<DialogActions>
<Button
color="primary"
disabled={loading}
onClick={props.onClose}
>
Cancel
</Button>
<Button
color="primary"
disabled={loading}
onClick={go}
>
Go
</Button>
</DialogActions>
</Dialog>
);
}
class JournalEntries extends React.PureComponent { class JournalEntries extends React.PureComponent {
public static defaultProps = { public static defaultProps = {
@ -27,7 +127,8 @@ class JournalEntries extends React.PureComponent {
}; };
public state: { public state: {
dialog?: string; dialog?: EteSync.SyncEntry;
rollbackDialogId?: string;
}; };
public props: { public props: {
@ -63,7 +164,7 @@ class JournalEntries extends React.PureComponent {
secondaryText="Unknown" secondaryText="Unknown"
onClick={() => { onClick={() => {
this.setState({ this.setState({
dialog: syncEntry.content, dialog: syncEntry,
}); });
}} }}
/> />
@ -113,7 +214,7 @@ class JournalEntries extends React.PureComponent {
secondaryText={uid} secondaryText={uid}
onClick={() => { onClick={() => {
this.setState({ this.setState({
dialog: syncEntry.content, dialog: syncEntry,
}); });
}} }}
/> />
@ -122,6 +223,13 @@ class JournalEntries extends React.PureComponent {
return ( return (
<div> <div>
<RollbackToHereDialog
journal={this.props.journal}
entries={this.props.entries}
entryUid={this.state.rollbackDialogId!}
open={!!this.state.rollbackDialogId}
onClose={() => this.setState({ rollbackDialogId: undefined })}
/>
<Dialog <Dialog
open={this.state.dialog !== undefined} open={this.state.dialog !== undefined}
onClose={() => { onClose={() => {
@ -132,9 +240,18 @@ class JournalEntries extends React.PureComponent {
Raw Content Raw Content
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<pre>{this.state.dialog}</pre> <pre>{this.state.dialog?.content}</pre>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button
color="primary"
onClick={() => this.setState({
dialog: undefined,
rollbackDialogId: this.state.dialog?.uid,
})}
>
Recover items until here
</Button>
<Button <Button
color="primary" color="primary"
onClick={() => { onClick={() => {

Loading…
Cancel
Save