Browse Source

Render inline system tags using new DAV properties API

Signed-off-by: Lucas Azevedo <lhs_azevedo@hotmail.com>
Lucas Azevedo 8 months ago
parent
commit
146e9eeb9f

+ 0 - 34
apps/files/css/files.scss

@@ -406,40 +406,6 @@ table {
 			z-index: 10;
 			padding: 0 20px 0 0;
 		}
-
-		/* System tags */
-		.system-tags {
-			--min-size: 32px;
-			display: flex;
-			justify-content: center;
-			align-items: center;
-			min-width: calc(var(--min-size) * 2);
-			max-width: 300px;
-
-			.system-tags__tag {
-				padding: 5px 10px;
-				border: 1px solid;
-				border-radius: var(--border-radius-pill);
-				border-color: var(--color-border);
-				color: var(--color-text-maxcontrast);
-				height: var(--min-size);
-				white-space: nowrap;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				line-height: 22px; // min-size - 2 * 5px padding
-				text-align: center;
-
-				&--more {
-					overflow: visible;
-					text-overflow: initial;
-				}
-
-				// Proper spacing if multiple shown
-				& + .system-tags__tag {
-					margin-left: 5px;
-				}
-			}
-		}
 	}
 }
 

+ 0 - 1
apps/files/js/merged-index.json

@@ -24,6 +24,5 @@
   "sidebarpreviewmanager.js",
   "sidebarpreviewtext.js",
   "tagsplugin.js",
-  "systemtagsplugin.js",
   "templates.js"
 ]

+ 0 - 128
apps/files/js/systemtagsplugin.js

@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
- *
- * This file is licensed under the Affero General Public License version 3
- * or later.
- *
- * See the COPYING-README file.
- *
- */
-
-/* global Handlebars */
-
-(function (OCA) {
-
-	_.extend(OC.Files.Client, {
-		PROPERTY_SYSTEM_TAGS: '{' + OC.Files.Client.NS_NEXTCLOUD + '}system-tags',
-	});
-
-	OCA.Files = OCA.Files || {};
-
-	/**
-	 * Extends the file actions and file list to add system tags inline
-	 *
-	 * @namespace OCA.Files.SystemTagsPlugin
-	 */
-	OCA.Files.SystemTagsPlugin = {
-		name: 'SystemTags',
-
-		allowedLists: [
-			'files',
-			'favorites',
-			'shares.self',
-			'shares.others',
-			'shares.link'
-		],
-		
-		_buildTagSpan: function(tag, isMore = false) {
-			var $tag = $('<li class="system-tags__tag"></li>');
-			$tag.text(tag).addClass(isMore ? 'system-tags__tag--more' : '');
-			return $tag;
-		},
-
-		_buildTagsUI: function(tags) {
-			$systemTags = $('<ul class="system-tags"></ul>');
-			if (tags.length === 1) {
-				$systemTags.attr('aria-label', t('files', 'This file has the tag {tag}', { tag: tags[0] }));
-			} else if (tags.length > 1) {
-				var firstTags = tags.slice(0, -1).join(', ');
-				var lastTag = tags[tags.length - 1];
-				$systemTags.attr('aria-label', t('files', 'This file has the tags {firstTags} and {lastTag}', { firstTags, lastTag }));
-			}
-
-			if (tags.length > 0) {
-				$systemTags.append(this._buildTagSpan(tags[0]));
-			}
-
-			// More tags than the one we're showing
-			if (tags.length > 1) {
-				$moreTag = this._buildTagSpan('+' + (tags.length - 1), true)
-				$moreTag.attr('title', tags.slice(1).join(', '));
-				$systemTags.append($moreTag);
-			}
-
-			return $systemTags;
-		},
-
-		_extendFileList: function(fileList) {
-			var self = this;
-
-			// extend row prototype
-			var oldCreateRow = fileList._createRow;
-			fileList._createRow = function(fileData) {
-				var $tr = oldCreateRow.apply(this, arguments);
-				var systemTags = fileData.systemTags || [];
-
-				// Update tr data list
-				$tr.attr('data-systemTags', systemTags.join('|'));
-
-				// No tags, no need to do anything
-				if (systemTags.length === 0) {
-					return $tr;
-				}
-
-				// Build tags ui and inject
-				$systemTags = self._buildTagsUI.apply(self, [systemTags])
-				$systemTags.insertAfter($tr.find('td.filename .nametext'));
-				return $tr;
-			};
-
-			var oldElementToFile = fileList.elementToFile;
-			fileList.elementToFile = function ($el) {
-				var fileInfo = oldElementToFile.apply(this, arguments);
-				var systemTags = $el.attr('data-systemTags');
-				fileInfo.systemTags = systemTags?.split?.('|') || [];
-				return fileInfo;
-			};
-
-			var oldGetWebdavProperties = fileList._getWebdavProperties;
-			fileList._getWebdavProperties = function () {
-				var props = oldGetWebdavProperties.apply(this, arguments);
-				props.push(OC.Files.Client.PROPERTY_SYSTEM_TAGS);
-				return props;
-			};
-
-			fileList.filesClient.addFileInfoParser(function (response) {
-				var data = {};
-				var props = response.propStat[0].properties;
-				var systemTags = props[OC.Files.Client.PROPERTY_SYSTEM_TAGS] || [];
-				if (systemTags && systemTags.length) {
-					data.systemTags = systemTags
-						.filter(xmlvalue => xmlvalue.namespaceURI === OC.Files.Client.NS_NEXTCLOUD && xmlvalue.nodeName.split(':')[1] === 'system-tag')
-						.map(xmlvalue => xmlvalue.textContent || xmlvalue.text);
-				}
-				return data;
-			});
-		},
-
-		attach: function(fileList) {
-			if (this.allowedLists.indexOf(fileList.id) < 0) {
-				return;
-			}
-			this._extendFileList(fileList);
-		},
-	};
-})
-(OCA);
-
-OC.Plugins.register('OCA.Files.FileList', OCA.Files.SystemTagsPlugin);

