diff --git a/app/assets/javascripts/app/controllers/editor.js b/app/assets/javascripts/app/controllers/editor.js index 924053b26..382440504 100644 --- a/app/assets/javascripts/app/controllers/editor.js +++ b/app/assets/javascripts/app/controllers/editor.js @@ -246,6 +246,12 @@ angular.module('app') this.saveNote = function($event) { var note = this.note; note.dummy = false; + // Make sure the note exists. A safety measure, as toggling between tags triggers deletes for dummy notes. + // Race conditions have been fixed, but we'll keep this here just in case. + if(!modelManager.findItem(note.uuid)) { + alert("The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note."); + return; + } this.save()(note, function(success){ if(success) { if(statusTimeout) $timeout.cancel(statusTimeout); diff --git a/app/assets/javascripts/app/controllers/home.js b/app/assets/javascripts/app/controllers/home.js index 786bc772f..6f626bd0d 100644 --- a/app/assets/javascripts/app/controllers/home.js +++ b/app/assets/javascripts/app/controllers/home.js @@ -112,10 +112,13 @@ angular.module('app') } function loadArchivedTag() { - var archiveTag = new Tag({content: {title: "Archived"}}); - archiveTag.archiveTag = true; + var archiveTag = new SmartTag({content: {title: "Archived", predicate: ["archived", "=", true]}}); + Object.defineProperty(archiveTag, "notes", { + get: () => { + return modelManager.notesMatchingPredicate(archiveTag.content.predicate); + } + }); $scope.archiveTag = archiveTag; - $scope.archiveTag.notes = modelManager.notes; } /* @@ -157,8 +160,15 @@ angular.module('app') */ $scope.tagsSelectionMade = function(tag) { + // If a tag is selected twice, then the needed dummy note is removed. + // So we perform this check. + if($scope.selectedTag && tag && $scope.selectedTag.uuid == tag.uuid) { + return; + } + if($scope.selectedNote && $scope.selectedNote.dummy) { modelManager.removeItemLocally($scope.selectedNote); + $scope.selectedNote = null; } $scope.selectedTag = tag; @@ -200,7 +210,7 @@ angular.module('app') $scope.notesAddNew = function(note) { modelManager.addItem(note); - if(!$scope.selectedTag.all && !$scope.selectedTag.archiveTag && !$scope.selectedTag.isSmartTag()) { + if(!$scope.selectedTag.all && !$scope.selectedTag.isSmartTag()) { $scope.selectedTag.addItemAsRelationship(note); $scope.selectedTag.setDirty(true); } @@ -246,7 +256,6 @@ angular.module('app') } $scope.deleteNote = function(note) { - modelManager.setItemToBeDeleted(note); if(note == $scope.selectedNote) { diff --git a/app/assets/javascripts/app/controllers/notes.js b/app/assets/javascripts/app/controllers/notes.js index 245fe87d9..e90be9064 100644 --- a/app/assets/javascripts/app/controllers/notes.js +++ b/app/assets/javascripts/app/controllers/notes.js @@ -14,7 +14,7 @@ angular.module('app') bindToController: true, link:function(scope, elem, attrs, ctrl) { - scope.$watch('ctrl.tag', function(tag, oldTag){ + scope.$watch('ctrl.tag', (tag, oldTag) => { if(tag) { if(tag.needsLoad) { scope.$watch('ctrl.tag.didLoad', function(didLoad){ @@ -133,12 +133,14 @@ angular.module('app') base += " Title"; } - if(this.showArchived && (!this.tag || !this.tag.archiveTag)) { - base += " | + Archived" - } - - if(this.hidePinned) { - base += " | – Pinned" + if(!this.tag || !this.tag.isSmartTag()) { + // These rules don't apply for smart tags + if(this.showArchived) { + base += " | + Archived" + } + if(this.hidePinned) { + base += " | – Pinned" + } } return base; @@ -227,9 +229,16 @@ angular.module('app') this.noteFilter = {text : ''}; this.filterNotes = function(note) { + var canShowArchived = false, canShowPinned = true; var isSmartTag = this.tag.isSmartTag(); + if(isSmartTag) { + canShowArchived = this.tag.isReferencingArchivedNotes(); + } else { + canShowArchived = this.showArchived; + canShowPinned = !this.hidePinned; + } - if((!isSmartTag && note.archived && !this.showArchived && !this.tag.archiveTag) || (note.pinned && this.hidePinned)) { + if((note.archived && !canShowArchived) || (note.pinned && !canShowPinned)) { note.visible = false; return note.visible; } @@ -244,9 +253,9 @@ angular.module('app') note.visible = matchesTitle || matchesBody; } - if(this.tag.archiveTag) { - note.visible = note.visible && note.archived; - } + // if(this.tag.archiveTag) { + // note.visible = note.visible && note.archived; + // } return note.visible; }.bind(this) diff --git a/app/assets/javascripts/app/controllers/tags.js b/app/assets/javascripts/app/controllers/tags.js index 168cbc365..93f2275cb 100644 --- a/app/assets/javascripts/app/controllers/tags.js +++ b/app/assets/javascripts/app/controllers/tags.js @@ -71,12 +71,10 @@ angular.module('app') this.selectTag(tag); } } else if(data.item.content_type == "SN|SmartTag") { - var params = data.item.content.predicate; - var predicate = new SFPredicate(params.keypath, params.operator, params.value); - var tag = new Tag(data.item); + var tag = new SmartTag(data.item); Object.defineProperty(tag, "notes", { get: () => { - return modelManager.notesMatchingPredicate(predicate); + return modelManager.notesMatchingPredicate(tag.content.predicate); } }); this.selectTag(tag); diff --git a/app/assets/javascripts/app/services/modelManager.js b/app/assets/javascripts/app/services/modelManager.js index 4668198d4..65d27a0e0 100644 --- a/app/assets/javascripts/app/services/modelManager.js +++ b/app/assets/javascripts/app/services/modelManager.js @@ -1,6 +1,7 @@ SFModelManager.ContentTypeClassMapping = { "Note" : Note, "Tag" : Tag, + "SN|SmartTag" : SmartTag, "Extension" : Extension, "SN|Editor" : Editor, "SN|Theme" : Theme, diff --git a/app/assets/templates/notes.html.haml b/app/assets/templates/notes.html.haml index 7d22da5bd..87e837568 100644 --- a/app/assets/templates/notes.html.haml +++ b/app/assets/templates/notes.html.haml @@ -30,7 +30,7 @@ %menu-row{"label" => "'Date Modified'", "circle" => "ctrl.sortBy == 'client_updated_at' && 'success'", "ng-click" => "ctrl.selectedMenuItem($event); ctrl.selectedSortByUpdated()", "desc" => "'Sort notes with the most recently updated first'"} %menu-row{"label" => "'Title'", "circle" => "ctrl.sortBy == 'title' && 'success'", "ng-click" => "ctrl.selectedMenuItem($event); ctrl.selectedSortByTitle()", "desc" => "'Sort notes alphabetically by their title'"} - .section{"ng-if" => "!ctrl.tag.archiveTag"} + .section{"ng-if" => "!ctrl.tag.isSmartTag()"} .header %h4.title Display @@ -52,7 +52,7 @@ %i.icon.ion-bookmark %strong.medium-text Pinned - .archived.tinted{"ng-if" => "note.archived && !ctrl.tag.archiveTag", "ng-class" => "{'tinted-selected' : ctrl.selectedNote == note}"} + .archived.tinted{"ng-if" => "note.archived && !ctrl.tag.isSmartTag()", "ng-class" => "{'tinted-selected' : ctrl.selectedNote == note}"} %i.icon.ion-ios-box %strong.medium-text Archived