Skip to content

Commit

Permalink
Make all content methods api dependent and add checks
Browse files Browse the repository at this point in the history
  • Loading branch information
bastianallgeier committed Nov 18, 2024
1 parent ea291b1 commit b017ccc
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 57 deletions.
65 changes: 13 additions & 52 deletions panel/src/components/Views/ModelView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default {
mounted() {
// create a delayed version of save
// that we can use in the input event
this.autosave = throttle(this.save, 1000, {
this.save = throttle(this.save, 1000, {
leading: true,
trailing: true
});
Expand All @@ -89,76 +89,46 @@ export default {
this.$events.on("model.reload", this.$reload);
this.$events.on("keydown.left", this.toPrev);
this.$events.on("keydown.right", this.toNext);
this.$events.on("view.save", this.onSave);
this.$events.on("view.save", this.onSubmitShortcut);
},
destroyed() {
this.$events.off("beforeunload", this.onBeforeUnload);
this.$events.off("model.reload", this.$reload);
this.$events.off("keydown.left", this.toPrev);
this.$events.off("keydown.right", this.toNext);
this.$events.off("view.save", this.onSave);
this.$events.off("view.save", this.onSubmitShortcut);
},
methods: {
async save(api, values) {
if (this.isLocked === true) {
return false;
}
await this.$panel.content.save(api, values);
// update the last modification timestamp
// if the view hasn't changed in the meantime,
// in which case the correct timestamp will come
// from the server
if (api === this.api) {
this.$panel.view.props.lock.modified = new Date();
}
async save(values) {
await this.$panel.content.save(values, this.api);
this.isSaved = true;
},
onBeforeUnload(e) {
if (this.isSaved === false) {
if (this.$panel.content.isProcessing === true || this.isSaved === false) {
e.preventDefault();
e.returnValue = "";
}
},
async onDiscard() {
if (this.isLocked === true) {
return false;
}
await this.$panel.content.discard(this.api);
this.$panel.view.props.content = this.$panel.view.props.originals;
this.$panel.view.reload();
},
onInput(values) {
if (this.isLocked === true) {
return false;
}
this.update(values);
this.autosave(this.api, values);
},
onSave(e) {
e?.preventDefault?.();
this.onSubmit();
this.save(values);
},
async onSubmit(values = {}) {
if (this.isLocked === true) {
return false;
}
this.update(values);
await this.$panel.content.publish(values, this.api);
await this.$panel.content.publish(this.api, this.content);
this.$panel.view.props.originals = this.content;
this.$panel.notification.success();
this.$events.emit("model.update");
await this.$panel.view.refresh();
},
onSubmitShortcut(e) {
e?.preventDefault?.();
this.onSubmit();
},
toPrev(e) {
if (this.prev && e.target.localName === "body") {
this.$go(this.prev.link);
Expand All @@ -170,16 +140,7 @@ export default {
}
},
update(values) {
if (length(values) === 0) {
return;
}
this.$panel.view.props.content = {
...this.originals,
...values
};
this.isSaved = false;
this.$panel.content.update(values, this.api);
}
}
};
Expand Down
77 changes: 72 additions & 5 deletions panel/src/panel/content.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { reactive } from "vue";
import { length } from "@/helpers/object";
import { reactive, set } from "vue";

Check failure on line 2 in panel/src/panel/content.js

View workflow job for this annotation

GitHub Actions / Coding Style

'set' is defined but never used

/**
* @since 5.0.0
Expand All @@ -8,20 +9,50 @@ export default (panel) => {
/**
* Removes all unpublished changes
*/
async discard(api) {
async discard(api = panel.view.props.api) {
if (this.isProcessing === true) {
return;
}

if (this.isCurrent(api) === true && this.isLocked(api) === true) {
throw new Error("Cannot discard locked changes");
}

this.isProcessing = true;

try {
await panel.api.post(api + "/changes/discard");

if (this.isCurrent(api)) {
panel.view.props.content = panel.view.props.originals;
}
} finally {
this.isProcessing = false;
}
},

/**
* Whether the api endpoint belongs to the current view
* @var {Boolean}
*/
isCurrent(api) {
return panel.view.props.api === api;
},

/**
* Whether the current view is locked
* @var {Boolean}
*/
isLocked(api = panel.view.props.api) {
if (this.isCurrent(api) === false) {
throw new Error(
"The lock state cannot be detected for content from in another view"
);
}

return panel.view.props.lock.isLocked;
},

/**
* Whether content is currently being discarded, saved or published
* @var {Boolean}
Expand All @@ -31,16 +62,25 @@ export default (panel) => {
/**
* Publishes any changes
*/
async publish(api, values) {
async publish(values, api = panel.view.props.api) {
if (this.isProcessing === true) {
return;
}

if (this.isCurrent(api) === true && this.isLocked(api) === true) {
throw new Error("Cannot publish locked changes");
}

this.isProcessing = true;
this.update(api, values);

// Send updated values to API
try {
await panel.api.post(api + "/changes/publish", values);

if (this.isCurrent(api)) {
panel.view.props.originals = panel.view.props.content;
}
} finally {
this.isProcessing = false;
}
Expand All @@ -49,7 +89,11 @@ export default (panel) => {
/**
* Saves any changes
*/
async save(api, values) {
async save(values, api = panel.view.props.api) {
if (this.isCurrent(api) === true && this.isLocked(api) === true) {
throw new Error("Cannot save locked changes");
}

this.isProcessing = true;

// ensure to abort unfinished previous save request
Expand All @@ -64,6 +108,11 @@ export default (panel) => {
});

this.isProcessing = false;

// update the lock info
if (this.isCurrent(api) === true) {
panel.view.props.lock.modified = new Date();
}
} catch (error) {
// silent aborted requests, but throw all other errors
if (error.name !== "AbortError") {
Expand All @@ -77,6 +126,24 @@ export default (panel) => {
* @internal
* @var {AbortController}
*/
saveAbortController: null
saveAbortController: null,

/**
* Updates the form values of the current view
*/
update(values, api = panel.view.props.api) {
if (length(values) === 0) {
return;
}

if (this.isCurrent(api) === false) {
throw new Error("The content in another view cannot be updated");
}

panel.view.props.content = {
...panel.view.props.originals,
...values
};
}
});
};

0 comments on commit b017ccc

Please sign in to comment.