mavo icon indicating copy to clipboard operation
mavo copied to clipboard

Allow (backend) plugin authors to pass the `conflictPolicy` property when firing the `mv-remotedatachange` event

Open DmitrySharabin opened this issue 2 years ago • 2 comments

In the upcoming version of Mavo, we give plugin authors a way to tell Mavo that data on the backend changed. To do so, they can fire the mv-remotedatachange event with (optional) data property with some new data. Like so:

$.fire(this, "mv-remotedatachange", {data});

However, working on the Google Calendar plugin, I noticed that when I try to create an event by specifying its fields (title, start date and time, end date and time, etc.), the newly created event doesn't show up in the list of events. Even though it was added to the calendar. I needed to refresh the page to see the new event. I couldn't understand why that happened. And after a bit of debugging, I could manage to find the cause.

Mind the following code snippet:

<article property="event">
  <input property="summary" value="Event Summary" />
  <p property="start">Start: <input type="datetime-local" property="dateTime" /></p>
  <p property="end">End: <input type="datetime-local" property="dateTime" /></p>
</article>

Changing any of those properties (either summary, or dateTime) will switch the unsavedChanges flag on. Firing the mv-remotedatachange will invoke Mavo.push(): https://github.com/mavoweb/mavo/blob/2bded90708765dddd8e274e6eec6b96bb5f7e442/src/mavo.js#L498

Mavo.push() in its turn will invoke Mavo.load() but only if there are no unsaved changes (unsavedChanges === false) or conflictPolicy === "force", or conflictPolicy === "ask" and the user confirmed loading of the new data:

https://github.com/mavoweb/mavo/blob/2bded90708765dddd8e274e6eec6b96bb5f7e442/src/mavo.js#L514-L528

However, in my case with the newly created event (from the code snippet above), I have unsaved changes (unsavedChanges === true) and conflictPolicy is equal to "stop" (the default value). So, Mavo.load() won't be triggered, and the remote data won't be loaded. That's why I couldn't see the newly created event in the event list.

It would be nice if we could pass the conflictPolicy parameter (property) with the mv-remotedatachange event. In my case, I would fire it this way:

$.fire(this, "mv-remotedatachange", {conflictPolicy: "force"});

I don't provide data here because Mavo will load (and render) it automatically.

DmitrySharabin avatar Jun 22 '22 21:06 DmitrySharabin

Thank you for such a detailed writeup. I don't understand one thing: to add the event to your calendar, you saved, right? Why was the unsavedChanges flag on after saving?

LeaVerou avatar Jun 23 '22 09:06 LeaVerou

Sorry, I didn't give you enough context. Let me fix it.

Technically, the Google Calendar plugin is read-only (there are neither put() nor store() methods). Even though Mavo provides the UI to modify the collection of events (add elements, update them, and delete), those changes won't have any effect (I wonder if it is possible to make the collection of events read-only on the plugin side? 🤔). There is no way for the user to save the changes back to the calendar.

Why did I follow this route? Unfortunately, I don't know the way to distinguish changes made by the user in the collection of events by looking at the data Mavo provides inside either store() or put() methods: which events were updated, which ones were created, and which ones were deleted. So I don't know which actions to perform on the user's calendar. Even if I get the collection of events itself, it will consist only of actual data (no deleted events), right?

However, I supposed that creating new events, updating and/or deleting the existing ones were the features end-users would love to have. And I decided to let authors provide those features to their users via custom actions: create_event(), update_event(), and delete_event(). So, authors can work with events, but they need to be explicit in their intentions.

And if we get back to the code snippet from above, the exact code would look like this (mind the Create Event button which is responsible for adding the event to the calendar):

<article property="event">
  <input property="summary" value="Event Summary" />
  <p property="start">Start: <input type="datetime-local" property="dateTime" /></p>
  <p property="end">End: <input type="datetime-local" property="dateTime" /></p>
</article>

<button mv-action="create_event(event)">Create Event</button>

As you can see, this action is performed without actually saving the whole collection of events back to the calendar. That's why the unsavedChanges flag remains on after adding/updating the event to/in the calendar—I don't invoke the save() method.

I might do something wrong and violate some Mavo principles. Please, let me know if I do.

Actually, in the plugin, everything is ready to let users modify events simply by working with the collection of events the way they used to by working with other collections, if we can distinguish newly added, updated, and deleted collection items.

Hope my explanations are clear enough. If not, don't hesitate to ask any questions. I'll do my best to find the correct wording.

Will this pen be helpful: https://codepen.io/dmitrysharabin/pen/rNJgjGV?

DmitrySharabin avatar Jun 23 '22 11:06 DmitrySharabin