mirror of https://github.com/nextcloud/server.git
Render inline system tags using new DAV properties API
Signed-off-by: Lucas Azevedo <lhs_azevedo@hotmail.com>pull/40284/head
parent
c6e6ebb999
commit
146e9eeb9f
@ -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);
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue