From e3b86314a65de514c896c9036c630c4020d05fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Trill=C3=B2?= Date: Thu, 9 Jul 2026 00:27:15 +0200 Subject: [PATCH] =?UTF-8?q?feat(systemtags):=20implement=20tag=20filter=20?= =?UTF-8?q?Assisted-by:=20Copilot:claude-sonnet-4-6=20Signed-off-by:=20Tom?= =?UTF-8?q?asz=20Trill=C3=B2=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/FileListFilterTags.vue | 117 ++++++++++++++++++ .../src/files_filters/TagsFilter.ts | 74 +++++++++++ apps/systemtags/src/init.ts | 2 + 3 files changed, 193 insertions(+) create mode 100644 apps/systemtags/src/components/FileListFilterTags.vue create mode 100644 apps/systemtags/src/files_filters/TagsFilter.ts diff --git a/apps/systemtags/src/components/FileListFilterTags.vue b/apps/systemtags/src/components/FileListFilterTags.vue new file mode 100644 index 0000000000000..a7a118ade9843 --- /dev/null +++ b/apps/systemtags/src/components/FileListFilterTags.vue @@ -0,0 +1,117 @@ + + + + diff --git a/apps/systemtags/src/files_filters/TagsFilter.ts b/apps/systemtags/src/files_filters/TagsFilter.ts new file mode 100644 index 0000000000000..c58f36843d693 --- /dev/null +++ b/apps/systemtags/src/files_filters/TagsFilter.ts @@ -0,0 +1,74 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import type { IFileListFilterChip, IFileListFilterWithUi, INode } from '@nextcloud/files' +import type { TagWithId } from '../types.ts' + +import svgTagOutline from '@mdi/svg/svg/tag-outline.svg?raw' +import { FileListFilter, registerFileListFilter } from '@nextcloud/files' +import { t } from '@nextcloud/l10n' +import { defineCustomElement } from 'vue' +import FileListFilterTagsCE from '../components/FileListFilterTags.vue' +import { getNodeSystemTags } from '../utils.ts' + +const tagName = 'systemtags-file-list-filter-tags' + +class TagsFilter extends FileListFilter implements IFileListFilterWithUi { + #selectedTags: TagWithId[] = [] + + public readonly displayName = t('systemtags', 'Tags') + public readonly iconSvgInline = svgTagOutline + public readonly tagName = tagName + + constructor() { + super('systemtags:tags', 75) + } + + public filter(nodes: INode[]): INode[] { + if (this.#selectedTags.length === 0) { + return nodes + } + + const selectedNames = this.#selectedTags.map((tag) => tag.displayName) + return nodes.filter((node) => { + const nodeTags = getNodeSystemTags(node) + return selectedNames.some((name) => nodeTags.includes(name)) + }) + } + + public reset(): void { + this.dispatchEvent(new CustomEvent('reset')) + } + + public get selectedTags(): TagWithId[] { + return this.#selectedTags + } + + public setTags(tags?: TagWithId[]): void { + this.#selectedTags = tags ?? [] + this.filterUpdated() + + const chips: IFileListFilterChip[] = this.#selectedTags.map((tag) => ({ + icon: svgTagOutline, + text: tag.displayName, + onclick: () => { + this.dispatchEvent(new CustomEvent('deselect', { detail: tag.id })) + this.setTags(this.#selectedTags.filter((t) => t.id !== tag.id)) + }, + })) + this.updateChips(chips) + } +} + +export type { TagsFilter } + +/** + * Register the file list filter by system tags + */ +export function registerTagsFilter() { + const TagsFilterElement = defineCustomElement(FileListFilterTagsCE, { shadowRoot: false }) + customElements.define(tagName, TagsFilterElement) + registerFileListFilter(new TagsFilter()) +} diff --git a/apps/systemtags/src/init.ts b/apps/systemtags/src/init.ts index c98cb3e7210af..6a5e00b201566 100644 --- a/apps/systemtags/src/init.ts +++ b/apps/systemtags/src/init.ts @@ -9,6 +9,7 @@ import { action as bulkSystemTagsAction } from './files_actions/bulkSystemTagsAc import { registerFileSidebarAction } from './files_actions/filesSidebarAction.ts' import { action as inlineSystemTagsAction } from './files_actions/inlineSystemTagsAction.ts' import { action as openInFilesAction } from './files_actions/openInFilesAction.ts' +import { registerTagsFilter } from './files_filters/TagsFilter.ts' import { registerSystemTagsView } from './files_views/systemtagsView.ts' registerDavProperty('nc:system-tags') @@ -18,3 +19,4 @@ registerFileAction(openInFilesAction) registerSystemTagsView() registerFileSidebarAction() +registerTagsFilter()