Skip to content

Commit

Permalink
manual edit of a note's title
Browse files Browse the repository at this point in the history
  • Loading branch information
korelstar committed Feb 25, 2020
1 parent 65387c0 commit 5490052
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 23 deletions.
6 changes: 6 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
19 changes: 16 additions & 3 deletions lib/Controller/NotesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
}


Expand Down
4 changes: 2 additions & 2 deletions lib/Service/NoteUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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(
Expand Down
51 changes: 37 additions & 14 deletions lib/Service/NotesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -160,17 +160,17 @@ 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);

// 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) {
Expand All @@ -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) {
Expand All @@ -191,14 +190,38 @@ 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
* @param boolean $favorite whether the note should be a favorite or not
* @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) {
Expand All @@ -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();
Expand All @@ -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])) {
Expand All @@ -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 {
Expand Down
13 changes: 13 additions & 0 deletions src/NotesService.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down
27 changes: 23 additions & 4 deletions src/components/NavigationNoteItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,43 @@
: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"
>
<template #actions>
<ActionButton :icon="actionFavoriteIcon" @click="onToggleFavorite">
{{ actionFavoriteText }}
</ActionButton>
<ActionButton icon="icon-files-dark" @click="onCategorySelected">
{{ actionCategoryText }}
</ActionButton>
<ActionButton :icon="actionDeleteIcon" @click="onDeleteNote">
{{ t('notes', 'Delete note') }}
</ActionButton>
<ActionSeparator />
<ActionButton icon="icon-files-dark" @click="onCategorySelected">
{{ actionCategoryText }}
</ActionButton>
</template>
</AppNavigationItem>
</template>

<script>
import {
ActionButton,
ActionSeparator,
AppNavigationItem,
} from '@nextcloud/vue'
import { showError } from '@nextcloud/dialogs'
import { categoryLabel, setFavorite, fetchNote, deleteNote } from '../NotesService'
import { categoryLabel, setFavorite, setTitle, fetchNote, deleteNote } from '../NotesService'
export default {
name: 'NavigationNoteItem',
components: {
ActionButton,
ActionSeparator,
AppNavigationItem,
},
Expand All @@ -47,6 +55,7 @@ export default {
data: function() {
return {
loading: {
note: false,
favorite: false,
delete: false,
},
Expand Down Expand Up @@ -107,6 +116,16 @@ export default {
this.$emit('category-selected', this.note.category)
},
onRename(newTitle) {
this.loading.note = true
setTitle(this.note.id, newTitle)
.catch(() => {
})
.finally(() => {
this.loading.note = false
})
},
onDeleteNote() {
this.loading.delete = true
fetchNote(this.note.id)
Expand Down

0 comments on commit 5490052

Please sign in to comment.