import/export

This commit is contained in:
Mo Bitar
2016-12-16 12:39:32 -06:00
parent 15a227daa2
commit c8d0159223
13 changed files with 160 additions and 215 deletions

View File

@@ -123,7 +123,7 @@ angular.module('app.frontend')
this.downloadDataArchive = function() { this.downloadDataArchive = function() {
var link = document.createElement('a'); var link = document.createElement('a');
link.setAttribute('download', 'neeto.json'); link.setAttribute('download', 'neeto.json');
link.href = apiController.notesDataFile(this.user); link.href = apiController.itemsDataFile();
link.click(); link.click();
} }

View File

@@ -7,25 +7,17 @@ angular.module('app.frontend')
var onUserSet = function() { var onUserSet = function() {
apiController.setUser($scope.defaultUser); apiController.setUser($scope.defaultUser);
$scope.allTag = new Tag({all: true}); $scope.allTag = new Tag({all: true});
$scope.allTag.content.name = "All"; $scope.allTag.content.title = "All";
$scope.tags = modelManager.tags; $scope.tags = modelManager.tags;
// apiController.verifyEncryptionStatusOfAllItems($scope.defaultUser, function(success){}); // apiController.verifyEncryptionStatusOfAllItems($scope.defaultUser, function(success){});
} }
apiController.getCurrentUser(function(response){ apiController.getCurrentUser(function(user, items){
if(response && !response.errors) { if(user && items) {
console.log("Get user response", response); console.log("Get user response", user, items);
$scope.defaultUser = new User(response); $scope.defaultUser = user;
modelManager.items = _.map(response.items, function(json_obj){ modelManager.items = items;
if(json_obj.content_type == "Note") {
return new Note(json_obj);
} else if(json_obj.content_type == "Tag") {
return new Tag(json_obj);
} else {
return new Item(json_obj);
}
});
$rootScope.title = "Notes — Neeto"; $rootScope.title = "Notes — Neeto";
onUserSet(); onUserSet();
} else { } else {

View File

@@ -71,7 +71,7 @@ angular.module('app.frontend')
var originalTagName = ""; var originalTagName = "";
this.onTagTitleFocus = function(tag) { this.onTagTitleFocus = function(tag) {
originalTagName = tag.content.name; originalTagName = tag.content.title;
} }
this.tagTitleDidChange = function(tag) { this.tagTitleDidChange = function(tag) {
@@ -80,14 +80,14 @@ angular.module('app.frontend')
this.saveTag = function($event, tag) { this.saveTag = function($event, tag) {
this.editingTag = null; this.editingTag = null;
if(tag.content.name.length == 0) { if(tag.content.title.length == 0) {
tag.content.name = originalTagName; tag.content.title = originalTagName;
originalTagName = ""; originalTagName = "";
return; return;
} }
$event.target.blur(); $event.target.blur();
if(!tag.content.name || tag.content.name.length == 0) { if(!tag.content.title || tag.content.title.length == 0) {
return; return;
} }

View File

@@ -4,8 +4,8 @@ angular.module('app.frontend')
$scope.saveUsername = function() { $scope.saveUsername = function() {
apiController.setUsername(user, $scope.formData.username, function(response){ apiController.setUsername(user, $scope.formData.username, function(response){
var username = response.root_path; var username = response.username;
user.presentation = response; user.username = username;
callback(username); callback(username);
$scope.closeThisDialog(); $scope.closeThisDialog();
}) })

View File

@@ -60,6 +60,10 @@ class Item {
}); });
} }
mergeMetadataFromItem(item) {
_.merge(this, _.omit(item, ["content"]));
}
updateReferencesLocalMapping() { updateReferencesLocalMapping() {
// should be overriden to manage local properties // should be overriden to manage local properties
} }

View File

@@ -7,8 +7,8 @@ class Tag extends Item {
this.notes = []; this.notes = [];
} }
if(!this.content.name) { if(!this.content.title) {
this.content.name = ""; this.content.title = "";
} }
} }

View File

@@ -65,9 +65,11 @@ angular.module('app.frontend')
Restangular.one("users/current").get().then(function(response){ Restangular.one("users/current").get().then(function(response){
var plain = response.plain(); var plain = response.plain();
var items = plain.items; var items = plain.items;
console.log("retreived items", plain);
this.decryptItemsWithLocalKey(items); this.decryptItemsWithLocalKey(items);
callback(plain); items = this.mapResponseItemsToLocalModels(items);
var user = _.omit(plain, ["items"]);
console.log("retreived items", plain);
callback(user, items);
}.bind(this)) }.bind(this))
.catch(function(error){ .catch(function(error){
callback(null); callback(null);
@@ -205,12 +207,34 @@ angular.module('app.frontend')
request.post().then(function(response) { request.post().then(function(response) {
var savedItems = response.items; var savedItems = response.items;
this.decryptItemsWithLocalKey(savedItems);
items.forEach(function(item){
var savedCounterpart = _.find(savedItems, {uuid: item.uuid});
item.mergeMetadataFromItem(savedCounterpart);
})
console.log("response items", savedItems); console.log("response items", savedItems);
callback(response); callback(response);
}) }.bind(this))
}
this.mapResponseItemsToLocalModels = function(items) {
return _.map(items, function(json_obj){
if(json_obj.content_type == "Note") {
return new Note(json_obj);
} else if(json_obj.content_type == "Tag") {
return new Tag(json_obj);
} else {
return new Item(json_obj);
}
});
} }
this.createRequestParamsForItem = function(item) { this.createRequestParamsForItem = function(item) {
return this.paramsForItem(item, !item.isPublic(), null, false);
}
this.paramsForItem = function(item, encrypted, additionalFields, forExportFile) {
var itemCopy = _.cloneDeep(item); var itemCopy = _.cloneDeep(item);
var params = {uuid: item.uuid, content_type: item.content_type, presentation_name: item.presentation_name}; var params = {uuid: item.uuid, content_type: item.content_type, presentation_name: item.presentation_name};
@@ -219,17 +243,22 @@ angular.module('app.frontend')
return {uuid: reference.uuid, content_type: reference.content_type}; return {uuid: reference.uuid, content_type: reference.content_type};
}) })
if(!item.isPublic()) { if(encrypted) {
// encrypted
this.encryptSingleItem(itemCopy, this.retrieveGk()); this.encryptSingleItem(itemCopy, this.retrieveGk());
params.content = itemCopy.content; params.content = itemCopy.content;
params.loc_eek = itemCopy.loc_eek; params.loc_eek = itemCopy.loc_eek;
} }
else { else {
// decrypted params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content);
params.content = JSON.stringify(item.content); if(!forExportFile) {
params.loc_eek = null; params.loc_eek = null;
}
} }
if(additionalFields) {
_.merge(params, _.pick(item, additionalFields));
}
return params; return params;
} }
@@ -290,39 +319,19 @@ angular.module('app.frontend')
this.importJSONData = function(jsonString, callback) { this.importJSONData = function(jsonString, callback) {
var data = JSON.parse(jsonString); var data = JSON.parse(jsonString);
var user = new User(data); var customModelManager = new ModelManager();
customModelManager.items = this.mapResponseItemsToLocalModels(data.items);
console.log("importing data", JSON.parse(jsonString)); console.log("importing data", JSON.parse(jsonString));
user.items.forEach(function(item) { this.saveItems(customModelManager.items, function(response){
if(item.isPublic()) { callback(response);
item.setContentRaw(JSON.stringify(item.content)); });
} else {
this.encryptSingleItemWithLocalKey(item);
}
// prevent circular links
item.tag = null;
}.bind(this))
user.tags.forEach(function(tag){
// prevent circular links
tag.items = null;
})
var request = Restangular.one("import");
request.data = {items: user.items, tags: user.tags};
request.post().then(function(response){
callback(true, response);
})
.catch(function(error){
callback(false, error);
})
} }
/* /*
Export Export
*/ */
this.itemsDataFile = function(user) { this.itemsDataFile = function() {
var textFile = null; var textFile = null;
var makeTextFile = function (text) { var makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/json'}); var data = new Blob([text], {type: 'text/json'});
@@ -339,49 +348,12 @@ angular.module('app.frontend')
return textFile; return textFile;
}.bind(this); }.bind(this);
var presentationParams = function(presentation) { var items = _.map(modelManager.items, function(item){
if(!presentation) { return this.paramsForItem(item, false, ["created_at", "updated_at"], true)
return null; }.bind(this));
}
return {
id: presentation.uuid,
uuid: presentation.uuid,
root_path: presentation.root_path,
relative_path: presentation.relative_path,
presentable_type: presentation.presentable_type,
presentable_id: presentation.presentable_id,
created_at: presentation.created_at,
modified_at: presentation.modified_at,
}
}
var items = _.map(user.filteredItems(), function(item){
return {
id: item.uuid,
uuid: item.uuid,
content: item.content,
tag_id: item.tag_id,
created_at: item.created_at,
modified_at: item.modified_at,
presentation: presentationParams(item.presentation)
}
});
var tags = _.map(user.tags, function(tag){
return {
id: tag.uuid,
uuid: tag.uuid,
name: tag.name,
created_at: tag.created_at,
modified_at: tag.modified_at,
presentation: presentationParams(tag.presentation)
}
});
var data = { var data = {
items: items, items: items
tags: tags
} }
return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */)); return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */));
@@ -389,7 +361,6 @@ angular.module('app.frontend')
/* /*
Merging Merging
*/ */
@@ -400,7 +371,7 @@ angular.module('app.frontend')
request.items.forEach(function(item){ request.items.forEach(function(item){
if(item.tag_id) { if(item.tag_id) {
var tag = tags.filter(function(tag){return tag.uuid == item.tag_id})[0]; var tag = tags.filter(function(tag){return tag.uuid == item.tag_id})[0];
item.tag_name = tag.name; item.tag_name = tag.content.title;
} }
}) })
request.post().then(function(response){ request.post().then(function(response){

View File

@@ -15,10 +15,14 @@ class ItemManager {
resolveReferences() { resolveReferences() {
this.items.forEach(function(item){ this.items.forEach(function(item){
// build out references // build out references, safely handle broken references
item.content.references = _.map(item.content.references, function(reference){ item.content.references = _.reduce(item.content.references, function(accumulator, reference){
return this.referencesForItemId(reference.uuid); var item = this.referencesForItemId(reference.uuid);
}.bind(this)) if(item) {
accumulator.push(item);
}
return accumulator;
}.bind(this), []);
}.bind(this)); }.bind(this));
} }

View File

@@ -23,11 +23,11 @@
%li %li
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleMarkdown()"} Toggle Markdown Preview %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleMarkdown()"} Toggle Markdown Preview
.shortcut Cmd + M .shortcut Cmd + M
%li{"ng-if" => "!ctrl.note.presentation"} %li{"ng-if" => "!ctrl.note.isPublic()"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.shareNote()"} Share %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.shareNote()"} Share
%li{"ng-if" => "ctrl.note.presentation"} %li{"ng-if" => "ctrl.note.isPublic()"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.editUrlPressed()"} Edit URL %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.editUrlPressed()"} Edit URL
%li{"ng-if" => "ctrl.note.presentation"} %li{"ng-if" => "ctrl.note.isPublic()"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.unshareNote()"} Unshare %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.unshareNote()"} Unshare
%li %li
%a.text{"ng-click" => "ctrl.deleteNote()"} Delete %a.text{"ng-click" => "ctrl.deleteNote()"} Delete

View File

@@ -1,7 +1,7 @@
.section.notes .section.notes
.content .content
.section-title-bar.notes-title-bar .section-title-bar.notes-title-bar
.title {{ctrl.tag.name}} notes .title {{ctrl.tag.content.title}} notes
.add-button{"ng-click" => "ctrl.createNewNote()"} + .add-button{"ng-click" => "ctrl.createNewNote()"} +
%br %br
.filter-section .filter-section
@@ -14,14 +14,14 @@
%span.caret %span.caret
%span.sr-only %span.sr-only
%ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark{"ng-if" => "ctrl.showMenu"} %ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark{"ng-if" => "ctrl.showMenu"}
%li{"ng-if" => "!ctrl.tag.presentation"} %li{"ng-if" => "!ctrl.tag.isPublic()"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagShare($event)"} Share Tag %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagShare($event)"} Share Tag
%li{"ng-if" => "ctrl.tag.presentation"} %li{"ng-if" => "ctrl.tag.isPublic()"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagUnshare()"} Unshare Tag %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagUnshare()"} Unshare Tag
%li{"ng-if" => "!ctrl.tag.all"} %li{"ng-if" => "!ctrl.tag.all"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagDelete()"} Delete Tag %a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagDelete()"} Delete Tag
.menu-right-container .menu-right-container
.public-link{"ng-if" => "ctrl.tag.presentation"} .public-link{"ng-if" => "ctrl.tag.isPublic()"}
%a.url{"ng-if" => "!ctrl.editingUrl", "href" => "{{ctrl.tag.presentationURL()}}", "target" => "_blank"} %a.url{"ng-if" => "!ctrl.editingUrl", "href" => "{{ctrl.tag.presentationURL()}}", "target" => "_blank"}
%span.icon-rss.icon %span.icon-rss.icon
{{ctrl.tag.presentationURL()}} {{ctrl.tag.presentationURL()}}

View File

@@ -6,13 +6,13 @@
{{ctrl.test}} {{ctrl.test}}
.tag{"ng-if" => "ctrl.allTag", "ng-click" => "ctrl.selectTag(ctrl.allTag)", "ng-class" => "{'selected' : ctrl.selectedTag == ctrl.allTag}", .tag{"ng-if" => "ctrl.allTag", "ng-click" => "ctrl.selectTag(ctrl.allTag)", "ng-class" => "{'selected' : ctrl.selectedTag == ctrl.allTag}",
"droppable" => true, "drop" => "ctrl.handleDrop", "tag" => "ctrl.allTag"} "droppable" => true, "drop" => "ctrl.handleDrop", "tag" => "ctrl.allTag"}
%input.title{"ng-disabled" => "true", "ng-model" => "ctrl.allTag.content.name"} %input.title{"ng-disabled" => "true", "ng-model" => "ctrl.allTag.content.title"}
.count {{ctrl.noteCount(ctrl.allTag)}} .count {{ctrl.noteCount(ctrl.allTag)}}
.tag{"ng-repeat" => "tag in ctrl.tags", "ng-click" => "ctrl.selectTag(tag)", "ng-class" => "{'selected' : ctrl.selectedTag == tag}", .tag{"ng-repeat" => "tag in ctrl.tags", "ng-click" => "ctrl.selectTag(tag)", "ng-class" => "{'selected' : ctrl.selectedTag == tag}",
"droppable" => true, "drop" => "ctrl.handleDrop", "tag" => "tag"} "droppable" => true, "drop" => "ctrl.handleDrop", "tag" => "tag"}
.icon.icon-rss{"ng-if" => "tag.presentation"} .icon.icon-rss{"ng-if" => "tag.isPublic()"}
%input.title{"ng-disabled" => "tag != ctrl.selectedTag", "ng-model" => "tag.content.name", %input.title{"ng-disabled" => "tag != ctrl.selectedTag", "ng-model" => "tag.content.title",
"ng-keyup" => "$event.keyCode == 13 && ctrl.saveTag($event, tag)", "mb-autofocus" => "true", "should-focus" => "ctrl.newTag", "ng-keyup" => "$event.keyCode == 13 && ctrl.saveTag($event, tag)", "mb-autofocus" => "true", "should-focus" => "ctrl.newTag",
"ng-change" => "ctrl.tagTitleDidChange(tag)", "ng-focus" => "ctrl.onTagTitleFocus(tag)"} "ng-change" => "ctrl.tagTitleDidChange(tag)", "ng-focus" => "ctrl.onTagTitleFocus(tag)"}
.count {{ctrl.noteCount(tag)}} .count {{ctrl.noteCount(tag)}}

View File

@@ -517,7 +517,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
this.downloadDataArchive = function () { this.downloadDataArchive = function () {
var link = document.createElement('a'); var link = document.createElement('a');
link.setAttribute('download', 'neeto.json'); link.setAttribute('download', 'neeto.json');
link.href = apiController.notesDataFile(this.user); link.href = apiController.itemsDataFile();
link.click(); link.click();
}; };
@@ -560,25 +560,17 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
var onUserSet = function onUserSet() { var onUserSet = function onUserSet() {
apiController.setUser($scope.defaultUser); apiController.setUser($scope.defaultUser);
$scope.allTag = new Tag({ all: true }); $scope.allTag = new Tag({ all: true });
$scope.allTag.content.name = "All"; $scope.allTag.content.title = "All";
$scope.tags = modelManager.tags; $scope.tags = modelManager.tags;
// apiController.verifyEncryptionStatusOfAllItems($scope.defaultUser, function(success){}); // apiController.verifyEncryptionStatusOfAllItems($scope.defaultUser, function(success){});
}; };
apiController.getCurrentUser(function (response) { apiController.getCurrentUser(function (user, items) {
if (response && !response.errors) { if (user && items) {
console.log("Get user response", response); console.log("Get user response", user, items);
$scope.defaultUser = new User(response); $scope.defaultUser = user;
modelManager.items = _.map(response.items, function (json_obj) { modelManager.items = items;
if (json_obj.content_type == "Note") {
return new Note(json_obj);
} else if (json_obj.content_type == "Tag") {
return new Tag(json_obj);
} else {
return new Item(json_obj);
}
});
$rootScope.title = "Notes — Neeto"; $rootScope.title = "Notes — Neeto";
onUserSet(); onUserSet();
} else { } else {
@@ -910,7 +902,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
var originalTagName = ""; var originalTagName = "";
this.onTagTitleFocus = function (tag) { this.onTagTitleFocus = function (tag) {
originalTagName = tag.content.name; originalTagName = tag.content.title;
}; };
this.tagTitleDidChange = function (tag) { this.tagTitleDidChange = function (tag) {
@@ -919,14 +911,14 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
this.saveTag = function ($event, tag) { this.saveTag = function ($event, tag) {
this.editingTag = null; this.editingTag = null;
if (tag.content.name.length == 0) { if (tag.content.title.length == 0) {
tag.content.name = originalTagName; tag.content.title = originalTagName;
originalTagName = ""; originalTagName = "";
return; return;
} }
$event.target.blur(); $event.target.blur();
if (!tag.content.name || tag.content.name.length == 0) { if (!tag.content.title || tag.content.title.length == 0) {
return; return;
} }
@@ -951,8 +943,8 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
$scope.saveUsername = function () { $scope.saveUsername = function () {
apiController.setUsername(user, $scope.formData.username, function (response) { apiController.setUsername(user, $scope.formData.username, function (response) {
var username = response.root_path; var username = response.username;
user.presentation = response; user.username = username;
callback(username); callback(username);
$scope.closeThisDialog(); $scope.closeThisDialog();
}); });
@@ -1024,6 +1016,11 @@ var Item = function () {
return reference.content_type == contentType; return reference.content_type == contentType;
}); });
} }
}, {
key: 'mergeMetadataFromItem',
value: function mergeMetadataFromItem(item) {
_.merge(this, _.omit(item, ["content"]));
}
}, { }, {
key: 'updateReferencesLocalMapping', key: 'updateReferencesLocalMapping',
value: function updateReferencesLocalMapping() { value: function updateReferencesLocalMapping() {
@@ -1145,8 +1142,8 @@ var Tag = function (_Item2) {
_this2.notes = []; _this2.notes = [];
} }
if (!_this2.content.name) { if (!_this2.content.title) {
_this2.content.name = ""; _this2.content.title = "";
} }
return _this2; return _this2;
} }
@@ -1243,9 +1240,11 @@ var User = function User(json_obj) {
Restangular.one("users/current").get().then(function (response) { Restangular.one("users/current").get().then(function (response) {
var plain = response.plain(); var plain = response.plain();
var items = plain.items; var items = plain.items;
console.log("retreived items", plain);
this.decryptItemsWithLocalKey(items); this.decryptItemsWithLocalKey(items);
callback(plain); items = this.mapResponseItemsToLocalModels(items);
var user = _.omit(plain, ["items"]);
console.log("retreived items", plain);
callback(user, items);
}.bind(this)).catch(function (error) { }.bind(this)).catch(function (error) {
callback(null); callback(null);
}); });
@@ -1379,12 +1378,34 @@ var User = function User(json_obj) {
request.post().then(function (response) { request.post().then(function (response) {
var savedItems = response.items; var savedItems = response.items;
this.decryptItemsWithLocalKey(savedItems);
items.forEach(function (item) {
var savedCounterpart = _.find(savedItems, { uuid: item.uuid });
item.mergeMetadataFromItem(savedCounterpart);
});
console.log("response items", savedItems); console.log("response items", savedItems);
callback(response); callback(response);
}.bind(this));
};
this.mapResponseItemsToLocalModels = function (items) {
return _.map(items, function (json_obj) {
if (json_obj.content_type == "Note") {
return new Note(json_obj);
} else if (json_obj.content_type == "Tag") {
return new Tag(json_obj);
} else {
return new Item(json_obj);
}
}); });
}; };
this.createRequestParamsForItem = function (item) { this.createRequestParamsForItem = function (item) {
return this.paramsForItem(item, !item.isPublic(), null, false);
};
this.paramsForItem = function (item, encrypted, additionalFields, forExportFile) {
var itemCopy = _.cloneDeep(item); var itemCopy = _.cloneDeep(item);
var params = { uuid: item.uuid, content_type: item.content_type, presentation_name: item.presentation_name }; var params = { uuid: item.uuid, content_type: item.content_type, presentation_name: item.presentation_name };
@@ -1393,16 +1414,21 @@ var User = function User(json_obj) {
return { uuid: reference.uuid, content_type: reference.content_type }; return { uuid: reference.uuid, content_type: reference.content_type };
}); });
if (!item.isPublic()) { if (encrypted) {
// encrypted
this.encryptSingleItem(itemCopy, this.retrieveGk()); this.encryptSingleItem(itemCopy, this.retrieveGk());
params.content = itemCopy.content; params.content = itemCopy.content;
params.loc_eek = itemCopy.loc_eek; params.loc_eek = itemCopy.loc_eek;
} else { } else {
// decrypted params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content);
params.content = JSON.stringify(item.content); if (!forExportFile) {
params.loc_eek = null; params.loc_eek = null;
}
} }
if (additionalFields) {
_.merge(params, _.pick(item, additionalFields));
}
return params; return params;
}; };
@@ -1463,30 +1489,11 @@ var User = function User(json_obj) {
this.importJSONData = function (jsonString, callback) { this.importJSONData = function (jsonString, callback) {
var data = JSON.parse(jsonString); var data = JSON.parse(jsonString);
var user = new User(data); var customModelManager = new ModelManager();
customModelManager.items = this.mapResponseItemsToLocalModels(data.items);
console.log("importing data", JSON.parse(jsonString)); console.log("importing data", JSON.parse(jsonString));
user.items.forEach(function (item) { this.saveItems(customModelManager.items, function (response) {
if (item.isPublic()) { callback(response);
item.setContentRaw(JSON.stringify(item.content));
} else {
this.encryptSingleItemWithLocalKey(item);
}
// prevent circular links
item.tag = null;
}.bind(this));
user.tags.forEach(function (tag) {
// prevent circular links
tag.items = null;
});
var request = Restangular.one("import");
request.data = { items: user.items, tags: user.tags };
request.post().then(function (response) {
callback(true, response);
}).catch(function (error) {
callback(false, error);
}); });
}; };
@@ -1494,7 +1501,7 @@ var User = function User(json_obj) {
Export Export
*/ */
this.itemsDataFile = function (user) { this.itemsDataFile = function () {
var textFile = null; var textFile = null;
var makeTextFile = function (text) { var makeTextFile = function (text) {
var data = new Blob([text], { type: 'text/json' }); var data = new Blob([text], { type: 'text/json' });
@@ -1511,49 +1518,12 @@ var User = function User(json_obj) {
return textFile; return textFile;
}.bind(this); }.bind(this);
var presentationParams = function presentationParams(presentation) { var items = _.map(modelManager.items, function (item) {
if (!presentation) { return this.paramsForItem(item, false, ["created_at", "updated_at"], true);
return null; }.bind(this));
}
return {
id: presentation.uuid,
uuid: presentation.uuid,
root_path: presentation.root_path,
relative_path: presentation.relative_path,
presentable_type: presentation.presentable_type,
presentable_id: presentation.presentable_id,
created_at: presentation.created_at,
modified_at: presentation.modified_at
};
};
var items = _.map(user.filteredItems(), function (item) {
return {
id: item.uuid,
uuid: item.uuid,
content: item.content,
tag_id: item.tag_id,
created_at: item.created_at,
modified_at: item.modified_at,
presentation: presentationParams(item.presentation)
};
});
var tags = _.map(user.tags, function (tag) {
return {
id: tag.uuid,
uuid: tag.uuid,
name: tag.name,
created_at: tag.created_at,
modified_at: tag.modified_at,
presentation: presentationParams(tag.presentation)
};
});
var data = { var data = {
items: items, items: items
tags: tags
}; };
return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */)); return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */));
@@ -1571,7 +1541,7 @@ var User = function User(json_obj) {
var tag = tags.filter(function (tag) { var tag = tags.filter(function (tag) {
return tag.uuid == item.tag_id; return tag.uuid == item.tag_id;
})[0]; })[0];
item.tag_name = tag.name; item.tag_name = tag.content.title;
} }
}); });
request.post().then(function (response) { request.post().then(function (response) {
@@ -1735,10 +1705,14 @@ var ItemManager = function () {
key: 'resolveReferences', key: 'resolveReferences',
value: function resolveReferences() { value: function resolveReferences() {
this.items.forEach(function (item) { this.items.forEach(function (item) {
// build out references // build out references, safely handle broken references
item.content.references = _.map(item.content.references, function (reference) { item.content.references = _.reduce(item.content.references, function (accumulator, reference) {
return this.referencesForItemId(reference.uuid); var item = this.referencesForItemId(reference.uuid);
}.bind(this)); if (item) {
accumulator.push(item);
}
return accumulator;
}.bind(this), []);
}.bind(this)); }.bind(this));
} }
}, { }, {

File diff suppressed because one or more lines are too long