fix(systemtags): support new attribute parsing of webdav props

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2025-03-02 15:42:45 +01:00
parent 321254fb86
commit da33770752
No known key found for this signature in database
GPG key ID: 45FAE7268762B400
3 changed files with 110 additions and 10 deletions

View file

@ -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
}

View file

@ -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'])
})
})
})

View file

@ -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 {