diff --git a/apps/files/src/actions/downloadAction.ts b/apps/files/src/actions/downloadAction.ts index 9a3ae828cb6..ce9f22450e9 100644 --- a/apps/files/src/actions/downloadAction.ts +++ b/apps/files/src/actions/downloadAction.ts @@ -55,7 +55,7 @@ export const action = new FileAction({ // some folders, we need to use the /apps/files/ajax/download.php // endpoint, which only supports user root folder. if (nodes.some(node => node.type === FileType.Folder) - && !nodes.every(node => node.root?.startsWith('/files'))) { + && nodes.some(node => !node.root?.startsWith('/files'))) { return false } diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index d08f5a11874..b7785e623b0 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -382,8 +382,7 @@ export default Vue.extend({ this.pathsStore.addPath({ service: currentView.id, fileid: node.fileid, path: join(dir, node.basename) }) }) } catch (error) { - throw error - // logger.error('Error while fetching content', { error }) + logger.error('Error while fetching content', { error }) } finally { this.loading = false } diff --git a/apps/files/src/views/Sidebar.vue b/apps/files/src/views/Sidebar.vue index 65e4c302632..b9804d7931e 100644 --- a/apps/files/src/views/Sidebar.vue +++ b/apps/files/src/views/Sidebar.vue @@ -91,6 +91,7 @@ import { emit } from '@nextcloud/event-bus' import { encodePath } from '@nextcloud/paths' import { File, Folder } from '@nextcloud/files' +import { getCapabilities } from '@nextcloud/capabilities' import { getCurrentUser } from '@nextcloud/auth' import { Type as ShareTypes } from '@nextcloud/sharing' import $ from 'jquery' @@ -299,7 +300,7 @@ export default { }, isSystemTagsEnabled() { - return OCA && 'SystemTags' in OCA + return getCapabilities()?.systemtags?.enabled === true }, }, created() { diff --git a/apps/systemtags/composer/composer/autoload_classmap.php b/apps/systemtags/composer/composer/autoload_classmap.php index 604b7df1672..66d788547c6 100644 --- a/apps/systemtags/composer/composer/autoload_classmap.php +++ b/apps/systemtags/composer/composer/autoload_classmap.php @@ -11,6 +11,7 @@ return array( 'OCA\\SystemTags\\Activity\\Provider' => $baseDir . '/../lib/Activity/Provider.php', 'OCA\\SystemTags\\Activity\\Setting' => $baseDir . '/../lib/Activity/Setting.php', 'OCA\\SystemTags\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', + 'OCA\\SystemTags\\Capabilities' => $baseDir . '/../lib/Capabilities.php', 'OCA\\SystemTags\\Controller\\LastUsedController' => $baseDir . '/../lib/Controller/LastUsedController.php', 'OCA\\SystemTags\\Search\\TagSearchProvider' => $baseDir . '/../lib/Search/TagSearchProvider.php', 'OCA\\SystemTags\\Settings\\Admin' => $baseDir . '/../lib/Settings/Admin.php', diff --git a/apps/systemtags/composer/composer/autoload_static.php b/apps/systemtags/composer/composer/autoload_static.php index 9c77f6d7a43..c1ea8635181 100644 --- a/apps/systemtags/composer/composer/autoload_static.php +++ b/apps/systemtags/composer/composer/autoload_static.php @@ -26,6 +26,7 @@ class ComposerStaticInitSystemTags 'OCA\\SystemTags\\Activity\\Provider' => __DIR__ . '/..' . '/../lib/Activity/Provider.php', 'OCA\\SystemTags\\Activity\\Setting' => __DIR__ . '/..' . '/../lib/Activity/Setting.php', 'OCA\\SystemTags\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', + 'OCA\\SystemTags\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php', 'OCA\\SystemTags\\Controller\\LastUsedController' => __DIR__ . '/..' . '/../lib/Controller/LastUsedController.php', 'OCA\\SystemTags\\Search\\TagSearchProvider' => __DIR__ . '/..' . '/../lib/Search/TagSearchProvider.php', 'OCA\\SystemTags\\Settings\\Admin' => __DIR__ . '/..' . '/../lib/Settings/Admin.php', diff --git a/apps/systemtags/lib/AppInfo/Application.php b/apps/systemtags/lib/AppInfo/Application.php index c07f32e81c1..7484438092c 100644 --- a/apps/systemtags/lib/AppInfo/Application.php +++ b/apps/systemtags/lib/AppInfo/Application.php @@ -28,6 +28,7 @@ namespace OCA\SystemTags\AppInfo; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\SystemTags\Search\TagSearchProvider; use OCA\SystemTags\Activity\Listener; +use OCA\SystemTags\Capabilities; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; @@ -45,6 +46,7 @@ class Application extends App implements IBootstrap { public function register(IRegistrationContext $context): void { $context->registerSearchProvider(TagSearchProvider::class); + $context->registerCapability(Capabilities::class); } public function boot(IBootContext $context): void { @@ -77,16 +79,5 @@ class Application extends App implements IBootstrap { $dispatcher->addListener(MapperEvent::EVENT_ASSIGN, $mapperListener); $dispatcher->addListener(MapperEvent::EVENT_UNASSIGN, $mapperListener); }); - - \OCA\Files\App::getNavigationManager()->add(function () { - $l = \OC::$server->getL10N(self::APP_ID); - return [ - 'id' => 'systemtagsfilter', - 'appname' => self::APP_ID, - 'script' => 'list.php', - 'order' => 25, - 'name' => $l->t('Tags'), - ]; - }); } } diff --git a/apps/systemtags/lib/Capabilities.php b/apps/systemtags/lib/Capabilities.php new file mode 100644 index 00000000000..5da70a17758 --- /dev/null +++ b/apps/systemtags/lib/Capabilities.php @@ -0,0 +1,40 @@ + + * + * @author John Molakvoæ + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\SystemTags; + +use OCP\Capabilities\ICapability; + +class Capabilities implements ICapability { + /** + * @return array{systemtags: array{enabled: true}} + */ + public function getCapabilities() { + $capabilities = [ + 'systemtags' => [ + 'enabled' => true, + ] + ]; + return $capabilities; + } +} diff --git a/apps/systemtags/src/css/systemtagsfilelist.scss b/apps/systemtags/src/css/systemtagsfilelist.scss deleted file mode 100644 index 4068eb2d8c5..00000000000 --- a/apps/systemtags/src/css/systemtagsfilelist.scss +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2016 - * - * This file is licensed under the Affero General Public License version 3 - * or later. - * - * See the COPYING-README file. - * - */ -#app-content-systemtagsfilter .select2-container { - width: 30%; - margin-left: 10px; -} - -#app-sidebar .app-sidebar-header__action .tag-label { - cursor: pointer; - padding: 13px 0; - display: flex; - color: var(--color-text-light); - position: relative; - margin-top: -20px; -} diff --git a/apps/systemtags/src/services/systemtags.ts b/apps/systemtags/src/services/systemtags.ts index d5ef942b91a..4e81ec7dce0 100644 --- a/apps/systemtags/src/services/systemtags.ts +++ b/apps/systemtags/src/services/systemtags.ts @@ -30,8 +30,6 @@ import { fetchTags } from './api' import { getClient } from '../../../files/src/services/WebdavClient' import { resultToNode } from '../../../files/src/services/Files' -let tagsCache = [] as TagWithId[] - const formatReportPayload = (tagId: number) => ` @@ -58,7 +56,7 @@ const tagToNode = function(tag: TagWithId): Folder { export const getContents = async (path = '/'): Promise => { // List tags in the root - tagsCache = await fetchTags() + const tagsCache = (await fetchTags()).filter(tag => tag.userVisible) as TagWithId[] if (path === '/') { return { @@ -67,6 +65,7 @@ export const getContents = async (path = '/'): Promise => { source: generateRemoteUrl('dav/systemtags'), owner: getCurrentUser()?.uid as string, root: '/systemtags', + permissions: Permission.NONE, }), contents: tagsCache.map(tagToNode), } diff --git a/apps/systemtags/tests/js/systemtagsfilelistSpec.js b/apps/systemtags/tests/js/systemtagsfilelistSpec.js deleted file mode 100644 index facdf8dc42c..00000000000 --- a/apps/systemtags/tests/js/systemtagsfilelistSpec.js +++ /dev/null @@ -1,240 +0,0 @@ -/** - * Copyright (c) 2016 Vincent Petry - * - * @author Christoph Wurst - * @author Vincent Petry - * - * @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 . - * - */ - -describe('OCA.SystemTags.FileList tests', function() { - var FileInfo = OC.Files.FileInfo; - var fileList; - - beforeEach(function() { - // init parameters and test table elements - $('#testArea').append( - '
' + - // init horrible parameters - '' + - '
' + - // dummy table - // TODO: at some point this will be rendered by the fileList class itself! - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
' + - '
Empty content message
' + - '
' - ); - }); - afterEach(function() { - fileList.destroy(); - fileList = undefined; - }); - - describe('filter field', function() { - var select2Stub, oldCollection, fetchTagsStub; - var $tagsField; - - beforeEach(function() { - fetchTagsStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); - select2Stub = sinon.stub($.fn, 'select2'); - oldCollection = OC.SystemTags.collection; - OC.SystemTags.collection = new OC.SystemTags.SystemTagsCollection([ - { - id: '123', - name: 'abc' - }, - { - id: '456', - name: 'def' - } - ]); - - fileList = new OCA.SystemTags.FileList( - $('#app-content'), { - systemTagIds: [] - } - ); - $tagsField = fileList.$el.find('[name=tags]'); - }); - afterEach(function() { - select2Stub.restore(); - fetchTagsStub.restore(); - OC.SystemTags.collection = oldCollection; - }); - it('inits select2 on filter field', function() { - expect(select2Stub.calledOnce).toEqual(true); - }); - it('uses global system tags collection', function() { - var callback = sinon.stub(); - var opts = select2Stub.firstCall.args[0]; - - $tagsField.val('123'); - - opts.initSelection($tagsField, callback); - - expect(callback.notCalled).toEqual(true); - expect(fetchTagsStub.calledOnce).toEqual(true); - - fetchTagsStub.yieldTo('success', fetchTagsStub.thisValues[0]); - - expect(callback.calledOnce).toEqual(true); - expect(callback.lastCall.args[0]).toEqual([ - OC.SystemTags.collection.get('123').toJSON() - ]); - }); - it('fetches tag list from the global collection', function() { - var callback = sinon.stub(); - var opts = select2Stub.firstCall.args[0]; - - $tagsField.val('123'); - - opts.query({ - term: 'de', - callback: callback - }); - - expect(fetchTagsStub.calledOnce).toEqual(true); - expect(callback.notCalled).toEqual(true); - fetchTagsStub.yieldTo('success', fetchTagsStub.thisValues[0]); - - expect(callback.calledOnce).toEqual(true); - expect(callback.lastCall.args[0]).toEqual({ - results: [ - OC.SystemTags.collection.get('456').toJSON() - ] - }); - }); - it('reloads file list after selection', function() { - var reloadStub = sinon.stub(fileList, 'reload'); - $tagsField.val('456,123').change(); - expect(reloadStub.calledOnce).toEqual(true); - reloadStub.restore(); - }); - it('updates URL after selection', function() { - var handler = sinon.stub(); - fileList.$el.on('changeDirectory', handler); - $tagsField.val('456,123').change(); - - expect(handler.calledOnce).toEqual(true); - expect(handler.lastCall.args[0].dir).toEqual('456/123'); - }); - it('updates tag selection when url changed', function() { - fileList.$el.trigger(new $.Event('urlChanged', {dir: '456/123'})); - - expect(select2Stub.lastCall.args[0]).toEqual('val'); - expect(select2Stub.lastCall.args[1]).toEqual(['456', '123']); - }); - }); - - describe('loading results', function() { - var getFilteredFilesSpec, requestDeferred; - - beforeEach(function() { - requestDeferred = new $.Deferred(); - getFilteredFilesSpec = sinon.stub(OC.Files.Client.prototype, 'getFilteredFiles') - .returns(requestDeferred.promise()); - }); - afterEach(function() { - getFilteredFilesSpec.restore(); - }); - - it('renders empty message when no tags were set', function() { - fileList = new OCA.SystemTags.FileList( - $('#app-content'), { - systemTagIds: [] - } - ); - - fileList.reload(); - - expect(fileList.$el.find('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(false); - - expect(getFilteredFilesSpec.notCalled).toEqual(true); - }); - - it('render files', function(done) { - fileList = new OCA.SystemTags.FileList( - $('#app-content'), { - systemTagIds: ['123', '456'] - } - ); - - var reloading = fileList.reload(); - - expect(getFilteredFilesSpec.calledOnce).toEqual(true); - expect(getFilteredFilesSpec.lastCall.args[0].systemTagIds).toEqual(['123', '456']); - - var testFiles = [new FileInfo({ - id: 1, - type: 'file', - name: 'One.txt', - mimetype: 'text/plain', - mtime: 123456789, - size: 12, - etag: 'abc', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 2, - type: 'file', - name: 'Two.jpg', - mimetype: 'image/jpeg', - mtime: 234567890, - size: 12049, - etag: 'def', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 3, - type: 'file', - name: 'Three.pdf', - mimetype: 'application/pdf', - mtime: 234560000, - size: 58009, - etag: '123', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 4, - type: 'dir', - name: 'somedir', - mimetype: 'httpd/unix-directory', - mtime: 134560000, - size: 250, - etag: '456', - permissions: OC.PERMISSION_ALL - })]; - - requestDeferred.resolve(207, testFiles); - - return reloading.then(function() { - expect(fileList.$el.find('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(true); - expect(fileList.$el.find('tbody>tr').length).toEqual(4); - }).then(done, done); - }); - }); -}); diff --git a/dist/files-main.js b/dist/files-main.js index 9a1867d0445..b5e94e056b4 100644 Binary files a/dist/files-main.js and b/dist/files-main.js differ diff --git a/dist/files-main.js.map b/dist/files-main.js.map index 73529bdc8ff..99734eec402 100644 Binary files a/dist/files-main.js.map and b/dist/files-main.js.map differ diff --git a/dist/files-sidebar.js b/dist/files-sidebar.js index e36ddc3587e..596099aa1eb 100644 Binary files a/dist/files-sidebar.js and b/dist/files-sidebar.js differ diff --git a/dist/files-sidebar.js.map b/dist/files-sidebar.js.map index 63cd6ea938d..176fafc2590 100644 Binary files a/dist/files-sidebar.js.map and b/dist/files-sidebar.js.map differ diff --git a/dist/systemtags-init.js b/dist/systemtags-init.js index 92c72bd5ddc..40d5bac58a8 100644 Binary files a/dist/systemtags-init.js and b/dist/systemtags-init.js differ diff --git a/dist/systemtags-init.js.map b/dist/systemtags-init.js.map index 362003c6565..8b9586ce454 100644 Binary files a/dist/systemtags-init.js.map and b/dist/systemtags-init.js.map differ diff --git a/tests/karma.config.js b/tests/karma.config.js index 31fcae5de32..c164c662926 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -65,7 +65,6 @@ module.exports = function(config) { ], testFiles: ['apps/files_sharing/tests/js/*.js'] }, - 'systemtags', 'files_trashbin', ]; }