Skip to content

Commit 2134307

Browse files
theatischbeinjuliusknorr
authored andcommitted
Category: Add new category button to create new folders in current
notes path for categories. Signed-off-by: Jonathan Pagel <jonny_tischbein@systemli.org>
1 parent 32b4598 commit 2134307

File tree

4 files changed

+124
-10
lines changed

4 files changed

+124
-10
lines changed

package-lock.json

Lines changed: 9 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"stylelint:fix": "stylelint 'src/**/*.vue' 'css/**/*.css' --fix"
1414
},
1515
"dependencies": {
16+
"@nextcloud/auth": "^2.2.1",
1617
"@nextcloud/axios": "^2.4.0",
1718
"@nextcloud/dialogs": "^4.2.1",
1819
"@nextcloud/event-bus": "^3.1.0",

src/NotesService.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import axios from '@nextcloud/axios'
2-
import { generateUrl } from '@nextcloud/router'
2+
import { getCurrentUser } from '@nextcloud/auth'
3+
import { generateUrl, generateRemoteUrl } from '@nextcloud/router'
34
import { showError } from '@nextcloud/dialogs'
45

56
import store from './store.js'
@@ -338,6 +339,40 @@ export const setFavorite = (noteId, favorite) => {
338339
})
339340
}
340341

342+
export const findCategory = (categoryName) => {
343+
return axios
344+
.get(generateRemoteUrl(`dav/files/${getCurrentUser().uid}/${store.state.app.settings.notesPath}${categoryName}`))
345+
.then(response => {
346+
return categoryName
347+
})
348+
.catch(err => {
349+
if (err?.response?.status === 404) {
350+
return false
351+
} else {
352+
console.error(err)
353+
handleSyncError(t('notes', 'Fetching category {name} has failed.', { name: categoryName }), err)
354+
throw err
355+
}
356+
})
357+
}
358+
359+
export const createCategory = (categoryName) => {
360+
// Axios MKCOL workaround: https://github.com/axios/axios/issues/2220
361+
return axios
362+
.request({
363+
url: generateRemoteUrl(`dav/files/${getCurrentUser().uid}/${store.state.app.settings.notesPath}${categoryName}`),
364+
method: 'MKCOL',
365+
})
366+
.then(response => {
367+
return categoryName
368+
})
369+
.catch(err => {
370+
console.error(err)
371+
handleSyncError(t('notes', 'Creating new category {name} has failed.', { name: categoryName }), err)
372+
throw err
373+
})
374+
}
375+
341376
export const setCategory = (noteId, category) => {
342377
return axios
343378
.put(url('/notes/' + noteId + '/category'), { category })

src/components/CategoriesList.vue

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,38 @@
11
<template>
22
<Fragment>
3+
4+
<NcAppNavigationItem
5+
:title="title"
6+
class="app-navigation-noclose separator-below"
7+
:class="{ 'category-header': selectedCategory !== null }"
8+
:open.sync="open"
9+
:menu-open.sync="menuOpen"
10+
:allow-collapse="true"
11+
@click.prevent.stop="onToggleCategories"
12+
>
13+
<template #menu-icon>
14+
<AddIcon :size="20" @click="onToggleNewCategory" />
15+
</template>
16+
<template #actions>
17+
<NcActionText>
18+
<template #icon>
19+
<ErrorIcon v-if="createCategoryError" :size="20" />
20+
<AddIcon v-else-if="!createCategoryError" :size="20" />
21+
</template>
22+
{{ createCategoryError ? createCategoryError : t('notes', 'Create a new category') }}
23+
</NcActionText>
24+
<NcActionInput
25+
icon=""
26+
:value="t('notes', 'Category name')"
27+
@submit.prevent.stop="createNewCategory"
28+
>
29+
<template #icon>
30+
<FolderIcon :size="20" />
31+
</template>
32+
</NcActionInput>
33+
</template>
34+
35+
<FolderIcon slot="icon" :size="20" />
336
<NcAppNavigationItem
437
:title="t('notes', 'All notes')"
538
:class="{ active: selectedCategory === null }"
@@ -31,6 +64,8 @@
3164

3265
<script>
3366
import {
67+
NcActionInput,
68+
NcActionText,
3469
NcAppNavigationItem,
3570
NcAppNavigationCaption,
3671
NcAppNavigationCounter,
@@ -40,8 +75,10 @@ import { Fragment } from 'vue-fragment'
4075
import FolderIcon from 'vue-material-design-icons/Folder.vue'
4176
import FolderOutlineIcon from 'vue-material-design-icons/FolderOutline.vue'
4277
import HistoryIcon from 'vue-material-design-icons/History.vue'
78+
import AddIcon from 'vue-material-design-icons/Plus.vue'
79+
import ErrorIcon from 'vue-material-design-icons/AlertCircle.vue'
4380
44-
import { getCategories } from '../NotesService.js'
81+
import { createCategory, findCategory, getCategories } from '../NotesService.js'
4582
import { categoryLabel } from '../Util.js'
4683
import store from '../store.js'
4784
@@ -56,6 +93,18 @@ export default {
5693
FolderIcon,
5794
FolderOutlineIcon,
5895
HistoryIcon,
96+
AddIcon,
97+
ErrorIcon,
98+
NcActionInput,
99+
NcActionText,
100+
},
101+
102+
data() {
103+
return {
104+
open: false,
105+
menuOpen: false,
106+
createCategoryError: null,
107+
}
59108
},
60109
61110
computed: {
@@ -77,9 +126,37 @@ export default {
77126
return categoryLabel(category)
78127
},
79128
129+
onToggleCategories() {
130+
this.open = !this.open
131+
},
132+
133+
onToggleNewCategory() {
134+
this.menuOpen = !this.menuOpen
135+
},
136+
80137
onSelectCategory(category) {
81138
store.commit('setSelectedCategory', category)
82139
},
140+
141+
createNewCategory(event) {
142+
const input = event.target.querySelector('input[type=text]')
143+
const categoryName = input.value.trim()
144+
145+
// Check if already exists
146+
findCategory(categoryName).then(data => {
147+
if (data !== false) {
148+
this.createCategoryError = t('notes', 'This category already exists')
149+
return
150+
}
151+
152+
// Create new directory for category in current notes path defined in settings
153+
createCategory(categoryName)
154+
this.createCategoryError = null
155+
this.onToggleNewCategory()
156+
this.onSelectCategory(categoryName)
157+
})
158+
159+
},
83160
},
84161
}
85162
</script>

0 commit comments

Comments
 (0)