Skip to content

Commit c147030

Browse files
committed
feat(ui): Add rename/delete category actions in the sidebar
Signed-off-by: Grigorij Aronov <aronovgj@gmx.net>
1 parent dd96e04 commit c147030

File tree

4 files changed

+499
-34
lines changed

4 files changed

+499
-34
lines changed

src/App.vue

Lines changed: 106 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
<NcAppNavigation :class="{loading: loading.notes, 'icon-error': error}">
1010
<NcAppNavigationNew
1111
v-show="!loading.notes && !error"
12-
:text="t('notes', 'New note')"
13-
@click="onNewNote"
12+
:text="t('notes', 'New category')"
13+
@click="onNewCategory"
14+
@dragover.native="onNewCategoryDragOver"
15+
@drop.native="onNewCategoryDrop"
1416
>
15-
<PlusIcon slot="icon" :size="20" />
17+
<FolderPlusIcon slot="icon" :size="20" />
1618
</NcAppNavigationNew>
1719

1820
<template #list>
19-
<CategoriesList v-show="!loading.notes"
20-
v-if="numNotes"
21-
/>
21+
<CategoriesList v-show="!loading.notes" />
2222
</template>
2323

2424
<template #footer>
@@ -54,16 +54,17 @@ import NcContent from '@nextcloud/vue/components/NcContent'
5454
import { loadState } from '@nextcloud/initial-state'
5555
import { showSuccess, TOAST_UNDO_TIMEOUT, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs'
5656
import '@nextcloud/dialogs/style.css'
57+
import { emit } from '@nextcloud/event-bus'
5758
58-
import PlusIcon from 'vue-material-design-icons/Plus.vue'
5959
import CogIcon from 'vue-material-design-icons/CogOutline.vue'
60+
import FolderPlusIcon from 'vue-material-design-icons/FolderPlus.vue'
6061
6162
import AppSettings from './components/AppSettings.vue'
6263
import CategoriesList from './components/CategoriesList.vue'
6364
import EditorHint from './components/Modal/EditorHint.vue'
6465
6566
import { config } from './config.js'
66-
import { fetchNotes, noteExists, createNote, undoDeleteNote } from './NotesService.js'
67+
import { fetchNotes, noteExists, undoDeleteNote } from './NotesService.js'
6768
import store from './store.js'
6869
6970
export default {
@@ -79,7 +80,7 @@ export default {
7980
NcAppNavigationNew,
8081
NcAppNavigationItem,
8182
NcContent,
82-
PlusIcon,
83+
FolderPlusIcon,
8384
},
8485
8586
data() {
@@ -89,7 +90,6 @@ export default {
8990
},
9091
loading: {
9192
notes: true,
92-
create: false,
9393
},
9494
error: false,
9595
undoNotification: null,
@@ -227,20 +227,89 @@ export default {
227227
this.settingsVisible = true
228228
},
229229
230-
onNewNote() {
231-
if (this.loading.create) {
230+
onNewCategory() {
231+
emit('notes:category:new')
232+
},
233+
234+
onNewCategoryDragOver(event) {
235+
if (!this.isNoteDrag(event)) {
232236
return
233237
}
234-
this.loading.create = true
235-
createNote(store.getters.getSelectedCategory())
236-
.then(note => {
237-
this.routeToNote(note.id, { new: null })
238-
})
239-
.catch(() => {
240-
})
241-
.finally(() => {
242-
this.loading.create = false
243-
})
238+
event.preventDefault()
239+
if (event.dataTransfer) {
240+
event.dataTransfer.dropEffect = 'move'
241+
}
242+
},
243+
244+
onNewCategoryDrop(event) {
245+
const noteId = this.getDraggedNoteId(event)
246+
if (noteId === null) {
247+
return
248+
}
249+
event.preventDefault()
250+
event.stopPropagation()
251+
emit('notes:category:new', { noteId })
252+
},
253+
254+
getDraggedNoteId(event) {
255+
const dt = event?.dataTransfer
256+
if (!dt) {
257+
return null
258+
}
259+
260+
const types = Array.from(dt.types ?? [])
261+
const hasCustom = types.includes('application/x-nextcloud-notes-note-id')
262+
const hasUri = types.includes('text/uri-list')
263+
if (!hasCustom && hasUri) {
264+
return null
265+
}
266+
267+
let raw = ''
268+
if (hasCustom) {
269+
try {
270+
raw = dt.getData('application/x-nextcloud-notes-note-id')
271+
} catch {
272+
// Some browsers only allow specific mime types.
273+
}
274+
}
275+
if (!raw) {
276+
try {
277+
raw = dt.getData('text/plain')
278+
} catch {
279+
raw = ''
280+
}
281+
}
282+
283+
const match = /^\s*(\d+)\s*$/.exec(raw)
284+
const parsedId = match ? Number.parseInt(match[1], 10) : Number.NaN
285+
if (!Number.isFinite(parsedId)) {
286+
return null
287+
}
288+
const note = store.getters.getNote(parsedId)
289+
if (!note || note.readonly) {
290+
return null
291+
}
292+
293+
return parsedId
294+
},
295+
296+
isNoteDrag(event) {
297+
const dt = event?.dataTransfer
298+
if (!dt) {
299+
return false
300+
}
301+
const types = Array.from(dt.types ?? [])
302+
if (types.includes('application/x-nextcloud-notes-note-id')) {
303+
return true
304+
}
305+
if (types.includes('text/uri-list')) {
306+
return false
307+
}
308+
try {
309+
return /^\s*\d+\s*$/.test(dt.getData('text/plain'))
310+
} catch {
311+
return false
312+
}
244313
},
245314
246315
onNoteDeleted(note) {
@@ -325,4 +394,19 @@ export default {
325394
padding-inline-start: 3px;
326395
margin: 0 3px;
327396
}
397+
398+
:deep(.app-navigation__body) {
399+
overflow: hidden !important;
400+
flex: 0 0 auto;
401+
}
402+
403+
:deep(.app-navigation__content) {
404+
min-height: 0;
405+
}
406+
407+
:deep(.app-navigation__list) {
408+
flex: 1 1 auto;
409+
min-height: 0;
410+
height: auto !important;
411+
}
328412
</style>

0 commit comments

Comments
 (0)