Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel running requests when discarding or publishing content #7037

Merged
merged 2 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion panel/src/helpers/throttle.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default (
let last = null;
let trailing = null;

return function (...args) {
function throttled(...args) {
if (timer) {
last = this;
trailing = args;
Expand All @@ -42,5 +42,17 @@ export default (
};

timer = setTimeout(cooled, delay);
}

// Add cancel method to clear the timeout
throttled.cancel = () => {
if (timer) {
clearTimeout(timer);
timer = null;
last = null;
trailing = null;
}
};

return throttled;
};
55 changes: 40 additions & 15 deletions panel/src/panel/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import throttle from "@/helpers/throttle.js";
*/
export default (panel) => {
const content = reactive({
/**
* Cancel any scheduled or ongoing save requests
*/
cancelSaving() {
// cancel any scheduled save requests
this.saveLazy.cancel();

// ensure to abort unfinished previous save request
// to avoid race conditions with older content
this.saveAbortController?.abort();
},

/**
* Returns an object with all changed fields
* @param {Object} env
Expand Down Expand Up @@ -42,21 +54,29 @@ export default (panel) => {
return;
}

// In the current view, we can use the existing
// lock state to determine if we can discard
if (this.isCurrent(env) === true && this.isLocked(env) === true) {
// Only discard changes from the current view
if (this.isCurrent(env) === false) {
throw new Error("Cannot discard content from another view");
}

// Check the lock state to determine if we can discard
if (this.isLocked(env) === true) {
throw new Error("Cannot discard locked changes");
}

// Cancel any ongoing save requests.
// The discard request will throw those
// changes away anyway.
this.cancelSaving();

// Start processing the request
this.isProcessing = true;

try {
await this.request("discard", {}, env);

// update the props for the current view
if (this.isCurrent(env)) {
panel.view.props.content = panel.view.props.originals;
}
panel.view.props.content = panel.view.props.originals;

this.emit("discard", {}, env);
} catch (error) {
Expand Down Expand Up @@ -182,19 +202,27 @@ export default (panel) => {
return;
}

if (this.isCurrent(env) === false) {
throw new Error("Cannot publish content from another view");
}

// Cancel any ongoing save requests.
// The publish request will submit the
// latest state of the form again.
this.cancelSaving();

// Start processing the request
this.isProcessing = true;

// Send updated values to API
try {
await this.request("publish", values, env);
await this.request("publish", this.merge(values, env), env);

// close the dialog if it is still open
this.dialog?.close();

// update the props for the current view
if (this.isCurrent(env) === true) {
panel.view.props.originals = panel.view.props.content;
}
panel.view.props.originals = panel.view.props.content;

this.emit("publish", { values }, env);
} catch (error) {
Expand Down Expand Up @@ -233,8 +261,6 @@ export default (panel) => {
* Saves any changes
*/
async save(values = {}, env = {}) {
this.isProcessing = true;

// ensure to abort unfinished previous save request
// to avoid race conditions with older content
this.saveAbortController?.abort();
Expand All @@ -243,8 +269,6 @@ export default (panel) => {
try {
await this.request("save", values, env);

this.isProcessing = false;

// close the dialog if it is still open
this.dialog?.close();

Expand Down Expand Up @@ -300,7 +324,8 @@ export default (panel) => {
// that we can use in the input event
content.saveLazy = throttle(content.save, 1000, {
leading: true,
trailing: true
trailing: true,
timer: content.timer
});

return content;
Expand Down