item deletion

This commit is contained in:
Mo Bitar
2016-12-15 20:50:16 -06:00
parent 1722eb299c
commit 36c74ed14d
17 changed files with 148 additions and 121 deletions

View File

@@ -81,7 +81,7 @@ angular.module('app.frontend')
{title: "MySQL list users", content: "SELECT User FROM mysql.user;"}, {title: "MySQL list users", content: "SELECT User FROM mysql.user;"},
]; ];
this.showSampler = !this.user.id && modelManager.filteredNotes.length == 0; this.showSampler = !this.user.uuid && modelManager.filteredNotes.length == 0;
this.demoNoteNames = _.map(this.demoNotes, function(note){ this.demoNoteNames = _.map(this.demoNotes, function(note){
return note.title; return note.title;

View File

@@ -144,7 +144,7 @@ angular.module('app.frontend')
} }
this.onAuthSuccess = function(user) { this.onAuthSuccess = function(user) {
this.user.id = user.id; this.user.uuid = user.uuid;
if(this.user.shouldMerge && this.hasLocalData()) { if(this.user.shouldMerge && this.hasLocalData()) {
apiController.mergeLocalDataRemotely(this.user, function(){ apiController.mergeLocalDataRemotely(this.user, function(){

View File

@@ -17,7 +17,15 @@ angular.module('app.frontend')
if(response && !response.errors) { if(response && !response.errors) {
console.log("Get user response", response); console.log("Get user response", response);
$scope.defaultUser = new User(response); $scope.defaultUser = new User(response);
modelManager.items = _.map(response.items, function(json_obj){return new Item(json_obj)}); modelManager.items = _.map(response.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);
}
});
$rootScope.title = "Notes — Neeto"; $rootScope.title = "Notes — Neeto";
onUserSet(); onUserSet();
} else { } else {
@@ -41,9 +49,6 @@ angular.module('app.frontend')
} }
$scope.tagsSelectionMade = function(tag) { $scope.tagsSelectionMade = function(tag) {
if(!tag.notes) {
tag.notes = [];
}
$scope.selectedTag = tag; $scope.selectedTag = tag;
} }
@@ -61,8 +66,7 @@ angular.module('app.frontend')
*/ */
$scope.tagsUpdateNoteTag = function(noteCopy, newTag, oldTag) { $scope.tagsUpdateNoteTag = function(noteCopy, newTag, oldTag) {
var originalNote = _.find($scope.defaultUser.notes, {uuid: noteCopy.uuid}); var originalNote = _.find(modelManager.notes, {uuid: noteCopy.uuid});
modelManager.removeTagFromNote(oldTag, originalNote);
if(!newTag.all) { if(!newTag.all) {
modelManager.addTagToNote(newTag, originalNote); modelManager.addTagToNote(newTag, originalNote);
} }
@@ -98,11 +102,12 @@ angular.module('app.frontend')
modelManager.addNote(note); modelManager.addNote(note);
if(!$scope.selectedTag.all) { if(!$scope.selectedTag.all) {
console.log("add tag");
modelManager.addTagToNote($scope.selectedTag, note); modelManager.addTagToNote($scope.selectedTag, note);
$scope.updateAllTag();
} else { } else {
$scope.selectedTag.notes.unshift(note); $scope.selectedTag.notes.unshift(note);
} }
} }
/* /*
@@ -130,11 +135,13 @@ angular.module('app.frontend')
$scope.selectedNote = null; $scope.selectedNote = null;
} }
$scope.updateAllTag();
if(note.dummy) { if(note.dummy) {
return; return;
} }
apiController.deleteItem($scope.defaultUser, note, function(success){}) apiController.deleteItem(note, function(success){})
apiController.saveDirtyItems(function(){}); apiController.saveDirtyItems(function(){});
} }

View File

@@ -25,7 +25,7 @@ angular.module('app.frontend')
} }
} }
}) })
.controller('NotesCtrl', function (apiController, modelManager, $timeout, ngDialog, $rootScope) { .controller('NotesCtrl', function (apiController, $timeout, ngDialog, $rootScope) {
$rootScope.$on("editorFocused", function(){ $rootScope.$on("editorFocused", function(){
this.showMenu = false; this.showMenu = false;
@@ -41,7 +41,11 @@ angular.module('app.frontend')
} }
this.noteFilter.text = ""; this.noteFilter.text = "";
this.setNotes(tag.notes, false);
tag.notes.forEach(function(note){
note.visible = true;
})
this.selectFirstNote(false);
if(isFirstLoad) { if(isFirstLoad) {
$timeout(function(){ $timeout(function(){
@@ -67,7 +71,7 @@ angular.module('app.frontend')
this.selectedTagShare = function() { this.selectedTagShare = function() {
this.showMenu = false; this.showMenu = false;
if(!this.user.id) { if(!this.user.uuid) {
alert("You must be signed in to share a tag."); alert("You must be signed in to share a tag.");
return; return;
} }
@@ -109,17 +113,8 @@ angular.module('app.frontend')
return this.tag.presentation.url; return this.tag.presentation.url;
} }
this.setNotes = function(notes, createNew) {
this.notes = notes;
console.log("set notes", notes);
notes.forEach(function(note){
note.visible = true;
})
this.selectFirstNote(createNew);
}
this.selectFirstNote = function(createNew) { this.selectFirstNote = function(createNew) {
var visibleNotes = this.notes.filter(function(note){ var visibleNotes = this.tag.notes.filter(function(note){
return note.visible; return note.visible;
}); });
@@ -136,12 +131,9 @@ angular.module('app.frontend')
} }
this.createNewNote = function() { this.createNewNote = function() {
var title = "New Note" + (this.notes ? (" " + (this.notes.length + 1)) : ""); var title = "New Note" + (this.tag.notes ? (" " + (this.tag.notes.length + 1)) : "");
this.newNote = new Note({dummy: true}); this.newNote = new Note({dummy: true});
this.newNote.content.title = title; this.newNote.content.title = title;
if(this.tag && !this.tag.all) {
modelManager.addTagToNote(this.tag, this.newNote);
}
this.selectNote(this.newNote); this.selectNote(this.newNote);
this.addNew()(this.newNote); this.addNew()(this.newNote);
} }

View File

@@ -63,10 +63,7 @@ angular.module('app.frontend')
return; return;
} }
this.newTag = new Tag({notes : []}); this.newTag = new Tag();
if(!this.user.uuid) {
this.newTag.uuid = Neeto.crypto.generateRandomKey()
}
this.selectedTag = this.newTag; this.selectedTag = this.newTag;
this.editingTag = this.newTag; this.editingTag = this.newTag;
this.addNew()(this.newTag); this.addNew()(this.newTag);
@@ -95,7 +92,7 @@ angular.module('app.frontend')
} }
this.save()(tag, function(savedTag){ this.save()(tag, function(savedTag){
_.merge(tag, savedTag); // _.merge(tag, savedTag);
this.selectTag(tag); this.selectTag(tag);
this.newTag = null; this.newTag = null;
}.bind(this)); }.bind(this));

View File

@@ -46,10 +46,12 @@ class Item {
addReference(reference) { addReference(reference) {
this.content.references.push(reference); this.content.references.push(reference);
this.content.references = _.uniq(this.content.references); this.content.references = _.uniq(this.content.references);
this.updateReferencesLocalMapping();
} }
removeReference(reference) { removeReference(reference) {
_.remove(this.content.references, _.find(this.content.references, {uuid: reference.uuid})); _.remove(this.content.references, _.find(this.content.references, {uuid: reference.uuid}));
this.updateReferencesLocalMapping();
} }
referencesMatchingContentType(contentType) { referencesMatchingContentType(contentType) {
@@ -62,7 +64,6 @@ class Item {
// should be overriden to manage local properties // should be overriden to manage local properties
} }
/* Returns true if note is shared individually or via tag */
isPublic() { isPublic() {
return this.presentation; return this.presentation;
} }

View File

@@ -18,6 +18,11 @@ class Note extends Item {
return filtered; return filtered;
} }
updateReferencesLocalMapping() {
super.updateReferencesLocalMapping();
this.tags = this.referencesMatchingContentType("Tag");
}
get hasOnePublicTag() { get hasOnePublicTag() {
var hasPublicTag = false; var hasPublicTag = false;
this.tags.forEach(function(tag){ this.tags.forEach(function(tag){
@@ -30,6 +35,10 @@ class Note extends Item {
return hasPublicTag; return hasPublicTag;
} }
toJSON() {
return {uuid: this.uuid}
}
isPublic() { isPublic() {
return super.isPublic() || this.hasOnePublicTag; return super.isPublic() || this.hasOnePublicTag;
} }

View File

@@ -19,6 +19,5 @@ class Tag extends Item {
updateReferencesLocalMapping() { updateReferencesLocalMapping() {
super.updateReferencesLocalMapping(); super.updateReferencesLocalMapping();
this.notes = this.referencesMatchingContentType("Note"); this.notes = this.referencesMatchingContentType("Note");
console.log("notes after maping", this.notes);
} }
} }

View File

@@ -143,7 +143,7 @@ angular.module('app.frontend')
*/ */
this.setUsername = function(user, username, callback) { this.setUsername = function(user, username, callback) {
var request = Restangular.one("users", user.id).one("set_username"); var request = Restangular.one("users", user.uuid).one("set_username");
request.username = username; request.username = username;
request.post().then(function(response){ request.post().then(function(response){
callback(response.plain()); callback(response.plain());
@@ -183,6 +183,10 @@ angular.module('app.frontend')
this.saveDirtyItems = function(callback) { this.saveDirtyItems = function(callback) {
var dirtyItems = modelManager.dirtyItems; var dirtyItems = modelManager.dirtyItems;
if(dirtyItems.length == 0) {
callback();
return;
}
this.saveItems(dirtyItems, function(response){ this.saveItems(dirtyItems, function(response){
modelManager.clearDirtyItems(); modelManager.clearDirtyItems();
@@ -232,7 +236,7 @@ angular.module('app.frontend')
this.deleteItem = function(item, callback) { this.deleteItem = function(item, callback) {
if(!this.user.id) { if(!this.user.uuid) {
this.writeUserToLocalStorage(this.user); this.writeUserToLocalStorage(this.user);
callback(true); callback(true);
} else { } else {
@@ -244,7 +248,7 @@ angular.module('app.frontend')
} }
this.shareItem = function(item, callback) { this.shareItem = function(item, callback) {
if(!this.user.id) { if(!this.user.uuid) {
alert("You must be signed in to share."); alert("You must be signed in to share.");
} else { } else {
Restangular.one("users", this.user.uuid).one("items", item.uuid).one("presentations").post() Restangular.one("users", this.user.uuid).one("items", item.uuid).one("presentations").post()
@@ -280,9 +284,9 @@ angular.module('app.frontend')
*/ */
this.updatePresentation = function(resource, presentation, callback) { this.updatePresentation = function(resource, presentation, callback) {
var request = Restangular.one("users", this.user.id) var request = Restangular.one("users", this.user.uuid)
.one("items", resource.id) .one("items", resource.uuid)
.one("presentations", resource.presentation.id); .one("presentations", resource.presentation.uuid);
_.merge(request, presentation); _.merge(request, presentation);
request.patch().then(function(response){ request.patch().then(function(response){
callback(response.plain()); callback(response.plain());
@@ -354,7 +358,7 @@ angular.module('app.frontend')
} }
return { return {
id: presentation.id, id: presentation.uuid,
uuid: presentation.uuid, uuid: presentation.uuid,
root_path: presentation.root_path, root_path: presentation.root_path,
relative_path: presentation.relative_path, relative_path: presentation.relative_path,
@@ -367,7 +371,7 @@ angular.module('app.frontend')
var items = _.map(user.filteredItems(), function(item){ var items = _.map(user.filteredItems(), function(item){
return { return {
id: item.id, id: item.uuid,
uuid: item.uuid, uuid: item.uuid,
content: item.content, content: item.content,
tag_id: item.tag_id, tag_id: item.tag_id,
@@ -379,7 +383,7 @@ angular.module('app.frontend')
var tags = _.map(user.tags, function(tag){ var tags = _.map(user.tags, function(tag){
return { return {
id: tag.id, id: tag.uuid,
uuid: tag.uuid, uuid: tag.uuid,
name: tag.name, name: tag.name,
created_at: tag.created_at, created_at: tag.created_at,
@@ -403,12 +407,12 @@ angular.module('app.frontend')
Merging Merging
*/ */
this.mergeLocalDataRemotely = function(user, callback) { this.mergeLocalDataRemotely = function(user, callback) {
var request = Restangular.one("users", user.id).one("merge"); var request = Restangular.one("users", user.uuid).one("merge");
var tags = user.tags; var tags = user.tags;
request.items = user.items; request.items = user.items;
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.id == 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.name;
} }
}) })

View File

@@ -91,7 +91,7 @@ angular
this.classList.remove('over'); this.classList.remove('over');
var binId = this.id; var binId = this.uuid;
var note = new Note(JSON.parse(e.dataTransfer.getData('Note'))); var note = new Note(JSON.parse(e.dataTransfer.getData('Note')));
scope.$apply(function(scope) { scope.$apply(function(scope) {
var fn = scope.drop(); var fn = scope.drop();

View File

@@ -30,12 +30,18 @@ class ItemManager {
// returns dirty item references that need saving // returns dirty item references that need saving
deleteItem(item) { deleteItem(item) {
var dirty = [];
_.remove(this.items, item); _.remove(this.items, item);
item.content.references.forEach(function(referencedItem){ var length = item.content.references.length;
this.removeReferencesBetweenItems(referencedItem, item); // note that references are deleted in this for loop, so you have to be careful how you iterate
}.bind(this)) for(var i = 0; i < length; i++) {
var referencedItem = item.content.references[0];
// console.log("removing references between items", referencedItem, item);
var _dirty = this.removeReferencesBetweenItems(referencedItem, item);
dirty = dirty.concat(_dirty);
}
return item.content.references; return dirty;
} }
removeReferencesBetweenItems(itemOne, itemTwo) { removeReferencesBetweenItems(itemOne, itemTwo) {

View File

@@ -9,15 +9,14 @@ class ModelManager extends ItemManager {
set items(items) { set items(items) {
super.items = items; super.items = items;
this.notes = _.map(this.itemsForContentType("Note"), function(json_obj) { this.notes = this.itemsForContentType("Note");
return new Note(json_obj); this.notes.forEach(function(note){
note.updateReferencesLocalMapping();
}) })
this.tags = _.map(this.itemsForContentType("Tag"), function(json_obj) { this.tags = this.itemsForContentType("Tag");
var tag = new Tag(json_obj); this.tags.forEach(function(tag){
console.log("tag references upon import", tag.content.references);
tag.updateReferencesLocalMapping(); tag.updateReferencesLocalMapping();
return tag;
}) })
} }
@@ -53,7 +52,6 @@ class ModelManager extends ItemManager {
} }
addTagToNote(tag, note) { addTagToNote(tag, note) {
console.log("adding tag to note", tag, note);
var dirty = this.createReferencesBetweenItems(tag, note); var dirty = this.createReferencesBetweenItems(tag, note);
this.refreshRelationshipsForTag(tag); this.refreshRelationshipsForTag(tag);
this.refreshRelationshipsForNote(note); this.refreshRelationshipsForNote(note);
@@ -78,11 +76,13 @@ class ModelManager extends ItemManager {
deleteNote(note) { deleteNote(note) {
var dirty = this.deleteItem(note); var dirty = this.deleteItem(note);
_.remove(this.notes, note);
this.addDirtyItems(dirty); this.addDirtyItems(dirty);
} }
deleteTag(tag) { deleteTag(tag) {
var dirty = this.deleteItem(tag); var dirty = this.deleteItem(tag);
_.remove(this.tags, tag);
this.addDirtyItems(dirty); this.addDirtyItems(dirty);
} }

View File

@@ -4,7 +4,7 @@
%a.navbar-brand{"ui-sref" => "home"} %a.navbar-brand{"ui-sref" => "home"}
.header-name .header-name
neeto neeto
%span.tagline{"ng-if" => "!ctrl.user.id", "ng-cloak" => "true"} secure code box for developers %span.tagline{"ng-if" => "!ctrl.user.uuid", "ng-cloak" => "true"} secure code box for developers
.menu.navbar-text.navbar-right .menu.navbar-text.navbar-right
.items .items

View File

@@ -6,7 +6,7 @@
"tags" => "tags", "user" => "defaultUser", "update-note-tag" => "tagsUpdateNoteTag"} "tags" => "tags", "user" => "defaultUser", "update-note-tag" => "tagsUpdateNoteTag"}
%notes-section{"remove-tag" => "notesRemoveTag", "user" => "defaultUser", "add-new" => "notesAddNew", "selection-made" => "notesSelectionMade", %notes-section{"remove-tag" => "notesRemoveTag", "user" => "defaultUser", "add-new" => "notesAddNew", "selection-made" => "notesSelectionMade",
"tag" => "selectedTag", "user-id" => "defaultUser.id", "remove" => "deleteNote"} "tag" => "selectedTag", "user-id" => "defaultUser.uuid", "remove" => "deleteNote"}
%editor-section{"ng-if" => "selectedNote", "note" => "selectedNote", "remove" => "deleteNote", %editor-section{"ng-if" => "selectedNote", "note" => "selectedNote", "remove" => "deleteNote",
"user" => "defaultUser", "save" => "saveNote"} "user" => "defaultUser", "save" => "saveNote"}

View File

@@ -30,7 +30,7 @@
%input.input{"ng-model" => "ctrl.url.token", "ng-keyup" => "$event.keyCode == 13 && ctrl.saveUrl($event)", %input.input{"ng-model" => "ctrl.url.token", "ng-keyup" => "$event.keyCode == 13 && ctrl.saveUrl($event)",
"ng-change" => "ctrl.urlChanged()", "ng-focus" => "ctrl.onUrlFocus()", "ng-change" => "ctrl.urlChanged()", "ng-focus" => "ctrl.onUrlFocus()",
"select-on-click" => "true", "autofocus" => "true"} "select-on-click" => "true", "autofocus" => "true"}
.note{"ng-repeat" => "note in ctrl.notes | filter: ctrl.filterNotes", .note{"ng-repeat" => "note in ctrl.tag.notes | filter: ctrl.filterNotes",
"ng-click" => "ctrl.selectNote(note)", "ng-class" => "{'selected' : ctrl.selectedNote == note}", "ng-click" => "ctrl.selectNote(note)", "ng-class" => "{'selected' : ctrl.selectedNote == note}",
"ng-attr-draggable" => "{{note.dummy ? undefined : 'true'}}", "note" => "note"} "ng-attr-draggable" => "{{note.dummy ? undefined : 'true'}}", "note" => "note"}
.name .name

View File

@@ -229,7 +229,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
this.demoNotes = [{ title: "Live print a file with tail", content: "tail -f log/production.log" }, { title: "Create SSH tunnel", content: "ssh -i .ssh/key.pem -N -L 3306:example.com:3306 ec2-user@example.com" }, { title: "List of processes running on port", content: "lsof -i:8080" }, { title: "Set ENV from file", content: "export $(cat .envfile | xargs)" }, { title: "Find process by name", content: "ps -ax | grep <application name>" }, { title: "NPM install without sudo", content: "sudo chown -R $(whoami) ~/.npm" }, { title: "Email validation regex", content: "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" }, { title: "Ruby generate 256 bit key", content: "Digest::SHA256.hexdigest(SecureRandom.random_bytes(32))" }, { title: "Mac add user to user tag", content: "sudo dsedittag -o edit -a USERNAME -t user GROUPNAME" }, { title: "Kill Mac OS System Apache", content: "sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist" }, { title: "Docker run with mount binding and port", content: "docker run -v /home/vagrant/www/app:/var/www/app -p 8080:80 -d kpi/s3" }, { title: "MySQL grant privileges", content: "GRANT [type of permission] ON [database name].[table name] TO [username]@'%;" }, { title: "MySQL list users", content: "SELECT User FROM mysql.user;" }]; this.demoNotes = [{ title: "Live print a file with tail", content: "tail -f log/production.log" }, { title: "Create SSH tunnel", content: "ssh -i .ssh/key.pem -N -L 3306:example.com:3306 ec2-user@example.com" }, { title: "List of processes running on port", content: "lsof -i:8080" }, { title: "Set ENV from file", content: "export $(cat .envfile | xargs)" }, { title: "Find process by name", content: "ps -ax | grep <application name>" }, { title: "NPM install without sudo", content: "sudo chown -R $(whoami) ~/.npm" }, { title: "Email validation regex", content: "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" }, { title: "Ruby generate 256 bit key", content: "Digest::SHA256.hexdigest(SecureRandom.random_bytes(32))" }, { title: "Mac add user to user tag", content: "sudo dsedittag -o edit -a USERNAME -t user GROUPNAME" }, { title: "Kill Mac OS System Apache", content: "sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist" }, { title: "Docker run with mount binding and port", content: "docker run -v /home/vagrant/www/app:/var/www/app -p 8080:80 -d kpi/s3" }, { title: "MySQL grant privileges", content: "GRANT [type of permission] ON [database name].[table name] TO [username]@'%;" }, { title: "MySQL list users", content: "SELECT User FROM mysql.user;" }];
this.showSampler = !this.user.id && modelManager.filteredNotes.length == 0; this.showSampler = !this.user.uuid && modelManager.filteredNotes.length == 0;
this.demoNoteNames = _.map(this.demoNotes, function (note) { this.demoNoteNames = _.map(this.demoNotes, function (note) {
return note.title; return note.title;
@@ -574,7 +574,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
}; };
this.onAuthSuccess = function (user) { this.onAuthSuccess = function (user) {
this.user.id = user.id; this.user.uuid = user.uuid;
if (this.user.shouldMerge && this.hasLocalData()) { if (this.user.shouldMerge && this.hasLocalData()) {
apiController.mergeLocalDataRemotely(this.user, function () { apiController.mergeLocalDataRemotely(this.user, function () {
@@ -607,7 +607,13 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
console.log("Get user response", response); console.log("Get user response", response);
$scope.defaultUser = new User(response); $scope.defaultUser = new User(response);
modelManager.items = _.map(response.items, function (json_obj) { modelManager.items = _.map(response.items, function (json_obj) {
return new Item(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);
}
}); });
$rootScope.title = "Notes — Neeto"; $rootScope.title = "Notes — Neeto";
onUserSet(); onUserSet();
@@ -632,9 +638,6 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
}; };
$scope.tagsSelectionMade = function (tag) { $scope.tagsSelectionMade = function (tag) {
if (!tag.notes) {
tag.notes = [];
}
$scope.selectedTag = tag; $scope.selectedTag = tag;
}; };
@@ -652,8 +655,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
*/ */
$scope.tagsUpdateNoteTag = function (noteCopy, newTag, oldTag) { $scope.tagsUpdateNoteTag = function (noteCopy, newTag, oldTag) {
var originalNote = _.find($scope.defaultUser.notes, { uuid: noteCopy.uuid }); var originalNote = _.find(modelManager.notes, { uuid: noteCopy.uuid });
modelManager.removeTagFromNote(oldTag, originalNote);
if (!newTag.all) { if (!newTag.all) {
modelManager.addTagToNote(newTag, originalNote); modelManager.addTagToNote(newTag, originalNote);
} }
@@ -689,8 +691,8 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
modelManager.addNote(note); modelManager.addNote(note);
if (!$scope.selectedTag.all) { if (!$scope.selectedTag.all) {
console.log("add tag");
modelManager.addTagToNote($scope.selectedTag, note); modelManager.addTagToNote($scope.selectedTag, note);
$scope.updateAllTag();
} else { } else {
$scope.selectedTag.notes.unshift(note); $scope.selectedTag.notes.unshift(note);
} }
@@ -721,11 +723,13 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
$scope.selectedNote = null; $scope.selectedNote = null;
} }
$scope.updateAllTag();
if (note.dummy) { if (note.dummy) {
return; return;
} }
apiController.deleteItem($scope.defaultUser, note, function (success) {}); apiController.deleteItem(note, function (success) {});
apiController.saveDirtyItems(function () {}); apiController.saveDirtyItems(function () {});
}; };
@@ -763,7 +767,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
}); });
} }
}; };
}).controller('NotesCtrl', function (apiController, modelManager, $timeout, ngDialog, $rootScope) { }).controller('NotesCtrl', function (apiController, $timeout, ngDialog, $rootScope) {
$rootScope.$on("editorFocused", function () { $rootScope.$on("editorFocused", function () {
this.showMenu = false; this.showMenu = false;
@@ -779,7 +783,11 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
} }
this.noteFilter.text = ""; this.noteFilter.text = "";
this.setNotes(tag.notes, false);
tag.notes.forEach(function (note) {
note.visible = true;
});
this.selectFirstNote(false);
if (isFirstLoad) { if (isFirstLoad) {
$timeout(function () { $timeout(function () {
@@ -805,7 +813,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
this.selectedTagShare = function () { this.selectedTagShare = function () {
this.showMenu = false; this.showMenu = false;
if (!this.user.id) { if (!this.user.uuid) {
alert("You must be signed in to share a tag."); alert("You must be signed in to share a tag.");
return; return;
} }
@@ -848,17 +856,8 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
return this.tag.presentation.url; return this.tag.presentation.url;
}; };
this.setNotes = function (notes, createNew) {
this.notes = notes;
console.log("set notes", notes);
notes.forEach(function (note) {
note.visible = true;
});
this.selectFirstNote(createNew);
};
this.selectFirstNote = function (createNew) { this.selectFirstNote = function (createNew) {
var visibleNotes = this.notes.filter(function (note) { var visibleNotes = this.tag.notes.filter(function (note) {
return note.visible; return note.visible;
}); });
@@ -875,12 +874,9 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
}; };
this.createNewNote = function () { this.createNewNote = function () {
var title = "New Note" + (this.notes ? " " + (this.notes.length + 1) : ""); var title = "New Note" + (this.tag.notes ? " " + (this.tag.notes.length + 1) : "");
this.newNote = new Note({ dummy: true }); this.newNote = new Note({ dummy: true });
this.newNote.content.title = title; this.newNote.content.title = title;
if (this.tag && !this.tag.all) {
modelManager.addTagToNote(this.tag, this.newNote);
}
this.selectNote(this.newNote); this.selectNote(this.newNote);
this.addNew()(this.newNote); this.addNew()(this.newNote);
}; };
@@ -967,10 +963,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
return; return;
} }
this.newTag = new Tag({ notes: [] }); this.newTag = new Tag();
if (!this.user.uuid) {
this.newTag.uuid = Neeto.crypto.generateRandomKey();
}
this.selectedTag = this.newTag; this.selectedTag = this.newTag;
this.editingTag = this.newTag; this.editingTag = this.newTag;
this.addNew()(this.newTag); this.addNew()(this.newTag);
@@ -999,7 +992,7 @@ angular.module('app.frontend').controller('BaseCtrl', BaseCtrl);
} }
this.save()(tag, function (savedTag) { this.save()(tag, function (savedTag) {
_.merge(tag, savedTag); // _.merge(tag, savedTag);
this.selectTag(tag); this.selectTag(tag);
this.newTag = null; this.newTag = null;
}.bind(this)); }.bind(this));
@@ -1077,11 +1070,13 @@ var Item = function () {
value: function addReference(reference) { value: function addReference(reference) {
this.content.references.push(reference); this.content.references.push(reference);
this.content.references = _.uniq(this.content.references); this.content.references = _.uniq(this.content.references);
this.updateReferencesLocalMapping();
} }
}, { }, {
key: 'removeReference', key: 'removeReference',
value: function removeReference(reference) { value: function removeReference(reference) {
_.remove(this.content.references, _.find(this.content.references, { uuid: reference.uuid })); _.remove(this.content.references, _.find(this.content.references, { uuid: reference.uuid }));
this.updateReferencesLocalMapping();
} }
}, { }, {
key: 'referencesMatchingContentType', key: 'referencesMatchingContentType',
@@ -1092,12 +1087,9 @@ var Item = function () {
} }
}, { }, {
key: 'updateReferencesLocalMapping', key: 'updateReferencesLocalMapping',
value: function updateReferencesLocalMapping() {} value: function updateReferencesLocalMapping() {
// should be overriden to manage local properties // should be overriden to manage local properties
}
/* Returns true if note is shared individually or via tag */
}, { }, {
key: 'isPublic', key: 'isPublic',
value: function isPublic() { value: function isPublic() {
@@ -1144,6 +1136,17 @@ var Note = function (_Item) {
} }
_createClass(Note, [{ _createClass(Note, [{
key: 'updateReferencesLocalMapping',
value: function updateReferencesLocalMapping() {
_get(Note.prototype.__proto__ || Object.getPrototypeOf(Note.prototype), 'updateReferencesLocalMapping', this).call(this);
this.tags = this.referencesMatchingContentType("Tag");
}
}, {
key: 'toJSON',
value: function toJSON() {
return { uuid: this.uuid };
}
}, {
key: 'isPublic', key: 'isPublic',
value: function isPublic() { value: function isPublic() {
return _get(Note.prototype.__proto__ || Object.getPrototypeOf(Note.prototype), 'isPublic', this).call(this) || this.hasOnePublicTag; return _get(Note.prototype.__proto__ || Object.getPrototypeOf(Note.prototype), 'isPublic', this).call(this) || this.hasOnePublicTag;
@@ -1203,7 +1206,6 @@ var Tag = function (_Item2) {
value: function updateReferencesLocalMapping() { value: function updateReferencesLocalMapping() {
_get(Tag.prototype.__proto__ || Object.getPrototypeOf(Tag.prototype), 'updateReferencesLocalMapping', this).call(this); _get(Tag.prototype.__proto__ || Object.getPrototypeOf(Tag.prototype), 'updateReferencesLocalMapping', this).call(this);
this.notes = this.referencesMatchingContentType("Note"); this.notes = this.referencesMatchingContentType("Note");
console.log("notes after maping", this.notes);
} }
}, { }, {
key: 'content_type', key: 'content_type',
@@ -1362,7 +1364,7 @@ var User = function User(json_obj) {
*/ */
this.setUsername = function (user, username, callback) { this.setUsername = function (user, username, callback) {
var request = Restangular.one("users", user.id).one("set_username"); var request = Restangular.one("users", user.uuid).one("set_username");
request.username = username; request.username = username;
request.post().then(function (response) { request.post().then(function (response) {
callback(response.plain()); callback(response.plain());
@@ -1400,6 +1402,10 @@ var User = function User(json_obj) {
this.saveDirtyItems = function (callback) { this.saveDirtyItems = function (callback) {
var dirtyItems = modelManager.dirtyItems; var dirtyItems = modelManager.dirtyItems;
if (dirtyItems.length == 0) {
callback();
return;
}
this.saveItems(dirtyItems, function (response) { this.saveItems(dirtyItems, function (response) {
modelManager.clearDirtyItems(); modelManager.clearDirtyItems();
@@ -1447,7 +1453,7 @@ var User = function User(json_obj) {
}; };
this.deleteItem = function (item, callback) { this.deleteItem = function (item, callback) {
if (!this.user.id) { if (!this.user.uuid) {
this.writeUserToLocalStorage(this.user); this.writeUserToLocalStorage(this.user);
callback(true); callback(true);
} else { } else {
@@ -1458,7 +1464,7 @@ var User = function User(json_obj) {
}; };
this.shareItem = function (item, callback) { this.shareItem = function (item, callback) {
if (!this.user.id) { if (!this.user.uuid) {
alert("You must be signed in to share."); alert("You must be signed in to share.");
} else { } else {
Restangular.one("users", this.user.uuid).one("items", item.uuid).one("presentations").post().then(function (response) { Restangular.one("users", this.user.uuid).one("items", item.uuid).one("presentations").post().then(function (response) {
@@ -1492,7 +1498,7 @@ var User = function User(json_obj) {
*/ */
this.updatePresentation = function (resource, presentation, callback) { this.updatePresentation = function (resource, presentation, callback) {
var request = Restangular.one("users", this.user.id).one("items", resource.id).one("presentations", resource.presentation.id); var request = Restangular.one("users", this.user.uuid).one("items", resource.uuid).one("presentations", resource.presentation.uuid);
_.merge(request, presentation); _.merge(request, presentation);
request.patch().then(function (response) { request.patch().then(function (response) {
callback(response.plain()); callback(response.plain());
@@ -1561,7 +1567,7 @@ var User = function User(json_obj) {
} }
return { return {
id: presentation.id, id: presentation.uuid,
uuid: presentation.uuid, uuid: presentation.uuid,
root_path: presentation.root_path, root_path: presentation.root_path,
relative_path: presentation.relative_path, relative_path: presentation.relative_path,
@@ -1574,7 +1580,7 @@ var User = function User(json_obj) {
var items = _.map(user.filteredItems(), function (item) { var items = _.map(user.filteredItems(), function (item) {
return { return {
id: item.id, id: item.uuid,
uuid: item.uuid, uuid: item.uuid,
content: item.content, content: item.content,
tag_id: item.tag_id, tag_id: item.tag_id,
@@ -1586,7 +1592,7 @@ var User = function User(json_obj) {
var tags = _.map(user.tags, function (tag) { var tags = _.map(user.tags, function (tag) {
return { return {
id: tag.id, id: tag.uuid,
uuid: tag.uuid, uuid: tag.uuid,
name: tag.name, name: tag.name,
created_at: tag.created_at, created_at: tag.created_at,
@@ -1607,13 +1613,13 @@ var User = function User(json_obj) {
Merging Merging
*/ */
this.mergeLocalDataRemotely = function (user, callback) { this.mergeLocalDataRemotely = function (user, callback) {
var request = Restangular.one("users", user.id).one("merge"); var request = Restangular.one("users", user.uuid).one("merge");
var tags = user.tags; var tags = user.tags;
request.items = user.items; request.items = user.items;
request.items.forEach(function (item) { request.items.forEach(function (item) {
if (item.tag_id) { if (item.tag_id) {
var tag = tags.filter(function (tag) { var tag = tags.filter(function (tag) {
return tag.id == item.tag_id; return tag.uuid == item.tag_id;
})[0]; })[0];
item.tag_name = tag.name; item.tag_name = tag.name;
} }
@@ -1798,12 +1804,18 @@ var ItemManager = function () {
}, { }, {
key: 'deleteItem', key: 'deleteItem',
value: function deleteItem(item) { value: function deleteItem(item) {
var dirty = [];
_.remove(this.items, item); _.remove(this.items, item);
item.content.references.forEach(function (referencedItem) { var length = item.content.references.length;
this.removeReferencesBetweenItems(referencedItem, item); // note that references are deleted in this for loop, so you have to be careful how you iterate
}.bind(this)); for (var i = 0; i < length; i++) {
var referencedItem = item.content.references[0];
// console.log("removing references between items", referencedItem, item);
var _dirty = this.removeReferencesBetweenItems(referencedItem, item);
dirty = dirty.concat(_dirty);
}
return item.content.references; return dirty;
} }
}, { }, {
key: 'removeReferencesBetweenItems', key: 'removeReferencesBetweenItems',
@@ -1897,7 +1909,6 @@ var ModelManager = function (_ItemManager) {
}, { }, {
key: 'addTagToNote', key: 'addTagToNote',
value: function addTagToNote(tag, note) { value: function addTagToNote(tag, note) {
console.log("adding tag to note", tag, note);
var dirty = this.createReferencesBetweenItems(tag, note); var dirty = this.createReferencesBetweenItems(tag, note);
this.refreshRelationshipsForTag(tag); this.refreshRelationshipsForTag(tag);
this.refreshRelationshipsForNote(note); this.refreshRelationshipsForNote(note);
@@ -1926,12 +1937,14 @@ var ModelManager = function (_ItemManager) {
key: 'deleteNote', key: 'deleteNote',
value: function deleteNote(note) { value: function deleteNote(note) {
var dirty = this.deleteItem(note); var dirty = this.deleteItem(note);
_.remove(this.notes, note);
this.addDirtyItems(dirty); this.addDirtyItems(dirty);
} }
}, { }, {
key: 'deleteTag', key: 'deleteTag',
value: function deleteTag(tag) { value: function deleteTag(tag) {
var dirty = this.deleteItem(tag); var dirty = this.deleteItem(tag);
_.remove(this.tags, tag);
this.addDirtyItems(dirty); this.addDirtyItems(dirty);
} }
}, { }, {
@@ -1943,15 +1956,14 @@ var ModelManager = function (_ItemManager) {
key: 'items', key: 'items',
set: function set(items) { set: function set(items) {
_set(ModelManager.prototype.__proto__ || Object.getPrototypeOf(ModelManager.prototype), 'items', items, this); _set(ModelManager.prototype.__proto__ || Object.getPrototypeOf(ModelManager.prototype), 'items', items, this);
this.notes = _.map(this.itemsForContentType("Note"), function (json_obj) { this.notes = this.itemsForContentType("Note");
return new Note(json_obj); this.notes.forEach(function (note) {
note.updateReferencesLocalMapping();
}); });
this.tags = _.map(this.itemsForContentType("Tag"), function (json_obj) { this.tags = this.itemsForContentType("Tag");
var tag = new Tag(json_obj); this.tags.forEach(function (tag) {
console.log("tag references upon import", tag.content.references);
tag.updateReferencesLocalMapping(); tag.updateReferencesLocalMapping();
return tag;
}); });
}, },
get: function get() { get: function get() {
@@ -2069,7 +2081,7 @@ angular.module('app.frontend').directive('droppable', function () {
this.classList.remove('over'); this.classList.remove('over');
var binId = this.id; var binId = this.uuid;
var note = new Note(JSON.parse(e.dataTransfer.getData('Note'))); var note = new Note(JSON.parse(e.dataTransfer.getData('Note')));
scope.$apply(function (scope) { scope.$apply(function (scope) {
var fn = scope.drop(); var fn = scope.drop();

File diff suppressed because one or more lines are too long