fixed pending state logic

This commit is contained in:
Carter 2026-06-24 14:16:54 -06:00
parent 895ed8e50b
commit 879a5ae1f0

View file

@ -70,6 +70,11 @@ interface Props {
refreshCallback: () => void; refreshCallback: () => void;
} }
interface PendingInteraction {
since: string;
accepted: boolean;
}
export default function InteractionsOverview(props: Props) { export default function InteractionsOverview(props: Props) {
const classes = useStyles(); const classes = useStyles();
const [{as, user}] = useGlobalState(); const [{as, user}] = useGlobalState();
@ -81,7 +86,7 @@ export default function InteractionsOverview(props: Props) {
const [interactions, setInteractions] = useState<Interaction[]>(props.interactions); const [interactions, setInteractions] = useState<Interaction[]>(props.interactions);
const [dirtyInteractions, setDirtyInteractions] = useState<Map<number, boolean>>(new Map()); const [dirtyInteractions, setDirtyInteractions] = useState<Map<number, boolean>>(new Map());
const [mappedComponents, setMappedComponents] = useState<Map<string, Component>>(new Map()); const [mappedComponents, setMappedComponents] = useState<Map<string, Component>>(new Map());
const [acceptedInteractions, setAcceptedInteractions] = useState<Set<string>>(new Set()); const [pendingInteractions, setPendingInteractions] = useState<Map<string, PendingInteraction>>(new Map());
const [renderToggle, setRenderToggle] = useState(false); const [renderToggle, setRenderToggle] = useState(false);
const [selectedInteraction, setSelectedInteraction] = useState<Interaction | undefined>( const [selectedInteraction, setSelectedInteraction] = useState<Interaction | undefined>(
undefined undefined
@ -97,20 +102,23 @@ export default function InteractionsOverview(props: Props) {
} }
if (props.interactions !== prevInteractions) { if (props.interactions !== prevInteractions) {
if (prevInteractions) { setPendingInteractions((prevPending) => {
setAcceptedInteractions((prevAccepted) => { const updatedPending = new Map(prevPending);
const updatedAccepted = new Set(prevAccepted);
props.interactions.forEach((interaction: Interaction) => { props.interactions.forEach((interaction: Interaction) => {
const previous = prevInteractions.find(prevInteraction => prevInteraction.key() === interaction.key()); const existing = updatedPending.get(interaction.key());
if (!interaction.status.synced) { if (!interaction.status.synced) {
updatedAccepted.delete(interaction.key()); if (!existing || existing.accepted) {
} else if (previous && !previous.status.synced) { updatedPending.set(interaction.key(), {
updatedAccepted.add(interaction.key()); since: interaction.status.lastUpdate || moment().toISOString(),
} accepted: false
});
return updatedAccepted;
}); });
} }
} else if (existing && !existing.accepted) {
updatedPending.set(interaction.key(), { ...existing, accepted: true });
}
});
return updatedPending;
});
setInteractions(cloneDeep(props.interactions)); setInteractions(cloneDeep(props.interactions));
} }
}, [components, prevComponents, props.interactions, prevInteractions]); }, [components, prevComponents, props.interactions, prevInteractions]);
@ -217,6 +225,14 @@ export default function InteractionsOverview(props: Props) {
index: number, index: number,
settings: pond.IInteractionSettings settings: pond.IInteractionSettings
) => { ) => {
const interactionKey = settings.key ?? "";
setPendingInteractions((prevPending) => {
const updatedPending = new Map(prevPending);
if (interactionKey) {
updatedPending.set(interactionKey, { since: moment().toISOString(), accepted: false });
}
return updatedPending;
});
interactionsAPI interactionsAPI
.updateInteraction(Number(deviceID), settings, as) .updateInteraction(Number(deviceID), settings, as)
.then((_response: any) => { .then((_response: any) => {
@ -224,7 +240,6 @@ export default function InteractionsOverview(props: Props) {
updatedDirtyInteractions.set(index, false); updatedDirtyInteractions.set(index, false);
setDirtyInteractions(updatedDirtyInteractions); setDirtyInteractions(updatedDirtyInteractions);
success("Successfully updated the interaction for " + component.name()); success("Successfully updated the interaction for " + component.name());
refreshCallback();
}) })
.catch((_err: any) => { .catch((_err: any) => {
error("Error occurred while updating the interaction for " + component.name()); error("Error occurred while updating the interaction for " + component.name());
@ -242,16 +257,13 @@ export default function InteractionsOverview(props: Props) {
let key = interaction.key(); let key = interaction.key();
let source = mappedComponents.get(componentIDToString(interaction.settings.source)); let source = mappedComponents.get(componentIDToString(interaction.settings.source));
let sink = mappedComponents.get(componentIDToString(interaction.settings.sink)); let sink = mappedComponents.get(componentIDToString(interaction.settings.sink));
const isPending = !interaction.status.synced && Boolean(interaction.status.lastUpdate); const pending = pendingInteractions.get(interaction.key());
const isAccepted = interaction.status.synced && acceptedInteractions.has(interaction.key()); const isAccepted = Boolean(pending?.accepted);
let statusText = const isPending = Boolean(pending && !pending.accepted);
!interaction.status.synced let statusText = isAccepted
? interaction.status.lastUpdate
? "Pending " +
moment(interaction.status.lastUpdate && interaction.status.lastUpdate).fromNow()
: ""
: acceptedInteractions.has(interaction.key())
? "Pending change accepted" ? "Pending change accepted"
: isPending
? "Pending " + moment(pending.since).fromNow()
: ""; : "";
let schedule = pond.InteractionSchedule.create( let schedule = pond.InteractionSchedule.create(
interaction.settings.schedule !== null ? interaction.settings.schedule : undefined interaction.settings.schedule !== null ? interaction.settings.schedule : undefined