@nextcloud/vue
Version:
Nextcloud vue components
280 lines (279 loc) • 8.05 kB
JavaScript
import NcEllipsisedOption from "../Components/NcEllipsisedOption.mjs";
import { N as NcSelect } from "./NcSelect-DRRPiPZG.mjs";
import axios from "@nextcloud/axios";
import { generateRemoteUrl } from "@nextcloud/router";
import { r as register, h as t0, a as t } from "./_l10n-JYjUKekn.mjs";
import { n as normalizeComponent } from "./_plugin-vue2_normalizer-DU4iP6Vu.mjs";
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") {
const 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) => {
const json = xmlToJson(parseXml(xml));
const list = json["d:multistatus"]["d:response"];
const result = [];
for (const index in list) {
const tag = list[index]["d:propstat"];
if (tag["d:status"]["#text"] !== "HTTP/1.1 200 OK") {
continue;
}
result.push({
id: parseInt(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 = async function() {
if (window.NextcloudVueDocs) {
return Promise.resolve(xmlToTagList(window.NextcloudVueDocs.tags));
}
const result = await axios({
method: "PROPFIND",
url: generateRemoteUrl("dav") + "/systemtags/",
data: '<?xml version="1.0"?>\n <d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">\n <d:prop>\n <oc:id />\n <oc:display-name />\n <oc:user-visible />\n <oc:user-assignable />\n <oc:can-assign />\n </d:prop>\n </d:propfind>'
});
return xmlToTagList(result.data);
};
register(t0);
const _sfc_main = {
name: "NcSelectTags",
components: {
NcEllipsisedOption,
NcSelect
},
props: {
// Add NcSelect prop defaults and populate $props
...NcSelect.props,
/**
* Enable automatic fetching of tags
*
* If `false`, available tags must be passed using the `options` prop
*/
fetchTags: {
type: Boolean,
default: true
},
/**
* Callback to generate the label text
*
* @see https://vue-select.org/api/props.html#getoptionlabel
*/
getOptionLabel: {
type: Function,
default: (option) => {
const { displayName, userVisible, userAssignable } = option;
if (userVisible === false) {
return t("{tag} (invisible)", { tag: displayName });
}
if (userAssignable === false) {
return t("{tag} (restricted)", { tag: displayName });
}
return displayName;
}
},
/**
* Sets the maximum number of tags to display in the dropdown list
*
* Because of compatibility reasons only 5 tag entries are shown by
* default
*/
limit: {
type: Number,
default: 5
},
/**
* Allow selection of multiple options
*
* This prop automatically sets the internal `closeOnSelect` prop to
* its boolean opposite
*
* @see https://vue-select.org/api/props.html#multiple
*/
multiple: {
type: Boolean,
default: true
},
/**
* Callback to filter available options
*/
optionsFilter: {
type: Function,
default: null
},
/**
* Enable passing of `value` prop and emitted `input` events as-is
* i.e. for usage with `v-model`
*
* If `true`, custom internal `value` and `input` handling is disabled
*/
passthru: {
type: Boolean,
default: false
},
/**
* Placeholder text
*
* @see https://vue-select.org/api/props.html#placeholder
*/
placeholder: {
type: String,
default: t("Select a tag")
},
/**
* Currently selected value
*/
value: {
type: [Number, Array, Object],
default: null
},
/**
* Any available prop
*
* @see https://vue-select.org/api/props.html
*/
// Not an actual prop but needed to show in vue-styleguidist docs
// eslint-disable-next-line
" ": {}
},
emits: [
"input",
/**
* All events from https://vue-select.org/api/events.html
*/
// Not an actual event but needed to show in vue-styleguidist docs
" "
],
data() {
return {
search: "",
availableTags: []
};
},
computed: {
availableOptions() {
if (this.optionsFilter) {
return this.tags.filter(this.optionsFilter);
}
return this.tags;
},
localValue() {
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);
}
},
propsToForward() {
const {
// Props handled by this component
fetchTags,
optionsFilter,
passthru,
// Props to forward
...propsToForward
} = this.$props;
return propsToForward;
},
tags() {
if (!this.fetchTags) {
return this.options;
}
return this.availableTags;
}
},
async created() {
if (!this.fetchTags) {
return;
}
try {
const result = await searchTags();
this.availableTags = result;
} catch (error) {
console.error("Loading systemtags failed", error);
}
},
methods: {
handleInput(value) {
if (this.multiple) {
this.$emit("input", value.map((element) => element.id));
} else {
if (value === null) {
this.$emit("input", null);
} else {
this.$emit("input", value.id);
}
}
}
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _c("NcSelect", _vm._g(_vm._b({ attrs: { "options": _vm.availableOptions, "close-on-select": !_vm.multiple, "value": _vm.passthru ? _vm.value : _vm.localValue }, on: { "search": (searchString) => _vm.search = searchString }, scopedSlots: _vm._u([{ key: "option", fn: function(option) {
return [_c("NcEllipsisedOption", { attrs: { "name": _vm.getOptionLabel(option), "search": _vm.search } })];
} }, { key: "selected-option", fn: function(selectedOption) {
return [_c("NcEllipsisedOption", { attrs: { "name": _vm.getOptionLabel(selectedOption), "search": _vm.search } })];
} }, _vm._l(_vm.$scopedSlots, function(_, name) {
return { key: name, fn: function(data) {
return [_vm._t(name, null, null, data)];
} };
})], null, true) }, "NcSelect", _vm.propsToForward, false), {
..._vm.$listeners,
input: _vm.passthru ? _vm.$listeners.input : _vm.handleInput
}));
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns,
false,
null,
null
);
const NcSelectTags = __component__.exports;
export {
NcSelectTags as N
};