123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- /**
- * Copyright (c) 2016 Vincent Petry <pvince81@owncloud.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Vincent Petry <vincent@nextcloud.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/>.
- *
- */
- (function() {
- /**
- * @class OCA.SystemTags.FileList
- * @augments OCA.Files.FileList
- *
- * @classdesc SystemTags file list.
- * Contains a list of files filtered by system tags.
- *
- * @param {object} $el container element with existing markup for the .files-controls and a table
- * @param {Array} [options] map of options, see other parameters
- * @param {Array.<string>} [options.systemTagIds] array of system tag ids to
- * filter by
- */
- const FileList = function($el, options) {
- this.initialize($el, options)
- }
- FileList.prototype = _.extend(
- {},
- OCA.Files.FileList.prototype,
- /** @lends OCA.SystemTags.FileList.prototype */ {
- id: 'systemtagsfilter',
- appName: t('systemtags', 'Tagged files'),
- /**
- * Array of system tag ids to filter by
- *
- * @type {Array.<string>}
- */
- _systemTagIds: [],
- _lastUsedTags: [],
- _clientSideSort: true,
- _allowSelection: false,
- _filterField: null,
- /**
- * @private
- * @param {object} $el container element
- * @param {object} [options] map of options, see other parameters
- */
- initialize($el, options) {
- OCA.Files.FileList.prototype.initialize.apply(this, arguments)
- if (this.initialized) {
- return
- }
- if (options && options.systemTagIds) {
- this._systemTagIds = options.systemTagIds
- }
- OC.Plugins.attach('OCA.SystemTags.FileList', this)
- const $controls = this.$el.find('.files-controls').empty()
- _.defer(_.bind(this._getLastUsedTags, this))
- this._initFilterField($controls)
- },
- destroy() {
- this.$filterField.remove()
- OCA.Files.FileList.prototype.destroy.apply(this, arguments)
- },
- _getLastUsedTags() {
- const self = this
- $.ajax({
- type: 'GET',
- url: OC.generateUrl('/apps/systemtags/lastused'),
- success(response) {
- self._lastUsedTags = response
- },
- })
- },
- _initFilterField($container) {
- const self = this
- this.$filterField = $('<input type="hidden" name="tags"/>')
- this.$filterField.val(this._systemTagIds.join(','))
- $container.append(this.$filterField)
- this.$filterField.select2({
- placeholder: t('systemtags', 'Select tags to filter by'),
- allowClear: false,
- multiple: true,
- toggleSelect: true,
- separator: ',',
- query: _.bind(this._queryTagsAutocomplete, this),
- id(tag) {
- return tag.id
- },
- initSelection(element, callback) {
- const val = $(element)
- .val()
- .trim()
- if (val) {
- const tagIds = val.split(',')
- const tags = []
- OC.SystemTags.collection.fetch({
- success() {
- _.each(tagIds, function(tagId) {
- const tag = OC.SystemTags.collection.get(
- tagId
- )
- if (!_.isUndefined(tag)) {
- tags.push(tag.toJSON())
- }
- })
- callback(tags)
- self._onTagsChanged({ target: element })
- },
- })
- } else {
- // eslint-disable-next-line n/no-callback-literal
- callback([])
- }
- },
- formatResult(tag) {
- return OC.SystemTags.getDescriptiveTag(tag)
- },
- formatSelection(tag) {
- return OC.SystemTags.getDescriptiveTag(tag).outerHTML
- },
- sortResults(results) {
- results.sort(function(a, b) {
- const aLastUsed = self._lastUsedTags.indexOf(a.id)
- const bLastUsed = self._lastUsedTags.indexOf(b.id)
- if (aLastUsed !== bLastUsed) {
- if (bLastUsed === -1) {
- return -1
- }
- if (aLastUsed === -1) {
- return 1
- }
- return aLastUsed < bLastUsed ? -1 : 1
- }
- // Both not found
- return OC.Util.naturalSortCompare(a.name, b.name)
- })
- return results
- },
- escapeMarkup(m) {
- // prevent double markup escape
- return m
- },
- formatNoMatches() {
- return t('systemtags', 'No tags found')
- },
- })
- this.$filterField.parent().children('.select2-container').attr('aria-expanded', 'false')
- this.$filterField.on('select2-open', () => {
- this.$filterField.parent().children('.select2-container').attr('aria-expanded', 'true')
- })
- this.$filterField.on('select2-close', () => {
- this.$filterField.parent().children('.select2-container').attr('aria-expanded', 'false')
- })
- this.$filterField.on(
- 'change',
- _.bind(this._onTagsChanged, this)
- )
- return this.$filterField
- },
- /**
- * Autocomplete function for dropdown results
- *
- * @param {object} query select2 query object
- */
- _queryTagsAutocomplete(query) {
- OC.SystemTags.collection.fetch({
- success() {
- const results = OC.SystemTags.collection.filterByName(
- query.term
- )
- query.callback({
- results: _.invoke(results, 'toJSON'),
- })
- },
- })
- },
- /**
- * Event handler for when the URL changed
- *
- * @param {Event} e the urlchanged event
- */
- _onUrlChanged(e) {
- if (e.dir) {
- const tags = _.filter(e.dir.split('/'), function(val) {
- return val.trim() !== ''
- })
- this.$filterField.select2('val', tags || [])
- this._systemTagIds = tags
- this.reload()
- }
- },
- _onTagsChanged(ev) {
- const val = $(ev.target)
- .val()
- .trim()
- if (val !== '') {
- this._systemTagIds = val.split(',')
- } else {
- this._systemTagIds = []
- }
- this.$el.trigger(
- $.Event('changeDirectory', {
- dir: this._systemTagIds.join('/'),
- })
- )
- this.reload()
- },
- updateEmptyContent() {
- const dir = this.getCurrentDirectory()
- if (dir === '/') {
- // root has special permissions
- if (!this._systemTagIds.length) {
- // no tags selected
- this.$el
- .find('.emptyfilelist.emptycontent')
- .html(
- '<div class="icon-systemtags"></div>'
- + '<h2>'
- + t(
- 'systemtags',
- 'Please select tags to filter by'
- )
- + '</h2>'
- )
- } else {
- // tags selected but no results
- this.$el
- .find('.emptyfilelist.emptycontent')
- .html(
- '<div class="icon-systemtags"></div>'
- + '<h2>'
- + t(
- 'systemtags',
- 'No files found for the selected tags'
- )
- + '</h2>'
- )
- }
- this.$el
- .find('.emptyfilelist.emptycontent')
- .toggleClass('hidden', !this.isEmpty)
- this.$el
- .find('.files-filestable thead th')
- .toggleClass('hidden', this.isEmpty)
- } else {
- OCA.Files.FileList.prototype.updateEmptyContent.apply(
- this,
- arguments
- )
- }
- },
- getDirectoryPermissions() {
- return OC.PERMISSION_READ | OC.PERMISSION_DELETE
- },
- updateStorageStatistics() {
- // no op because it doesn't have
- // storage info like free space / used space
- },
- reload() {
- // there is only root
- this._setCurrentDir('/', false)
- if (!this._systemTagIds.length) {
- // don't reload
- this.updateEmptyContent()
- this.setFiles([])
- return $.Deferred().resolve()
- }
- this._selectedFiles = {}
- this._selectionSummary.clear()
- if (this._currentFileModel) {
- this._currentFileModel.off()
- }
- this._currentFileModel = null
- this.$el.find('.select-all').prop('checked', false)
- this.showMask()
- this._reloadCall = this.filesClient.getFilteredFiles(
- {
- systemTagIds: this._systemTagIds,
- },
- {
- properties: this._getWebdavProperties(),
- }
- )
- if (this._detailsView) {
- // close sidebar
- this._updateDetailsView(null)
- }
- const callBack = this.reloadCallback.bind(this)
- return this._reloadCall.then(callBack, callBack)
- },
- reloadCallback(status, result) {
- if (result) {
- // prepend empty dir info because original handler
- result.unshift({})
- }
- return OCA.Files.FileList.prototype.reloadCallback.call(
- this,
- status,
- result
- )
- },
- }
- )
- OCA.SystemTags.FileList = FileList
- })()
|