System smart tags
This commit is contained in:
@@ -40,10 +40,6 @@ angular.module('app')
|
|||||||
openDatabase();
|
openDatabase();
|
||||||
// Retrieve local data and begin sycing timer
|
// Retrieve local data and begin sycing timer
|
||||||
initiateSync();
|
initiateSync();
|
||||||
// Configure "All" psuedo-tag
|
|
||||||
loadAllTag();
|
|
||||||
// Configure "Archived" psuedo-tag
|
|
||||||
loadArchivedTag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(passcodeManager.isLocked()) {
|
if(passcodeManager.isLocked()) {
|
||||||
@@ -94,7 +90,6 @@ angular.module('app')
|
|||||||
|
|
||||||
syncManager.loadLocalItems().then(() => {
|
syncManager.loadLocalItems().then(() => {
|
||||||
$timeout(() => {
|
$timeout(() => {
|
||||||
$scope.allTag.didLoad = true;
|
|
||||||
$rootScope.$broadcast("initial-data-loaded"); // This needs to be processed first before sync is called so that singletonManager observers function properly.
|
$rootScope.$broadcast("initial-data-loaded"); // This needs to be processed first before sync is called so that singletonManager observers function properly.
|
||||||
syncManager.sync();
|
syncManager.sync();
|
||||||
// refresh every 30s
|
// refresh every 30s
|
||||||
@@ -113,25 +108,6 @@ angular.module('app')
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAllTag() {
|
|
||||||
var allTag = new SNTag({content: {title: "All"}});
|
|
||||||
allTag.all = true;
|
|
||||||
allTag.needsLoad = true;
|
|
||||||
$scope.allTag = allTag;
|
|
||||||
$scope.tags = modelManager.tags;
|
|
||||||
$scope.allTag.notes = modelManager.notes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadArchivedTag() {
|
|
||||||
var archiveTag = new SNSmartTag({content: {title: "Archived", predicate: ["archived", "=", true]}});
|
|
||||||
Object.defineProperty(archiveTag, "notes", {
|
|
||||||
get: () => {
|
|
||||||
return modelManager.notesMatchingPredicate(archiveTag.content.predicate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$scope.archiveTag = archiveTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Editor Callbacks
|
Editor Callbacks
|
||||||
*/
|
*/
|
||||||
@@ -220,7 +196,7 @@ angular.module('app')
|
|||||||
$scope.notesAddNew = function(note) {
|
$scope.notesAddNew = function(note) {
|
||||||
modelManager.addItem(note);
|
modelManager.addItem(note);
|
||||||
|
|
||||||
if(!$scope.selectedTag.all && !$scope.selectedTag.isSmartTag()) {
|
if(!$scope.selectedTag.isSmartTag()) {
|
||||||
$scope.selectedTag.addItemAsRelationship(note);
|
$scope.selectedTag.addItemAsRelationship(note);
|
||||||
$scope.selectedTag.setDirty(true);
|
$scope.selectedTag.setDirty(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ angular.module('app')
|
|||||||
if(this.isFiltering()) {
|
if(this.isFiltering()) {
|
||||||
return `${this.tag.notes.filter((i) => {return i.visible;}).length} search results`;
|
return `${this.tag.notes.filter((i) => {return i.visible;}).length} search results`;
|
||||||
} else if(this.tag) {
|
} else if(this.tag) {
|
||||||
return `${this.tag.title} notes`;
|
return `${this.tag.title}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ angular.module('app')
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.tag.all) {
|
if(this.tag.content.isAllTag) {
|
||||||
return note.tags && note.tags.length > 0;
|
return note.tags && note.tags.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ angular.module('app')
|
|||||||
selectionMade: "&",
|
selectionMade: "&",
|
||||||
save: "&",
|
save: "&",
|
||||||
tags: "=",
|
tags: "=",
|
||||||
allTag: "=",
|
|
||||||
archiveTag: "=",
|
|
||||||
updateNoteTag: "&",
|
updateNoteTag: "&",
|
||||||
removeTag: "&"
|
removeTag: "&"
|
||||||
},
|
},
|
||||||
@@ -17,25 +15,22 @@ angular.module('app')
|
|||||||
controller: 'TagsCtrl',
|
controller: 'TagsCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
bindToController: true,
|
bindToController: true,
|
||||||
|
|
||||||
link:function(scope, elem, attrs, ctrl) {
|
|
||||||
scope.$watch('ctrl.tags', function(newTags){
|
|
||||||
if(newTags) {
|
|
||||||
ctrl.setTags(newTags);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$watch('ctrl.allTag', function(allTag){
|
|
||||||
if(allTag) {
|
|
||||||
ctrl.setAllTag(allTag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.controller('TagsCtrl', function ($rootScope, modelManager, $timeout, componentManager, authManager) {
|
.controller('TagsCtrl', function ($rootScope, modelManager, syncManager, $timeout, componentManager, authManager) {
|
||||||
|
let initialLoad = true;
|
||||||
|
|
||||||
var initialLoad = true;
|
syncManager.addEventHandler((syncEvent, data) => {
|
||||||
|
if(syncEvent == "initial-data-loaded" || syncEvent == "sync:completed") {
|
||||||
|
this.tags = modelManager.tags;
|
||||||
|
this.smartTags = modelManager.getSmartTags();
|
||||||
|
|
||||||
|
if(initialLoad) {
|
||||||
|
initialLoad = false;
|
||||||
|
this.selectTag(this.smartTags[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.panelController = {};
|
this.panelController = {};
|
||||||
|
|
||||||
@@ -69,40 +64,27 @@ angular.module('app')
|
|||||||
}.bind(this), actionHandler: function(component, action, data){
|
}.bind(this), actionHandler: function(component, action, data){
|
||||||
if(action === "select-item") {
|
if(action === "select-item") {
|
||||||
if(data.item.content_type == "Tag") {
|
if(data.item.content_type == "Tag") {
|
||||||
var tag = modelManager.findItem(data.item.uuid);
|
let tag = modelManager.findItem(data.item.uuid);
|
||||||
if(tag) {
|
if(tag) {
|
||||||
this.selectTag(tag);
|
this.selectTag(tag);
|
||||||
}
|
}
|
||||||
} else if(data.item.content_type == "SN|SmartTag") {
|
} else if(data.item.content_type == "SN|SmartTag") {
|
||||||
var tag = new SNSmartTag(data.item);
|
let smartTag = new SNSmartTag(data.item);
|
||||||
Object.defineProperty(tag, "notes", {
|
this.selectTag(smartTag);
|
||||||
get: () => {
|
|
||||||
return modelManager.notesMatchingPredicate(tag.content.predicate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.selectTag(tag);
|
|
||||||
}
|
}
|
||||||
} else if(action === "clear-selection") {
|
} else if(action === "clear-selection") {
|
||||||
this.selectTag(this.allTag);
|
this.selectTag(this.smartTags[0]);
|
||||||
}
|
}
|
||||||
}.bind(this)});
|
}.bind(this)});
|
||||||
|
|
||||||
this.setAllTag = function(allTag) {
|
|
||||||
this.selectTag(this.allTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setTags = function(tags) {
|
|
||||||
if(initialLoad) {
|
|
||||||
initialLoad = false;
|
|
||||||
this.selectTag(this.allTag);
|
|
||||||
} else {
|
|
||||||
if(tags && tags.length > 0) {
|
|
||||||
this.selectTag(tags[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectTag = function(tag) {
|
this.selectTag = function(tag) {
|
||||||
|
if(tag.isSmartTag()) {
|
||||||
|
Object.defineProperty(tag, "notes", {
|
||||||
|
get: () => {
|
||||||
|
return modelManager.notesMatchingPredicate(tag.content.predicate);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
this.selectedTag = tag;
|
this.selectedTag = tag;
|
||||||
tag.conflict_of = null; // clear conflict
|
tag.conflict_of = null; // clear conflict
|
||||||
this.selectionMade()(tag);
|
this.selectionMade()(tag);
|
||||||
@@ -161,12 +143,12 @@ angular.module('app')
|
|||||||
|
|
||||||
this.selectedDeleteTag = function(tag) {
|
this.selectedDeleteTag = function(tag) {
|
||||||
this.removeTag()(tag);
|
this.removeTag()(tag);
|
||||||
this.selectTag(this.allTag);
|
this.selectTag(this.smartTags[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.noteCount = function(tag) {
|
this.noteCount = function(tag) {
|
||||||
var validNotes = SNNote.filterDummyNotes(tag.notes).filter(function(note){
|
var validNotes = SNNote.filterDummyNotes(tag.notes).filter(function(note){
|
||||||
return !note.archived;
|
return !note.archived && !note.content.trashed;
|
||||||
});
|
});
|
||||||
return validNotes.length;
|
return validNotes.length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ class ModelManager extends SFModelManager {
|
|||||||
this.components = [];
|
this.components = [];
|
||||||
|
|
||||||
this.storageManager = storageManager;
|
this.storageManager = storageManager;
|
||||||
|
|
||||||
|
this.buildSystemSmartTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSignout() {
|
handleSignout() {
|
||||||
@@ -119,6 +121,21 @@ class ModelManager extends SFModelManager {
|
|||||||
return this.itemsMatchingPredicates([contentTypePredicate, predicate]);
|
return this.itemsMatchingPredicates([contentTypePredicate, predicate]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildSystemSmartTags() {
|
||||||
|
this.systemSmartTags = SNSmartTag.systemSmartTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSmartTagWithId(id) {
|
||||||
|
return this.getSmartTags().find((candidate) => candidate.uuid == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSmartTags() {
|
||||||
|
let userTags = this.validItemsForContentType("SN|SmartTag").sort((a, b) => {
|
||||||
|
return a.content.title < b.content.title ? -1 : 1;
|
||||||
|
});
|
||||||
|
return this.systemSmartTags.concat(userTags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Misc
|
Misc
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tags-title-bar {
|
.tags-title-section {
|
||||||
color: var(--sn-stylekit-secondary-foreground-color);
|
color: var(--sn-stylekit-secondary-foreground-color);
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
.app#app{"ng-if" => "!needsUnlock", "ng-class" => "appClass"}
|
.app#app{"ng-if" => "!needsUnlock", "ng-class" => "appClass"}
|
||||||
%tags-section{"save" => "tagsSave", "add-new" => "tagsAddNew", "selection-made" => "tagsSelectionMade",
|
%tags-section{"save" => "tagsSave", "add-new" => "tagsAddNew", "selection-made" => "tagsSelectionMade",
|
||||||
"all-tag" => "allTag", "archive-tag" => "archiveTag", "tags" => "tags", "remove-tag" => "removeTag"}
|
"tags" => "tags", "remove-tag" => "removeTag"}
|
||||||
%notes-section{"add-new" => "notesAddNew", "selection-made" => "notesSelectionMade", "tag" => "selectedTag"}
|
%notes-section{"add-new" => "notesAddNew", "selection-made" => "notesSelectionMade", "tag" => "selectedTag"}
|
||||||
%editor-section{"note" => "selectedNote", "remove" => "deleteNote", "update-tags" => "updateTagsForNote"}
|
%editor-section{"note" => "selectedNote", "remove" => "deleteNote", "update-tags" => "updateTagsForNote"}
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,23 @@
|
|||||||
%component-view.component-view{"component" => "ctrl.component"}
|
%component-view.component-view{"component" => "ctrl.component"}
|
||||||
|
|
||||||
#tags-content.content{"ng-if" => "!(ctrl.component && ctrl.component.active)"}
|
#tags-content.content{"ng-if" => "!(ctrl.component && ctrl.component.active)"}
|
||||||
#tags-title-bar.section-title-bar
|
.tags-title-section.section-title-bar
|
||||||
.section-title-bar-header
|
.section-title-bar-header
|
||||||
.sk-h3.title
|
.sk-h3.title
|
||||||
%span.sk-bold Tags
|
%span.sk-bold Views
|
||||||
.sk-button.sk-secondary-contrast.wide{"ng-click" => "ctrl.clickedAddNewTag()", "title" => "Create a new tag"}
|
.sk-button.sk-secondary-contrast.wide{"ng-click" => "ctrl.clickedAddNewTag()", "title" => "Create a new tag"}
|
||||||
.sk-label +
|
.sk-label +
|
||||||
|
|
||||||
.scrollable
|
.scrollable
|
||||||
.infinite-scroll
|
.infinite-scroll
|
||||||
.tag{"ng-if" => "ctrl.allTag", "ng-click" => "ctrl.selectTag(ctrl.allTag)", "ng-class" => "{'selected' : ctrl.selectedTag == ctrl.allTag}"}
|
.tag{"ng-repeat" => "tag in ctrl.smartTags", "ng-click" => "ctrl.selectTag(tag)", "ng-class" => "{'selected' : ctrl.selectedTag == tag}"}
|
||||||
.info
|
.info
|
||||||
%input.title{"ng-disabled" => "true", "ng-model" => "ctrl.allTag.title"}
|
%input.title{"ng-disabled" => "true", "ng-model" => "tag.title"}
|
||||||
.count {{ctrl.noteCount(ctrl.allTag)}}
|
|
||||||
|
.tags-title-section.section-title-bar
|
||||||
|
.section-title-bar-header
|
||||||
|
.sk-h3.title
|
||||||
|
%span.sk-bold Tags
|
||||||
.tag{"ng-repeat" => "tag in ctrl.tags track by tag.uuid", "ng-click" => "ctrl.selectTag(tag)", "ng-class" => "{'selected' : ctrl.selectedTag == tag}"}
|
.tag{"ng-repeat" => "tag in ctrl.tags track by tag.uuid", "ng-click" => "ctrl.selectTag(tag)", "ng-class" => "{'selected' : ctrl.selectedTag == tag}"}
|
||||||
.info
|
.info
|
||||||
%input.title{"ng-attr-id" => "tag-{{tag.uuid}}", "ng-click" => "ctrl.selectTag(tag)", "ng-model" => "tag.title",
|
%input.title{"ng-attr-id" => "tag-{{tag.uuid}}", "ng-click" => "ctrl.selectTag(tag)", "ng-model" => "tag.title",
|
||||||
@@ -31,8 +35,5 @@
|
|||||||
%a.item{"ng-click" => "ctrl.selectedRenameTag($event, tag)", "ng-if" => "!ctrl.editingTag"} Rename
|
%a.item{"ng-click" => "ctrl.selectedRenameTag($event, tag)", "ng-if" => "!ctrl.editingTag"} Rename
|
||||||
%a.item{"ng-click" => "ctrl.saveTag($event, tag)", "ng-if" => "ctrl.editingTag"} Save
|
%a.item{"ng-click" => "ctrl.saveTag($event, tag)", "ng-if" => "ctrl.editingTag"} Save
|
||||||
%a.item{"ng-click" => "ctrl.selectedDeleteTag(tag)"} Delete
|
%a.item{"ng-click" => "ctrl.selectedDeleteTag(tag)"} Delete
|
||||||
.tag.faded{"ng-if" => "ctrl.archiveTag", "ng-click" => "ctrl.selectTag(ctrl.archiveTag)", "ng-class" => "{'selected' : ctrl.selectedTag == ctrl.archiveTag}"}
|
|
||||||
.info
|
|
||||||
%input.title{"ng-disabled" => "true", "ng-model" => "ctrl.archiveTag.title"}
|
|
||||||
|
|
||||||
%panel-resizer{"panel-id" => "'tags-column'", "default-width" => 150, "on-resize-finish" => "ctrl.onPanelResize", "control" => "ctrl.panelController", "hoverable" => "true", "collapsable" => "true"}
|
%panel-resizer{"panel-id" => "'tags-column'", "default-width" => 150, "on-resize-finish" => "ctrl.onPanelResize", "control" => "ctrl.panelController", "hoverable" => "true", "collapsable" => "true"}
|
||||||
|
|||||||
3461
package-lock.json
generated
3461
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@
|
|||||||
"karma-phantomjs-launcher": "^1.0.2",
|
"karma-phantomjs-launcher": "^1.0.2",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"serve-static": "^1.13.2",
|
"serve-static": "^1.13.2",
|
||||||
"sn-models": "0.1.9",
|
"sn-models": "~/Desktop/sn/dev/sn-models",
|
||||||
"sn-stylekit": "2.0.13",
|
"sn-stylekit": "2.0.13",
|
||||||
"standard-file-js": "0.3.31",
|
"standard-file-js": "0.3.31",
|
||||||
"grunt-shell": "^2.1.0"
|
"grunt-shell": "^2.1.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user