extension sync
This commit is contained in:
@@ -53,6 +53,12 @@ angular.module('app.frontend')
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadExtensionsPressed = function() {
|
||||
if(confirm("For your security, reloading extensions will disable any currently enabled repeat actions.")) {
|
||||
extensionManager.refreshExtensionsFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
this.changeServer = function() {
|
||||
apiController.setServer(this.serverData.url, true);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
class Extension extends Item {
|
||||
constructor(json) {
|
||||
super(json);
|
||||
_.merge(this, json);
|
||||
|
||||
this.actions = this.actions.map(function(action){
|
||||
return new Action(action);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Action {
|
||||
constructor(json) {
|
||||
_.merge(this, json);
|
||||
@@ -22,3 +11,44 @@ class Action {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Extension extends Item {
|
||||
constructor(json) {
|
||||
super(json);
|
||||
_.merge(this, json);
|
||||
|
||||
this.content_type = "Extension";
|
||||
}
|
||||
|
||||
mapContentToLocalProperties(contentObject) {
|
||||
super.mapContentToLocalProperties(contentObject)
|
||||
this.name = contentObject.name;
|
||||
this.url = contentObject.url;
|
||||
this.actions = contentObject.actions.map(function(action){
|
||||
return new Action(action);
|
||||
})
|
||||
}
|
||||
|
||||
updateFromExternalResponseItem(externalResponseItem) {
|
||||
_.merge(this, externalResponseItem);
|
||||
this.actions = externalResponseItem.actions.map(function(action){
|
||||
return new Action(action);
|
||||
})
|
||||
}
|
||||
|
||||
referenceParams() {
|
||||
return null;
|
||||
}
|
||||
|
||||
structureParams() {
|
||||
var params = {
|
||||
name: this.name,
|
||||
url: this.url,
|
||||
actions: this.actions
|
||||
};
|
||||
|
||||
_.merge(params, super.structureParams());
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ angular.module('app.frontend')
|
||||
return this.createRequestParamsForItem(item, options.additionalFields);
|
||||
}.bind(this));
|
||||
|
||||
console.log("syncing items", request.items);
|
||||
// console.log("syncing items", request.items);
|
||||
|
||||
if(this.syncToken) {
|
||||
request.sync_token = this.syncToken;
|
||||
|
||||
@@ -1,28 +1,78 @@
|
||||
class ExtensionManager {
|
||||
|
||||
constructor(Restangular, modelManager) {
|
||||
constructor(Restangular, modelManager, apiController) {
|
||||
this.Restangular = Restangular;
|
||||
this.modelManager = modelManager;
|
||||
this.extensions = [];
|
||||
this.enabledRepeatActions = [];
|
||||
this.enabledRepeatActionUrls = localStorage.getItem("enabled_ext_urls") || [];
|
||||
this.apiController = apiController;
|
||||
this.enabledRepeatActionUrls = JSON.parse(localStorage.getItem("enabledRepeatActionUrls")) || [];
|
||||
|
||||
modelManager.addItemSyncObserver("extensionManager", "Extension", function(items){
|
||||
for (var ext of items) {
|
||||
for (var action of ext.actions) {
|
||||
if(this.enabledRepeatActionUrls.includes(action.url)) {
|
||||
this.enableRepeatAction(action, ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
get extensions() {
|
||||
return this.modelManager.extensions;
|
||||
}
|
||||
|
||||
actionWithURL(url) {
|
||||
for (var extension of this.extensions) {
|
||||
return _.find(extension.actions, {url: url})
|
||||
}
|
||||
}
|
||||
|
||||
addExtension(url) {
|
||||
this.retrieveExtensionFromServer(url, null);
|
||||
}
|
||||
|
||||
retrieveExtensionFromServer(url, callback) {
|
||||
console.log("Registering URL", url);
|
||||
this.Restangular.oneUrl(url, url).get().then(function(response){
|
||||
console.log("get response", response.plain());
|
||||
var extension = new Extension(response.plain());
|
||||
this.registerExtension(extension);
|
||||
var ext = this.handleExtensionLoadExternalResponseItem(url, response.plain());
|
||||
if(callback) {
|
||||
callback(ext);
|
||||
}
|
||||
}.bind(this))
|
||||
.catch(function(response){
|
||||
console.log("Error registering extension", response);
|
||||
})
|
||||
}
|
||||
|
||||
registerExtension(extension) {
|
||||
this.extensions.push(extension);
|
||||
console.log("registered extensions", this.extensions);
|
||||
handleExtensionLoadExternalResponseItem(url, externalResponseItem) {
|
||||
var extension = _.find(this.extensions, {url: url});
|
||||
if(extension) {
|
||||
extension.updateFromExternalResponseItem(externalResponseItem);
|
||||
console.log("updated existing ext", extension);
|
||||
} else {
|
||||
console.log("creating new ext", externalResponseItem);
|
||||
extension = new Extension(externalResponseItem);
|
||||
extension.url = url;
|
||||
extension.dirty = true;
|
||||
this.modelManager.addItem(extension);
|
||||
this.apiController.sync(null);
|
||||
}
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
refreshExtensionsFromServer() {
|
||||
for (var url of this.enabledRepeatActionUrls) {
|
||||
var action = this.actionWithURL(url);
|
||||
this.disableRepeatAction(action);
|
||||
}
|
||||
|
||||
for(var ext of this.extensions) {
|
||||
this.retrieveExtensionFromServer(ext.url, function(extension){
|
||||
extension.dirty = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
executeAction(action, extension, callback) {
|
||||
@@ -43,46 +93,71 @@ class ExtensionManager {
|
||||
disableRepeatAction(action, extension) {
|
||||
console.log("Disabling action", action);
|
||||
_.pull(this.enabledRepeatActionUrls, action.url);
|
||||
_.pull(this.enabledRepeatActions, action);
|
||||
this.modelManager.removeItemObserver(action.url);
|
||||
this.modelManager.removeItemSyncObserver(action.url);
|
||||
console.assert(this.isRepeatActionEnabled(action) == false);
|
||||
}
|
||||
|
||||
enableRepeatAction(action, extension) {
|
||||
console.log("Enabling repeat action", action);
|
||||
|
||||
this.enabledRepeatActionUrls.push(action.url);
|
||||
this.enabledRepeatActions.push(action);
|
||||
if(!_.find(this.enabledRepeatActionUrls, action.url)) {
|
||||
this.enabledRepeatActionUrls.push(action.url);
|
||||
localStorage.setItem("enabledRepeatActionUrls", JSON.stringify(this.enabledRepeatActionUrls));
|
||||
}
|
||||
|
||||
if(action.repeatType == "watch") {
|
||||
for(var structure of action.structures) {
|
||||
this.modelManager.addItemObserver(action.url, structure.type, function(changedItems){
|
||||
this.modelManager.addItemSyncObserver(action.url, structure.type, function(changedItems){
|
||||
this.triggerWatchAction(action, changedItems);
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queueAction(action, delay, changedItems) {
|
||||
this.actionQueue = this.actionQueue || [];
|
||||
if(_.find(this.actionQueue, action)) {
|
||||
// console.log("Action already queued, skipping.")
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log("Adding action to queue", action);
|
||||
|
||||
this.actionQueue.push(action);
|
||||
|
||||
setTimeout(function () {
|
||||
console.log("Performing queued action", action);
|
||||
this.triggerWatchAction(action, changedItems);
|
||||
_.pull(this.actionQueue, action);
|
||||
}.bind(this), delay * 1000);
|
||||
}
|
||||
|
||||
triggerWatchAction(action, changedItems) {
|
||||
console.log("Watch action triggered", action, changedItems);
|
||||
// console.log("Watch action triggered", action, changedItems);
|
||||
if(action.repeatFrequency > 0) {
|
||||
var lastExecuted = action.lastExecuted;
|
||||
var diffInSeconds = (new Date() - lastExecuted)/1000;
|
||||
console.log("last executed", action.lastExecuted, "diff", diffInSeconds, "repeatFreq", action.repeatFrequency);
|
||||
if(diffInSeconds < action.repeatFrequency) {
|
||||
console.log("too frequent, returning");
|
||||
var delay = action.repeatFrequency - diffInSeconds;
|
||||
console.log("delaying action by", delay);
|
||||
this.queueAction(action, delay, changedItems);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Performing action immediately", action);
|
||||
action.lastExecuted = new Date();
|
||||
// console.log("setting last exectured", action.lastExecuted)
|
||||
|
||||
if(action.repeatVerb == "post") {
|
||||
var request = this.Restangular.oneUrl(action.url, action.url);
|
||||
request.items = changedItems.map(function(item){
|
||||
var params = {uuid: item.uuid, content_type: item.content_type, content: item.content};
|
||||
var params = {uuid: item.uuid, content_type: item.content_type, content: item.createContentJSONFromProperties()};
|
||||
return params;
|
||||
})
|
||||
request.post().then(function(response){
|
||||
console.log("watch action response", response);
|
||||
action.lastExecuted = new Date();
|
||||
// console.log("watch action response", response);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ class ModelManager {
|
||||
constructor() {
|
||||
this.notes = [];
|
||||
this.tags = [];
|
||||
this.changeObservers = [];
|
||||
this.itemSyncObservers = [];
|
||||
this.items = [];
|
||||
this.extensions = [];
|
||||
}
|
||||
|
||||
findItem(itemId) {
|
||||
@@ -44,6 +45,13 @@ class ModelManager {
|
||||
models.push(item)
|
||||
}
|
||||
|
||||
for(var observer of this.itemSyncObservers) {
|
||||
var relevantItems = models.filter(function(item){return item.content_type == observer.type});
|
||||
if(relevantItems.length > 0) {
|
||||
observer.callback(relevantItems);
|
||||
}
|
||||
}
|
||||
|
||||
this.sortItems();
|
||||
return models;
|
||||
}
|
||||
@@ -53,6 +61,8 @@ class ModelManager {
|
||||
return new Note(json_obj);
|
||||
} else if(json_obj.content_type == "Tag") {
|
||||
return new Tag(json_obj);
|
||||
} else if(json_obj.content_type == "Extension") {
|
||||
return new Extension(json_obj);
|
||||
} else {
|
||||
return new Item(json_obj);
|
||||
}
|
||||
@@ -70,6 +80,10 @@ class ModelManager {
|
||||
if(!_.find(this.notes, {uuid: item.uuid})) {
|
||||
this.notes.unshift(item);
|
||||
}
|
||||
} else if(item.content_type == "Extension") {
|
||||
if(!_.find(this.extensions, {uuid: item.uuid})) {
|
||||
this.extensions.unshift(item);
|
||||
}
|
||||
}
|
||||
}.bind(this))
|
||||
}
|
||||
@@ -85,7 +99,6 @@ class ModelManager {
|
||||
}
|
||||
|
||||
resolveReferencesForItem(item) {
|
||||
|
||||
var contentObject = item.contentObject;
|
||||
if(!contentObject.references) {
|
||||
return;
|
||||
@@ -100,7 +113,6 @@ class ModelManager {
|
||||
console.log("Unable to find item:", reference.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sortItems() {
|
||||
@@ -111,33 +123,23 @@ class ModelManager {
|
||||
})
|
||||
}
|
||||
|
||||
addItemObserver(id, type, callback) {
|
||||
this.changeObservers.push({id: id, type: type, callback: callback});
|
||||
addItemSyncObserver(id, type, callback) {
|
||||
this.itemSyncObservers.push({id: id, type: type, callback: callback});
|
||||
}
|
||||
|
||||
removeItemObserver(id) {
|
||||
_.remove(this.changeObservers, _.find(this.changeObservers, {id: id}));
|
||||
removeItemSyncObserver(id) {
|
||||
_.remove(this.itemSyncObservers, _.find(this.itemSyncObservers, {id: id}));
|
||||
}
|
||||
|
||||
get filteredNotes() {
|
||||
return Note.filterDummyNotes(this.notes);
|
||||
}
|
||||
|
||||
notifyObserversOfSyncCompletion() {
|
||||
for(var observer of this.changeObservers) {
|
||||
var changedItems = this.dirtyItems.filter(function(item){return item.content_type == observer.type});
|
||||
console.log("observer:", observer, "items", changedItems);
|
||||
observer.callback(changedItems);
|
||||
}
|
||||
}
|
||||
|
||||
getDirtyItems() {
|
||||
return this.items.filter(function(item){return item.dirty == true && !item.dummy})
|
||||
}
|
||||
|
||||
clearDirtyItems() {
|
||||
this.notifyObserversOfSyncCompletion();
|
||||
|
||||
this.getDirtyItems().forEach(function(item){
|
||||
item.dirty = false;
|
||||
})
|
||||
@@ -156,6 +158,8 @@ class ModelManager {
|
||||
_.pull(this.tags, item);
|
||||
} else if(item.content_type == "Note") {
|
||||
_.pull(this.notes, item);
|
||||
} else if(item.content_type == "Extension") {
|
||||
_.pull(this.extensions, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user