Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Category fixes #265

Merged
merged 6 commits into from
Nov 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions js/app/controllers/notescontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ app.controller('NotesController', function($routeParams, $scope, $location,
event.target.blur();
};

$scope.getCategories = _.memoize(function (notes) {
return NotesModel.getCategories(notes, 1, true);
});
$scope.categories = [];
$scope.$watch('notes', function(notes) {
$scope.categories = NotesModel.getCategories(notes, 1, true);
}, true);

$scope.toggleFolderSelector = function () {
$scope.folderSelectorOpen = !$scope.folderSelectorOpen;
Expand Down Expand Up @@ -84,6 +85,10 @@ app.controller('NotesController', function($routeParams, $scope, $location,
return true;
};

$scope.isCategory = function (item) {
return typeof item === 'string';
};

$window.onbeforeunload = function() {
var notes = NotesModel.getAll();
for(var i=0; i<notes.length; i+=1) {
Expand Down
22 changes: 9 additions & 13 deletions js/app/filters/groupNotes.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
/**
* group notes by (sub) category
*/
app.filter('groupNotes', ['$filter', function () {
app.filter('groupNotes', function () {
'use strict';
return _.memoize(function (notes, category) {
return function (items, category) {
if(category) {
var items = [];
var prevCat = null;
for(var i=0; i<notes.length; i+=1) {
var note = notes[i];
for(var i=0; i<items.length; i+=1) {
var note = items[i];
if(prevCat !== null && prevCat !== note.category) {
items.push({
isCategory: true,
title: note.category.substring(category.length+1),
});
items.splice(i, 0,
note.category.substring(category.length+1));
}
prevCat = note.category;
items.push(note);
}
return items;
} else {
return notes;
return items;
}
});
}]);
};
});
7 changes: 7 additions & 0 deletions js/app/services/savequeue.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ app.factory('SaveQueue', function($q) {
note.error = false;
note.title = response.title;
note.modified = response.modified;
if(note.category !== response.category) {
OC.Notification.showTemporary(
t('notes', 'Updating the note\'s category has failed. ' +
'Is the target directory writable?')
);
note.category = response.category;
}
if(response.content === note.content) {
note.unsaved = false;
}
Expand Down
2 changes: 1 addition & 1 deletion js/public/app.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/public/app.min.js.map

Large diffs are not rendered by default.

32 changes: 26 additions & 6 deletions service/notesservice.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,19 @@ public function create ($userId) {
public function update ($id, $content, $userId, $category=null, $mtime=0) {
$notesFolder = $this->getFolderForUser($userId);
$file = $this->getFileById($notesFolder, $id);
$folder = $file->getParent();
$title = $this->getSafeTitleFromContent($content);


// rename/move file with respect to title/category
// this can fail if access rights are not sufficient or category name is illegal
try {
$currentFilePath = $this->root->getFullPath($file->getPath());
$currentBasePath = pathinfo($currentFilePath, PATHINFO_DIRNAME);
$fileSuffix = '.' . pathinfo($file->getName(), PATHINFO_EXTENSION);

// detect (new) folder path based on category name
if($category===null) {
$basePath = pathinfo($currentFilePath, PATHINFO_DIRNAME);
$basePath = $currentBasePath;
} else {
$basePath = $notesFolder->getPath();
if(!empty($category)) {
Expand All @@ -180,8 +180,8 @@ public function update ($id, $content, $userId, $category=null, $mtime=0) {
$cats = array_filter($cats, function($str) { return !empty($str); });
$basePath .= '/'.implode('/', $cats);
}
$this->getOrCreateFolder($basePath);
}
$folder = $this->getOrCreateFolder($basePath);

// assemble new file path
$newFilePath = $basePath . '/' . $this->generateFileName($folder, $title, $fileSuffix, $id);
Expand All @@ -190,6 +190,9 @@ public function update ($id, $content, $userId, $category=null, $mtime=0) {
if($currentFilePath !== $newFilePath) {
$file->move($newFilePath);
}
if($currentBasePath !== $basePath) {
$this->deleteEmptyFolder($notesFolder, $this->root->get($currentBasePath));
}
} catch(\OCP\Files\NotPermittedException $e) {
$this->logger->error('Moving note '.$id.' ('.$title.') to the desired target is not allowed. Please check the note\'s target category ('.$category.').', ['app' => $this->appName]);
} catch(\Exception $e) {
Expand All @@ -205,7 +208,6 @@ public function update ($id, $content, $userId, $category=null, $mtime=0) {
return $this->getNote($file, $notesFolder, $this->getTags($id));
}


/**
* Set or unset a note as favorite.
* @param int $id the id of the note used to update
Expand Down Expand Up @@ -238,9 +240,11 @@ public function favorite ($id, $favorite, $userId){
* exist
*/
public function delete ($id, $userId) {
$folder = $this->getFolderForUser($userId);
$file = $this->getFileById($folder, $id);
$notesFolder = $this->getFolderForUser($userId);
$file = $this->getFileById($notesFolder, $id);
$parent = $file->getParent();
$file->delete();
$this->deleteEmptyFolder($notesFolder, $parent);
}

// removes characters that are illegal in a file or folder name on some operating systems
Expand Down Expand Up @@ -343,6 +347,22 @@ private function getOrCreateFolder($path) {
return $folder;
}

/*
* Delete a folder and it's parent(s) if it's/they're empty
* @param Folder root folder for notes
* @param Folder folder to delete
*/
private function deleteEmptyFolder(Folder $notesFolder, Folder $folder) {
$content = $folder->getDirectoryListing();
$isEmpty = !count($content);
$isNotesFolder = $folder->getPath()===$notesFolder->getPath();
if($isEmpty && !$isNotesFolder) {
$this->logger->info('Deleting empty category folder '.$folder->getPath(), ['app' => $this->appName]);
$parent = $folder->getParent();
$folder->delete();
$this->deleteEmptyFolder($notesFolder, $parent);
}
}

/**
* get path of file and the title.txt and check if they are the same
Expand Down
14 changes: 7 additions & 7 deletions templates/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class="nav-icon-recent svg"

<!-- category list -->
<li
ng-repeat="category in (getCategories(notes) | orderBy:['name'])"
ng-repeat="category in (categories | orderBy:['name'])"
class="nav-files"
ng-class="{ active: filterCategory==category.name && filterFavorite==false }"
title="{{ category.name || '<?php p($l->t('Uncategorized')); ?>' }}"
Expand Down Expand Up @@ -111,22 +111,22 @@ class="svg"

<!-- notes list -->
<li ng-repeat="note in filteredNotes = (notes | filter:categoryFilter | and:search | orderBy:filterOrder | groupNotes:filterCategory)"
ng-class="{ active: note.id == route.noteId, 'has-error': note.error, 'app-navigation-noclose': note.isCategory }"
ng-class="{ active: note.id == route.noteId, 'has-error': note.error, 'app-navigation-noclose': isCategory(note) }"
class="note-item">

<a class="nav-icon-files svg separator-above"
ng-if="note.isCategory"
ng-click="setFilter(filterCategory + '/' + note.title)"
>&hellip; / {{ note.title | categoryTitle }}</a>
ng-if="isCategory(note)"
ng-click="setFilter(filterCategory + '/' + note)"
>&hellip; / {{ note | categoryTitle }}</a>

<a href="#/notes/{{ note.id }}"
title="{{ note.title }}"
ng-if="!note.isCategory"
ng-if="!isCategory(note)"
>
{{ note.title }}
<span ng-if="note.unsaved">*</span>
</a>
<div class="app-navigation-entry-utils" ng-class="{'hidden': note.error }" ng-if="!note.isCategory">
<div class="app-navigation-entry-utils" ng-class="{'hidden': note.error }" ng-if="!isCategory(note)">
<ul>
<li class="app-navigation-entry-utils-menu-button button-delete">
<button class="svg action icon-delete"
Expand Down
2 changes: 1 addition & 1 deletion templates/note.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<textarea editor notes-timeout-change="onEdit()" name="editor" ng-if="note!==false"></textarea>
<div class="note-meta" ng-if="note!==false">
<span class="note-category" ng-class="{ uncategorized: !note.category }" title="<?php p($l->t('Category')); ?>" ng-show="!editCategory" ng-click="showEditCategory()">{{ note.category || '<?php p($l->t('Uncategorized')) ?>' | categoryTitle}} <input type="button" class="edit icon icon-rename" title="<?php p($l->t('Edit category')); ?>"></span>
<span class="note-category" title="<?php p($l->t('Edit category')); ?>" ng-show="editCategory"><form class="category"><input type="text" id="category" name="category" ng-blur="closeCategory()" placeholder="<?php p($l->t('Uncategorized')); ?>"><input type="submit" class="icon-confirm" value=""></form></span>
<span class="note-category" title="<?php p($l->t('Edit category')); ?>" ng-show="editCategory"><form class="category" ng-submit="closeCategory()"><input type="text" id="category" name="category" ng-blur="closeCategory()" placeholder="<?php p($l->t('Uncategorized')); ?>"><input type="submit" class="icon-confirm" value=""></form></span>
<span class="note-word-count" ng-if="note.content.length > 0">{{note.content | wordCount}}</span>
<span class="note-unsaved" ng-if="note.unsaved" title="<?php p($l->t('The note has unsaved changes.')); ?>"><?php p($l->t('*')); ?></span>
<span class="note-error" ng-if="note.error" ng-click="manualSave()" title="<?php p($l->t('Click here to try again')); ?>"><?php p($l->t('Saving failed!')); ?></span>
Expand Down