diff options
author | Julius Härtl <jus@bitgrid.net> | 2019-09-09 16:20:33 +0200 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2019-09-10 09:01:26 +0200 |
commit | 335d7cfba3f767efe709eb27676c34c7086a2d68 (patch) | |
tree | 512183af76c0e375c35ce134d5950a94d6c2200c /apps/workflowengine | |
parent | e17a6665177f6c62ce5a067d0738f11f33021a8f (diff) | |
download | nextcloud-server-335d7cfba3f767efe709eb27676c34c7086a2d68.tar.gz nextcloud-server-335d7cfba3f767efe709eb27676c34c7086a2d68.zip |
Add tag selector
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'apps/workflowengine')
6 files changed, 312 insertions, 3 deletions
diff --git a/apps/workflowengine/src/components/Checks/FileSystemTag.vue b/apps/workflowengine/src/components/Checks/FileSystemTag.vue new file mode 100644 index 00000000000..ead4edf60c2 --- /dev/null +++ b/apps/workflowengine/src/components/Checks/FileSystemTag.vue @@ -0,0 +1,82 @@ +<!-- + - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> + - + - @author Julius Härtl <jus@bitgrid.net> + - + - @license GNU AGPL version 3 or any later version + - + - 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/>. + - + --> + +<template> + <MultiselectTag v-model="newValue" :multiple="false" + label="Select a tag" + @input="update" /> +</template> + +<script> + import { MultiselectTag } from './MultiselectTag' + + export default { + name: 'SizeValue', + components: { + MultiselectTag + }, + props: { + value: { + type: String, + default: '' + } + }, + data() { + return { + valid: false, + newValue: [] + } + }, + beforeMount() { + this.updateValue() + }, + watch: { + value() { + this.updateValue() + } + }, + methods: { + updateValue() { + if (this.value !== "") { + this.newValue = this.value + } else { + this.newValue = null + } + }, + validate() { + return true + }, + update() { + if (this.validate()) { + this.$emit('input', this.newValue || '') + this.valid = false + } else { + this.valid = false + } + } + } + } +</script> + +<style scoped> + +</style> diff --git a/apps/workflowengine/src/components/Checks/MultiselectTag/MultiselectTag.vue b/apps/workflowengine/src/components/Checks/MultiselectTag/MultiselectTag.vue new file mode 100644 index 00000000000..a046861b132 --- /dev/null +++ b/apps/workflowengine/src/components/Checks/MultiselectTag/MultiselectTag.vue @@ -0,0 +1,130 @@ +<!-- + - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> + - + - @author Julius Härtl <jus@bitgrid.net> + - + - @license GNU AGPL version 3 or any later version + - + - 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/>. + - + --> + +<template> + <Multiselect v-model="inputValObjects" + :options="tags" :options-limit="5" + :placeholder="label" + track-by="id" + :custom-label="tagLabel" + class="multiselect-vue" :multiple="multiple" + :close-on-select="false" :tag-width="60" + :disabled="disabled" @input="update" + @search-change="asyncFind"> + <span slot="noResult">{{ t('core', 'No results') }}</span> + <template #option="scope"> + {{ tagLabel(scope.option) }} + </template> + </multiselect> +</template> + +<script> +import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect' +import { searchTags } from './api' + +let uuid = 0 +export default { + name: 'MultiselectTag', + components: { + Multiselect + }, + props: { + label: { + type: String, + required: true + }, + value: { + default() { + return [] + } + }, + disabled: { + type: Boolean, + default: false + }, + multiple: { + type: Boolean, + default: true + } + }, + data() { + return { + inputValObjects: [], + tags: [] + } + }, + computed: { + id() { + return 'settings-input-text-' + this.uuid + } + }, + watch: { + value(newVal) { + this.inputValObjects = this.getValueObject() + } + }, + beforeCreate: function() { + this.uuid = uuid.toString() + uuid += 1 + searchTags().then((result) => { + this.tags = result + this.inputValObjects = this.getValueObject() + }) + }, + methods: { + asyncFind(query) { + }, + getValueObject() { + if (this.tags.length === 0) { + return [] + } + if (this.multiple) { + return this.value.filter((tag) => tag !== '').map( + (id) => this.tags.find((tag2) => tag2.id === id) + ) + } else { + return this.tags.find((tag) => tag.id === this.value) + } + }, + update() { + if (this.multiple) { + this.$emit('input', this.inputValObjects.map((element) => element.id)) + } else { + if (this.inputValObjects === null) { + this.$emit('input', '') + } else { + this.$emit('input', this.inputValObjects.id) + } + } + }, + tagLabel({ displayName, userVisible, userAssignable }) { + if (userVisible === false) { + return `${displayName} (invisible)` + } + if (userAssignable === false) { + return `${displayName} (restricted)` + } + return displayName + } + } +} +</script> diff --git a/apps/workflowengine/src/components/Checks/MultiselectTag/api.js b/apps/workflowengine/src/components/Checks/MultiselectTag/api.js new file mode 100644 index 00000000000..f371a4b71de --- /dev/null +++ b/apps/workflowengine/src/components/Checks/MultiselectTag/api.js @@ -0,0 +1,90 @@ +import axios from 'nextcloud-axios' +import { generateRemoteUrl } from 'nextcloud-router' + +const xmlToJson = (xml) => { + let obj = {} + + if (xml.nodeType === 1) { + if (xml.attributes.length > 0) { + obj['@attributes'] = {} + for (let j = 0; j < xml.attributes.length; j++) { + const attribute = xml.attributes.item(j) + obj['@attributes'][attribute.nodeName] = attribute.nodeValue + } + } + } else if (xml.nodeType === 3) { + obj = xml.nodeValue + } + + if (xml.hasChildNodes()) { + for (let i = 0; i < xml.childNodes.length; i++) { + const item = xml.childNodes.item(i) + const nodeName = item.nodeName + if (typeof (obj[nodeName]) === 'undefined') { + obj[nodeName] = xmlToJson(item) + } else { + if (typeof obj[nodeName].push === 'undefined') { + var old = obj[nodeName] + obj[nodeName] = [] + obj[nodeName].push(old) + } + obj[nodeName].push(xmlToJson(item)) + } + } + } + return obj +} + +const parseXml = (xml) => { + let dom = null + try { + dom = (new DOMParser()).parseFromString(xml, 'text/xml') + } catch (e) { + console.error('Failed to parse xml document', e) + } + return dom +} + +const xmlToTagList = (xml) => { + let json = xmlToJson(parseXml(xml)) + let list = json['d:multistatus']['d:response'] + let result = [] + for (let index in list) { + let tag = list[index]['d:propstat'] + + if (tag['d:status']['#text'] !== 'HTTP/1.1 200 OK') { + continue + } + result.push({ + id: tag['d:prop']['oc:id']['#text'], + displayName: tag['d:prop']['oc:display-name']['#text'], + canAssign: tag['d:prop']['oc:can-assign']['#text'] === 'true', + userAssignable: tag['d:prop']['oc:user-assignable']['#text'] === 'true', + userVisible: tag['d:prop']['oc:user-visible']['#text'] === 'true' + }) + } + return result +} + +const searchTags = function() { + return axios({ + method: 'PROPFIND', + url: generateRemoteUrl('dav') + '/systemtags/', + data: `<?xml version="1.0"?> + <d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns"> + <d:prop> + <oc:id /> + <oc:display-name /> + <oc:user-visible /> + <oc:user-assignable /> + <oc:can-assign /> + </d:prop> + </d:propfind>` + }).then((response) => { + return xmlToTagList(response.data) + }) +} + +export { + searchTags +} diff --git a/apps/workflowengine/src/components/Checks/MultiselectTag/index.js b/apps/workflowengine/src/components/Checks/MultiselectTag/index.js new file mode 100644 index 00000000000..69b7e277e76 --- /dev/null +++ b/apps/workflowengine/src/components/Checks/MultiselectTag/index.js @@ -0,0 +1,4 @@ +import MultiselectTag from './MultiselectTag' + +export default MultiselectTag +export { MultiselectTag } diff --git a/apps/workflowengine/src/components/Checks/file.js b/apps/workflowengine/src/components/Checks/file.js index 816aaa73a65..431a3f93580 100644 --- a/apps/workflowengine/src/components/Checks/file.js +++ b/apps/workflowengine/src/components/Checks/file.js @@ -22,6 +22,7 @@ import FileMimeType from './FileMimeType' import { stringValidator, validateIPv4, validateIPv6 } from './../../helpers/validators' +import FileSystemTag from './FileSystemTag'; const FileChecks = [ { class: 'OCA\\WorkflowEngine\\Check\\FileName', @@ -95,7 +96,8 @@ const FileChecks = [ operators: [ { operator: 'is', name: t('workflowengine', 'is tagged with') }, { operator: '!is', name: t('workflowengine', 'is not tagged with') } - ] + ], + component: FileSystemTag } ] diff --git a/apps/workflowengine/src/components/Checks/request.js b/apps/workflowengine/src/components/Checks/request.js index 5550555cf02..ee574f9de90 100644 --- a/apps/workflowengine/src/components/Checks/request.js +++ b/apps/workflowengine/src/components/Checks/request.js @@ -22,6 +22,7 @@ import RequestUserAgent from './RequestUserAgent' import RequestTime from './RequestTime' +import RequestURL from './RequestURL' const RequestChecks = [ { @@ -32,8 +33,8 @@ const RequestChecks = [ { operator: '!is', name: t('workflowengine', 'is not') }, { operator: 'matches', name: t('workflowengine', 'matches') }, { operator: '!matches', name: t('workflowengine', 'does not match') } - ] - // TODO: implement component + ], + component: RequestURL }, { class: 'OCA\\WorkflowEngine\\Check\\RequestTime', |