-
Notifications
You must be signed in to change notification settings - Fork 32
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
Updates not visible in items before syncing #86
Comments
Yes, there are some rough edges here. The outbox API is structured around the idea of form submissions that may or may not have an associated model (the outbox actually predates the model API). The underlying principle is that the local model should not be updated until the item is synced with the server, to ensure you know whether you need to run a sync again (see https://wq.io/docs/outbox-js). The downside, of course, is that it is tricky to do a lot of work offline with interrelated editable models. In the long term, I could see switching the logic around so that the model API always has your latest local version, with a flag to indicate whether a particular record has been synced or not. In the short term, it is possible to workaround these issues with some tricks. Displaying and editing and outbox mostly work already - as long as you only use the outbox URLs ( // Hack to override postsave/presync activity (should really have a plugin hook for this)
var _appPostsave = app.postsave;
app.postsave = function(item, backgroundSync) {
var id = getId(item);
if (id && backgroundSync) {
return app.models[item.options.modelConf.name].remove(id).then(function() {
return _appPostsave(item, backgroundSync);
});
} else {
return _appPostsave(item, backgroundSync);
}
};
function getId(item) {
// id is usually only detectable from the URL (it's not a form field)
// c.f. _renderOutboxItem
var idMatch = item.options.url.match(
new RegExp(item.options.modelConf.url + '/([^\/]+)$')
);
if (idMatch) {
return idMatch[1];
}
} Unfortunately, this will temporarily break any foreign key links from other related models. One workaround for this would be to set up a context plugin that would detect this situation: define(['wq/outbox'], function(outbox) {
return {
'context': function(ctx, routeInfo) {
if (routeInfo.page != 'childrecord') {
return;
}
var context = {};
outbox.model.load().then(function(items) {
items.list.forEach(function(item) {
if (item.options.modelConf.name == 'parentrecord') {
if (getId(item) == ctx.parentrecord_id) {
context['parentrecord_outbox_id'] = item.id;
}
}
});
})
}
};
}); Then you would need to detect this in the template: <!-- childrecord_detail.html -->
<html>
<h1>{{label}}</h1>
{{#parentrecord_outbox_id}}
<a href="{{rt}}/outbox/{{parentrecord_outbox_id}}">{{parentrecord_label}}</a>
{{/parentrecord_outbox_id}}
{{^parentrecord_outbox_id}}
<a href="{{rt}}/parentrecords/{{parentrecord_id}}">{{parentrecord_label}}</a>
{{/parentrecord_outbox_id}}
</html> |
Thanks a lot! |
Ok... so you could do the same thing I did in 68efcba, which is essentially to make more router.register('outbox/<slug>/childrecords', function() {
// generate context and render page
});
router.addRoute('outbox/<slug>/childrecords', 's', function() {
// run plugins
}); But, I'm starting to be convinced that having all of these duplicate routes is unecessary. I would be willing to support a boolean configuration option, off by default (for now), that will automatically update the local models as soon as the form is saved. Once you turn it on, the outbox would then only be for showing sync status, and you wouldn't need to access any of the For now, you can emulate this by updating instead of deleting the unedited record: // Hack to override postsave/presync activity (should really have a plugin hook for this)
var _appPostsave = app.postsave;
app.postsave = function(item, backgroundSync) {
if (backgroundSync) {
// FIXME: handle JSON forms (see app.js)
// _parseJsonForm(item)
var newRecord = item.data;
newRecord.id = getId(item) || 'outbox-' + item.id;
// FIXME: avoid having two outbox records for the same record
// (be sure to erase after sync)
// newRecord.outbox_id = item.id
return app.models[item.options.modelConf.name].update([newRecord]).then(function() {
return _appPostsave(item, backgroundSync);
});
} else {
return _appPostsave(item, backgroundSync);
}
}; You could then use the stock templates and routes mostly as-is, except that you'd might want to disable or modify the links in the Note: This approach assigns a temporary id ( |
Thanks! |
There's no official hook but you could do it after app.prefetchAll().then(recopyOutboxItems); You could also just remove the default call to |
Thank you. With these steps I managed to move forward several steps, but I think new items don't get properly copied and I need workarounds in templates. |
Any chance that you looked at these modifications? If not, I can try to start working on them. |
Hi, I haven't had a chance to look at this yet. If I implement it myself, it will probably be some time after the 1.0 release. If you can work on it, I can certainly review and hopefully merge your changes before then. |
I found a universal offline storage library that (among other features) allows overlaying pending changes as "offline effects". It can also use localForage as its backend. If integrated with the wq models API it would allow easy customizations for each of the models. |
I didn't manage to implement these updates, but I'm steadily interested in resolving this issue. |
I finally had a chance to look at redux-offline and agree it could address a lot of syncing issues (or at least make them easier to reason about). See #105 for more thoughts. |
I just noticed another project that could solve these issues: It supports "shredders", which can be used to filter results while offline. |
I was finally able to integrate redux-offline for the outbox (see #113). From there, it was mostly a matter of supporting multiple strategies for dispatching model state updates (6580895). In the default (backwards-compatible) mode, a I updated the outbox documentation here: https://wq.io/1.2/docs/outbox-js I imagine there may be a few edge cases to sort out, but this seems to be working pretty well overall. Let me know if you have any thoughts on the API. I am hoping to address most of the outbox issues for the wq.app 1.2 release. |
An updated item is "cloned to the outbox", with the original one's data not updated. This poses a problem, because I'd like to edit and display different objects while offline.
Are there any plans to support this use case? Any ideas for a solution or a workaround would also be very valuable. I'd also like to be able to update items several times before syncing.
I thought about patching
model.find
to overwrite fields from a corresponding item (by id) if it exists inunsyncedItems
, but it may slow down the API significantly. Maybe just updating the local item when creating one is created in the outbox?The text was updated successfully, but these errors were encountered: