aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2025-03-02 15:42:45 +0100
committerFerdinand Thiessen <opensource@fthiessen.de>2025-03-02 15:42:45 +0100
commitda3377075243f21e650c902cb8a5a78d08b5714e (patch)
tree74dd8286913321e10a9efc17c6ea0f5fc7e21ebf
parent321254fb864573b03351519a5bca8ac18e1c4096 (diff)
downloadnextcloud-server-da3377075243f21e650c902cb8a5a78d08b5714e.tar.gz
nextcloud-server-da3377075243f21e650c902cb8a5a78d08b5714e.zip
fix(systemtags): support new attribute parsing of webdav props
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r--apps/systemtags/src/files_actions/bulkSystemTagsAction.ts10
-rw-r--r--apps/systemtags/src/utils.spec.ts93
-rw-r--r--apps/systemtags/src/utils.ts17
3 files changed, 110 insertions, 10 deletions
diff --git a/apps/systemtags/src/files_actions/bulkSystemTagsAction.ts b/apps/systemtags/src/files_actions/bulkSystemTagsAction.ts
index c764db98f29..cdb1025f094 100644
--- a/apps/systemtags/src/files_actions/bulkSystemTagsAction.ts
+++ b/apps/systemtags/src/files_actions/bulkSystemTagsAction.ts
@@ -14,9 +14,11 @@ import { loadState } from '@nextcloud/initial-state'
import TagMultipleSvg from '@mdi/svg/svg/tag-multiple.svg?raw'
+const restrictSystemTagsCreationToAdmin = loadState<'0'|'1'>('settings', 'restrictSystemTagsCreationToAdmin', '0') === '1'
+
/**
- *
- * @param nodes
+ * Spawn a dialog to add or remove tags from multiple nodes.
+ * @param nodes Nodes to modify tags for
*/
async function execBatch(nodes: Node[]): Promise<(null|boolean)[]> {
const response = await new Promise<null|boolean>((resolve) => {
@@ -37,7 +39,7 @@ export const action = new FileAction({
// If the app is disabled, the action is not available anyway
enabled(nodes) {
// By default, everyone can create system tags
- if (loadState('settings', 'restrictSystemTagsCreationToAdmin', '0') === '1' && getCurrentUser()?.isAdmin !== true) {
+ if (restrictSystemTagsCreationToAdmin && getCurrentUser()?.isAdmin !== true) {
return false
}
@@ -50,7 +52,7 @@ export const action = new FileAction({
}
// Disabled for non dav resources
- if (nodes.some((node) => !node.isDavRessource)) {
+ if (nodes.some((node) => !node.isDavResource)) {
return false
}
diff --git a/apps/systemtags/src/utils.spec.ts b/apps/systemtags/src/utils.spec.ts
index a43d6db8ca6..e1c175c7475 100644
--- a/apps/systemtags/src/utils.spec.ts
+++ b/apps/systemtags/src/utils.spec.ts
@@ -5,9 +5,10 @@
import type { DAVResultResponseProps } from 'webdav'
import type { ServerTag, Tag } from './types.js'
-import { describe, expect, it } from 'vitest'
-import { formatTag, parseIdFromLocation, parseTags } from './utils'
+import { describe, expect, it } from 'vitest'
+import { formatTag, getNodeSystemTags, parseIdFromLocation, parseTags } from './utils'
+import { Folder } from '@nextcloud/files'
describe('systemtags - utils', () => {
describe('parseTags', () => {
@@ -85,4 +86,92 @@ describe('systemtags - utils', () => {
})
})
})
+
+ describe('getNodeSystemTags', () => {
+ it('parses a plain tag', () => {
+ const node = new Folder({
+ owner: 'test',
+ source: 'https://example.com/remote.php/dav/files/test/folder',
+ attributes: {
+ 'system-tags': {
+ 'system-tag': 'tag',
+ },
+ },
+ })
+ expect(getNodeSystemTags(node)).toStrictEqual(['tag'])
+ })
+
+ it('parses plain tags', () => {
+ const node = new Folder({
+ owner: 'test',
+ source: 'https://example.com/remote.php/dav/files/test/folder',
+ attributes: {
+ 'system-tags': {
+ 'system-tag': [
+ 'tag',
+ 'my-tag',
+ ],
+ },
+ },
+ })
+ expect(getNodeSystemTags(node)).toStrictEqual(['tag', 'my-tag'])
+ })
+
+ it('parses tag with attributes', () => {
+ const node = new Folder({
+ owner: 'test',
+ source: 'https://example.com/remote.php/dav/files/test/folder',
+ attributes: {
+ 'system-tags': {
+ 'system-tag': {
+ text: 'tag',
+ '@can-assign': true,
+ },
+ },
+ },
+ })
+ expect(getNodeSystemTags(node)).toStrictEqual(['tag'])
+ })
+
+ it('parses tags with attributes', () => {
+ const node = new Folder({
+ owner: 'test',
+ source: 'https://example.com/remote.php/dav/files/test/folder',
+ attributes: {
+ 'system-tags': {
+ 'system-tag': [
+ {
+ text: 'tag',
+ '@can-assign': true,
+ },
+ {
+ text: 'my-tag',
+ '@can-assign': false,
+ },
+ ],
+ },
+ },
+ })
+ expect(getNodeSystemTags(node)).toStrictEqual(['tag', 'my-tag'])
+ })
+
+ it('parses tags mixed with and without attributes', () => {
+ const node = new Folder({
+ owner: 'test',
+ source: 'https://example.com/remote.php/dav/files/test/folder',
+ attributes: {
+ 'system-tags': {
+ 'system-tag': [
+ 'tag',
+ {
+ text: 'my-tag',
+ '@can-assign': false,
+ },
+ ],
+ },
+ },
+ })
+ expect(getNodeSystemTags(node)).toStrictEqual(['tag', 'my-tag'])
+ })
+ })
})
diff --git a/apps/systemtags/src/utils.ts b/apps/systemtags/src/utils.ts
index 35fed6026f3..6b886e836ec 100644
--- a/apps/systemtags/src/utils.ts
+++ b/apps/systemtags/src/utils.ts
@@ -59,13 +59,22 @@ export const formatTag = (initialTag: Tag | ServerTag): ServerTag => {
}
export const getNodeSystemTags = function(node: Node): string[] {
- const tags = node.attributes?.['system-tags']?.['system-tag'] as string|string[]|undefined
-
- if (tags === undefined) {
+ const attribute = node.attributes?.['system-tags']?.['system-tag']
+ if (attribute === undefined) {
return []
}
- return [tags].flat()
+ // if there is only one tag it is a single string or prop object
+ // if there are multiple then its an array - so we flatten it to be always an array of string or prop objects
+ return [attribute]
+ .flat()
+ .map((tag: string|{ text: string }) => (
+ typeof tag === 'string'
+ // its a plain text prop (the tag name) without prop attributes
+ ? tag
+ // its a prop object with attributes, the tag name is in the 'text' attribute
+ : tag.text
+ ))
}
export const setNodeSystemTags = function(node: Node, tags: string[]): void {