From f0d7f752c0b2391cb4367fe2f9546213b5b025d5 Mon Sep 17 00:00:00 2001 From: korelstar Date: Mon, 3 Feb 2020 21:36:41 +0100 Subject: [PATCH 1/4] manual edit of a note's title --- appinfo/routes.php | 6 ++++ lib/Controller/NotesController.php | 19 ++++++++-- lib/Service/NoteUtil.php | 4 +-- lib/Service/NotesService.php | 51 +++++++++++++++++++-------- src/NotesService.js | 13 +++++++ src/components/NavigationNoteItem.vue | 27 +++++++++++--- 6 files changed, 97 insertions(+), 23 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index e38f5994c..59af979a1 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -64,6 +64,12 @@ 'verb' => 'PUT', 'requirements' => ['id' => '\d+'], ], + [ + 'name' => 'notes#title', + 'url' => '/notes/{id}/title', + 'verb' => 'PUT', + 'requirements' => ['id' => '\d+'], + ], [ 'name' => 'notes#favorite', 'url' => '/notes/{id}/favorite', diff --git a/lib/Controller/NotesController.php b/lib/Controller/NotesController.php index e7d9780fc..be1b27fa6 100644 --- a/lib/Controller/NotesController.php +++ b/lib/Controller/NotesController.php @@ -177,7 +177,7 @@ public function undo($id, $content, $category, $modified, $favorite) { */ public function update($id, $content) { try { - $note = $this->notesService->update($id, $content, $this->userId); + $note = $this->notesService->setContent($this->userId, $id, $content); return new DataResponse($note); } catch (InsufficientStorageException $e) { return new DataResponse([], Http::STATUS_INSUFFICIENT_STORAGE); @@ -194,8 +194,21 @@ public function update($id, $content) { * @return DataResponse */ public function category($id, $category) { - $note = $this->notesService->update($id, null, $this->userId, $category); - return new DataResponse($note->category); + $note = $this->notesService->setTitleCategory($this->userId, $id, null, $category); + return new DataResponse($note->getCategory()); // @phan-suppress-current-line PhanTypeMismatchArgument + } + + + /** + * @NoAdminRequired + * + * @param int $id + * @param string $title + * @return DataResponse + */ + public function title($id, $title) { + $note = $this->notesService->setTitleCategory($this->userId, $id, $title, null); + return new DataResponse($note->getTitle()); // @phan-suppress-current-line PhanTypeMismatchArgument } diff --git a/lib/Service/NoteUtil.php b/lib/Service/NoteUtil.php index 8985da3a7..3a2e6ded0 100644 --- a/lib/Service/NoteUtil.php +++ b/lib/Service/NoteUtil.php @@ -67,7 +67,7 @@ public function isNote(FileInfo $file) : bool { return $file->getType() === 'file' && in_array($ext, $allowedExtensions); } - public function moveNote(Folder $notesFolder, File $file, $category, string $title) : void { + public function moveNote(Folder $notesFolder, File $file, string $title, ?string $category = null) : void { $id = $file->getId(); $currentFilePath = $this->root->getFullPath($file->getPath()); $currentBasePath = pathinfo($currentFilePath, PATHINFO_DIRNAME); @@ -229,7 +229,7 @@ public function deleteEmptyFolder(Folder $notesFolder, Folder $folder) : void { * @param int $requiredBytes amount of storage needed in $folder * @throws InsufficientStorageException */ - public function ensureSufficientStorage(Folder $folder, $requiredBytes) : void { + public function ensureSufficientStorage(Folder $folder, int $requiredBytes) : void { $availableBytes = $folder->getFreeSpace(); if ($availableBytes >= 0 && $availableBytes < $requiredBytes) { $this->logger->error( diff --git a/lib/Service/NotesService.php b/lib/Service/NotesService.php index eec5e61d2..8d8050ea1 100644 --- a/lib/Service/NotesService.php +++ b/lib/Service/NotesService.php @@ -65,7 +65,7 @@ public function __construct( * @param string $userId * @return array with all notes in the current directory */ - public function getAll($userId, $onlyMeta = false) { + public function getAll(string $userId, bool $onlyMeta = false) { $notesFolder = $this->getFolderForUser($userId); $notes = $this->noteUtil->gatherNoteFiles($notesFolder); $filesById = []; @@ -91,17 +91,17 @@ public function getAll($userId, $onlyMeta = false) { * @throws NoteDoesNotExistException if note does not exist * @return Note */ - public function get($id, $userId, $onlyMeta = false) : Note { + public function get(int $id, string $userId, bool $onlyMeta = false) : Note { $folder = $this->getFolderForUser($userId); return $this->getNote($this->getFileById($folder, $id), $folder, $this->getTags($id), $onlyMeta); } - private function getTags($id) { + private function getTags(int $id) { $tags = $this->tags->getTagsForObjects([$id]); return is_array($tags) && array_key_exists($id, $tags) ? $tags[$id] : []; } - private function getNote(File $file, Folder $notesFolder, $tags = [], $onlyMeta = false) : Note { + private function getNote(File $file, Folder $notesFolder, array $tags = [], bool $onlyMeta = false) : Note { $id = $file->getId(); try { $note = Note::fromFile($file, $notesFolder, $tags, $onlyMeta); @@ -122,7 +122,7 @@ private function getNote(File $file, Folder $notesFolder, $tags = [], $onlyMeta * @see update for setting note content * @return Note the newly created note */ - public function create($userId) : Note { + public function create(string $userId) : Note { $title = $this->l10n->t('New note'); $folder = $this->getFolderForUser($userId); $this->noteUtil->ensureSufficientStorage($folder, 1); @@ -160,7 +160,7 @@ public function create($userId) : Note { * @throws NoteDoesNotExistException if note does not exist * @return \OCA\Notes\Db\Note the updated note */ - public function update($id, $content, $userId, $category = null, $mtime = 0) : Note { + public function update(int $id, ?string $content, string $userId, ?string $category = null, int $mtime = 0) : Note { $notesFolder = $this->getFolderForUser($userId); $file = $this->getFileById($notesFolder, $id); $title = $this->noteUtil->getSafeTitleFromContent($content===null ? $file->getContent() : $content); @@ -168,9 +168,9 @@ public function update($id, $content, $userId, $category = null, $mtime = 0) : N // rename/move file with respect to title/category // this can fail if access rights are not sufficient or category name is illegal try { - $this->noteUtil->moveNote($notesFolder, $file, $category, $title); + $this->noteUtil->moveNote($notesFolder, $file, $title, $category); } catch (\OCP\Files\NotPermittedException $e) { - $err = 'Moving note '.$id.' ('.$title.') to the desired target is not allowed.' + $err = 'Moving note '.$file->getId().' ('.$title.') to the desired target is not allowed.' .' Please check the note\'s target category ('.$category.').'; $this->logger->error($err, ['app' => $this->appName]); } catch (\Exception $e) { @@ -180,8 +180,7 @@ public function update($id, $content, $userId, $category = null, $mtime = 0) : N } if ($content !== null) { - $this->noteUtil->ensureSufficientStorage($file->getParent(), strlen($content)); - $file->putContent($content); + $this->setContentForFile($file, $content); } if ($mtime) { @@ -191,6 +190,30 @@ public function update($id, $content, $userId, $category = null, $mtime = 0) : N return $this->getNote($file, $notesFolder, $this->getTags($id)); } + private function setContentForFile(File $file, $content) : void { + $this->noteUtil->ensureSufficientStorage($file->getParent(), strlen($content)); + $file->putContent($content); + } + + public function setContent(string $userId, int $id, string $content) : Note { + $notesFolder = $this->getFolderForUser($userId); + $file = $this->getFileById($notesFolder, $id); + $this->setContentForFile($file, $content); + return $this->getNote($file, $notesFolder, $this->getTags($id)); + } + + public function setTitleCategory(string $userId, int $id, ?string $title, ?string $category = null) : Note { + $notesFolder = $this->getFolderForUser($userId); + $file = $this->getFileById($notesFolder, $id); + if ($title === null) { + $note = $this->getNote($file, $notesFolder, [], true); + $title = $note->getTitle(); + } + $this->noteUtil->moveNote($notesFolder, $file, $title, $category); + + 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 @@ -198,7 +221,7 @@ public function update($id, $content, $userId, $category = null, $mtime = 0) : N * @throws NoteDoesNotExistException if note does not exist * @return boolean the new favorite state of the note */ - public function favorite($id, $favorite, $userId) { + public function favorite(int $id, bool $favorite, string $userId) { $note = $this->get($id, $userId, true); if ($favorite !== $note->getFavorite()) { if ($favorite) { @@ -219,7 +242,7 @@ public function favorite($id, $favorite, $userId) { * @throws NoteDoesNotExistException if note does not * exist */ - public function delete($id, $userId) { + public function delete(int $id, string $userId) { $notesFolder = $this->getFolderForUser($userId); $file = $this->getFileById($notesFolder, $id); $parent = $file->getParent(); @@ -233,7 +256,7 @@ public function delete($id, $userId) { * @throws NoteDoesNotExistException * @return \OCP\Files\File */ - private function getFileById(Folder $folder, $id) : File { + private function getFileById(Folder $folder, int $id) : File { $file = $folder->getById($id); if (count($file) <= 0 || !($file[0] instanceof File) || !$this->noteUtil->isNote($file[0])) { @@ -246,7 +269,7 @@ private function getFileById(Folder $folder, $id) : File { * @param string $userId the user id * @return Folder */ - private function getFolderForUser($userId) : Folder { + private function getFolderForUser(string $userId) : Folder { // TODO use IRootFolder->getUserFolder() ? $path = '/' . $userId . '/files/' . $this->settings->get($userId, 'notesPath'); try { diff --git a/src/NotesService.js b/src/NotesService.js index a56f69897..05a45a0a1 100644 --- a/src/NotesService.js +++ b/src/NotesService.js @@ -77,6 +77,19 @@ export const fetchNote = noteId => { }) } +export const setTitle = (noteId, title) => { + return axios + .put(url('/notes/' + noteId + '/title'), { title: title }) + .then(response => { + store.commit('setNoteAttribute', { noteId: noteId, attribute: 'title', value: response.data }) + }) + .catch(err => { + console.error(err) + handleSyncError(t('notes', 'Renaming note {id} has failed.', { id: noteId })) + throw err + }) +} + export const createNote = category => { return axios .post(url('/notes'), { category: category }) diff --git a/src/components/NavigationNoteItem.vue b/src/components/NavigationNoteItem.vue index 17637b714..94edcd290 100644 --- a/src/components/NavigationNoteItem.vue +++ b/src/components/NavigationNoteItem.vue @@ -5,17 +5,23 @@ :menu-open.sync="actionsOpen" :to="{ name: 'note', params: { noteId: note.id.toString() } }" :class="{ actionsOpen }" + :loading="loading.note" + :editable="true" + :edit-label="t('notes', 'Rename')" + :edit-placeholder="t('notes', 'Note\'s title')" + @update:title="onRename" > @@ -23,17 +29,19 @@