+ 88 - 0
apps/files/src/actions/inlineSystemTagsAction.ts

@@ -0,0 +1,88 @@
+/**
+ * @copyright Copyright (c) 2023 Lucas Azevedo <lhs_azevedo@hotmail.com>
+ *
+ * @author Lucas Azevedo <lhs_azevedo@hotmail.com>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+import { FileAction, Node, registerDavProperty, registerFileAction } from "@nextcloud/files";
+import { translate as t } from '@nextcloud/l10n'
+
+import '../css/fileEntryInlineSystemTags.scss'
+
+const getNodeSystemTags = function (node: Node): string[] {
+	const tags = node.attributes?.['system-tags']?.['system-tag'] as string|string[]|undefined
+
+	if (tags === undefined) {
+		return []
+	}
+
+	return [tags].flat()
+}
+
+const renderTag = function (tag: string, isMore: boolean = false): HTMLElement {
+	const tagElement = document.createElement('li')
+	tagElement.classList.add('files-list__system-tag')
+	tagElement.innerText = tag
+
+	if (isMore) {
+		tagElement.classList.add('files-list__system-tag--more')
+	}
+
+	return tagElement;
+}
+
+export const action = new FileAction({
+	id: 'system-tags',
+	displayName: () => '',
+	iconSvgInline: () => '',
+	exec: async () => null,
+
+	async renderInline(node: Node) {
+		// Ensure we have the system tags as an array
+		const tags = getNodeSystemTags(node)
+
+		if (tags.length === 0) {
+			return null
+		}
+
+		const systemTagsElement = document.createElement('ul')
+		systemTagsElement.classList.add('files-list__system-tags')
+
+		if (tags.length === 1) {
+			systemTagsElement.setAttribute('aria-label', t('files', 'This file has the tag {tag}', { tag: tags[0] }));
+		} else {
+			var firstTags = tags.slice(0, -1).join(', ');
+			var lastTag = tags[tags.length - 1];
+			systemTagsElement.setAttribute('aria-label', t('files', 'This file has the tags {firstTags} and {lastTag}', { firstTags, lastTag }));
+		}
+
+		systemTagsElement.append(renderTag(tags[0]))
+		
+		// More tags than the one we're showing
+		if (tags.length > 1) {
+			const moreTagElement = renderTag('+' + (tags.length - 1), true)
+			moreTagElement.setAttribute('title', tags.slice(1).join(', '));
+			systemTagsElement.append(moreTagElement);
+		}
+
+		return systemTagsElement
+	}
+})
+
+registerDavProperty('nc:system-tags')
+registerFileAction(action)

+ 32 - 0
apps/files/src/css/fileEntryInlineSystemTags.scss

@@ -0,0 +1,32 @@
+.files-list__system-tags {
+    --min-size: 32px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    min-width: calc(var(--min-size) * 2);
+    max-width: 300px;
+}
+
+.files-list__system-tag {
+    padding: 5px 10px;
+    border: 1px solid;
+    border-radius: var(--border-radius-pill);
+    border-color: var(--color-border);
+    color: var(--color-text-maxcontrast);
+    height: var(--min-size);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    line-height: 22px; // min-size - 2 * 5px padding
+    text-align: center;
+
+    &--more {
+        overflow: visible;
+        text-overflow: initial;
+    }
+
+    // Proper spacing if multiple shown
+    & + .files-list__system-tag {
+        margin-left: 5px;
+    }
+}

+ 1 - 0
apps/files/src/main.ts

@@ -5,6 +5,7 @@ import './actions/deleteAction'
 import './actions/downloadAction'
 import './actions/editLocallyAction'
 import './actions/favoriteAction'
+import './actions/inlineSystemTagsAction'
 import './actions/openFolderAction'
 import './actions/openInFilesAction.js'
 import './actions/renameAction'