diff --git a/package-lock.json b/package-lock.json index 6484568b32..e912f30b3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8247,6 +8247,21 @@ "axios": "^0.19.0" } }, + "nextcloud-router": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/nextcloud-router/-/nextcloud-router-0.0.9.tgz", + "integrity": "sha512-w0i4xqFwJJuXNWFf9AB9huCWW5XmwdJHSHa7oXlOLTAvP9WxwU3KCm/mcKy8Eb0cT0ElRPg72HLUxl7oyEWoBQ==", + "requires": { + "core-js": "^3.1.4" + }, + "dependencies": { + "core-js": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", + "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" + } + } + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", diff --git a/package.json b/package.json index fd43829a69..0c007bbc7c 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "hammerjs": "^2.0.8", "md5": "^2.2.1", "nextcloud-axios": "^0.2.0", + "nextcloud-router": "0.0.9", "v-tooltip": "^2.0.0-rc.33", "vue": "^2.6.7", "vue-click-outside": "^1.0.7", diff --git a/src/components/MultiselectTag/MultiselectTag.vue b/src/components/MultiselectTag/MultiselectTag.vue new file mode 100644 index 0000000000..3f0901270c --- /dev/null +++ b/src/components/MultiselectTag/MultiselectTag.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/src/components/MultiselectTag/api.js b/src/components/MultiselectTag/api.js new file mode 100644 index 0000000000..f371a4b71d --- /dev/null +++ b/src/components/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: ` + + + + + + + + + ` + }).then((response) => { + return xmlToTagList(response.data) + }) +} + +export { + searchTags +} diff --git a/src/components/MultiselectTag/index.js b/src/components/MultiselectTag/index.js new file mode 100644 index 0000000000..69b7e277e7 --- /dev/null +++ b/src/components/MultiselectTag/index.js @@ -0,0 +1,4 @@ +import MultiselectTag from './MultiselectTag' + +export default MultiselectTag +export { MultiselectTag } diff --git a/src/components/index.js b/src/components/index.js index 6b11cc7230..181cf3aaaf 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -45,6 +45,7 @@ import Content from './Content' import DatetimePicker from './DatetimePicker' import Modal from './Modal' import Multiselect from './Multiselect' +import MultiselectTag from './MultiselectTag' import PopoverMenu from './PopoverMenu' export { @@ -73,5 +74,6 @@ export { DatetimePicker, Modal, Multiselect, + MultiselectTag, PopoverMenu }