Create vue component for WikiData input. #783.
This commit is contained in:
parent
4724cddeae
commit
0763a787fa
|
@ -0,0 +1,4 @@
|
|||
import TainacanWikiData from "./tainacan-wiki-data-component.vue";
|
||||
|
||||
window.tainacan_extra_components = typeof window.tainacan_extra_components != "undefined" ? window.tainacan_extra_components : {};
|
||||
window.tainacan_extra_components["tainacan-wiki-data"] = TainacanWikiData;
|
|
@ -0,0 +1,370 @@
|
|||
<template>
|
||||
<div :class="{ 'is-flex is-flex-wrap-wrap': itemMetadatum.metadatum.multiple != 'yes' || maxtags != undefined }">
|
||||
<b-tabs
|
||||
v-if="wikidataPropertyId"
|
||||
size="is-small"
|
||||
animated
|
||||
v-model="activeTab">
|
||||
<b-tab-item :label="$i18n.get('label_insert_items')">
|
||||
<b-taginput
|
||||
expanded
|
||||
:disabled="disabled"
|
||||
:id="wikiDataInputId"
|
||||
size="is-small"
|
||||
icon="magnify"
|
||||
:value="selected"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@add="onAdd"
|
||||
@remove="onRemove"
|
||||
:data="options"
|
||||
:maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : '1')"
|
||||
autocomplete
|
||||
:remove-on-keys="[]"
|
||||
:dropdown-position="isLastMetadatum ? 'top' :'auto'"
|
||||
attached
|
||||
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : $i18n.get('instruction_type_existing_item')"
|
||||
:loading="isLoading"
|
||||
:aria-close-label="$i18n.get('remove_value')"
|
||||
:class="{'has-selected': selected != undefined && selected != []}"
|
||||
field="label"
|
||||
@typing="search"
|
||||
check-infinite-scroll
|
||||
@infinite-scroll="searchMore"
|
||||
:has-counter="false"
|
||||
@focus="onMobileSpecialFocus">
|
||||
<template slot-scope="props">
|
||||
<div class="media">
|
||||
<div
|
||||
class="media-content"
|
||||
style="display: block;">
|
||||
{{ props.option.label }}
|
||||
<br v-if="props.option.description">
|
||||
<small v-if="props.option.description">{{ props.option.description }}</small>
|
||||
</div>
|
||||
<div class="has-text-gray media-right">
|
||||
({{ props.option.value }})
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
v-else
|
||||
class="tainacan-wiki-data-group">
|
||||
<div v-html="props.option.valuesAsHtml" />
|
||||
</div> -->
|
||||
</template>
|
||||
<template
|
||||
v-if="!isLoading"
|
||||
slot="empty">
|
||||
{{ $i18n.get('info_no_item_found') }}
|
||||
</template>
|
||||
<!-- <template
|
||||
v-if="currentUserCanEditItems && (!$adminOptions.itemEditionMode || $adminOptions.allowItemEditionModalInsideModal)"
|
||||
slot="footer">
|
||||
<a @click="editItemModalOpen = true">
|
||||
{{ $i18n.get('label_create_new_item') + ' "' + searchQuery + '"' }}
|
||||
</a>
|
||||
</template> -->
|
||||
</b-taginput>
|
||||
</b-tab-item>
|
||||
<b-tab-item
|
||||
v-if="itemMetadatum && itemMetadatum.value !== undefined"
|
||||
style="min-height: 56px;"
|
||||
:label="( itemMetadatum.value.length == 1 || itemMetadatum.metadatum.multiple != 'yes' ) ? $i18n.get('label_selected_item') : ( $i18n.get('label_selected_items') + ' (' + itemMetadatum.value.length + ')' )">
|
||||
<div class="tainacan-wiki-data-results-container">
|
||||
<div
|
||||
v-if="itemMetadatum.value && itemMetadatum.value.length"
|
||||
class="tainacan-wiki-data-group">
|
||||
<div
|
||||
v-for="(itemValue, index) of selected"
|
||||
:key="index"
|
||||
style="position: relative;">
|
||||
<!-- <div v-html="itemValue.valuesAsHtml" /> -->
|
||||
<a
|
||||
@click="removeFromSelected(itemValue.value)"
|
||||
class="wiki-data-value-button--remove">
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-close" />
|
||||
</span>
|
||||
</a>
|
||||
<span
|
||||
v-if="index < selected.length - 1"
|
||||
class="multivalue-separator"> | </span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p
|
||||
class="has-text-gray"
|
||||
style="font-size: 0.875em;">
|
||||
{{ $i18n.get('info_no_item_found') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</b-tab-item>
|
||||
</b-tabs>
|
||||
<section
|
||||
v-else
|
||||
class="field is-grouped-centered section">
|
||||
<div class="content has-text-gray has-text-centered">
|
||||
<p>
|
||||
<span class="icon is-large">
|
||||
<i class="tainacan-icon tainacan-icon-36px tainacan-icon-processes tainacan-icon-rotate-90"/>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import qs from 'qs';
|
||||
|
||||
export default {
|
||||
name: "TainacanWikiData",
|
||||
props: {
|
||||
itemMetadatum: Object,
|
||||
value: [String, Number, Array],
|
||||
maxtags: undefined,
|
||||
disabled: false,
|
||||
allowNew: true,
|
||||
isLastMetadatum: false,
|
||||
isMobileScreen: false
|
||||
},
|
||||
computed: {
|
||||
wikidataPropertyId() {
|
||||
return this.itemMetadatum.metadatum &&
|
||||
this.itemMetadatum.metadatum.exposer_mapping &&
|
||||
this.itemMetadatum.metadatum.exposer_mapping['wiki-data'] &&
|
||||
this.itemMetadatum.metadatum.exposer_mapping['wiki-data']['wikidataPropertyId'] ? this.itemMetadatum.metadatum.exposer_mapping['wiki-data']['wikidataPropertyId'] : false;
|
||||
},
|
||||
wikidataEndpoint() {
|
||||
return 'https://www.wikidata.org/w/api.php?origin=*&action=wbsearchentities&format=json&language=pt-br&uselang=pt-br&props=claims&claim=' + this.wikidataPropertyId + '&';
|
||||
},
|
||||
maxMultipleValues() {
|
||||
return (
|
||||
this.itemMetadatum &&
|
||||
this.itemMetadatum.metadatum &&
|
||||
this.itemMetadatum.metadatum.cardinality &&
|
||||
!isNaN(this.itemMetadatum.metadatum.cardinality) &&
|
||||
this.itemMetadatum.metadatum.cardinality > 1
|
||||
) ? this.itemMetadatum.metadatum.cardinality : undefined;
|
||||
},
|
||||
wikiDataInputId() {
|
||||
if (this.itemMetadatum && this.itemMetadatum.metadatum)
|
||||
return 'tainacan-item-metadatum_id-' + this.itemMetadatum.metadatum.id + (this.itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + this.itemMetadatum.parent_meta_id) : '');
|
||||
else
|
||||
return '';
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selected:[],
|
||||
options: [],
|
||||
isLoading: false,
|
||||
searchQuery: '',
|
||||
totalItems: 0,
|
||||
page: 1,
|
||||
activeTab: 0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.wikiDataPropertyId && this.itemMetadatum.value && (Array.isArray( this.itemMetadatum.value ) ? this.itemMetadatum.value.length > 0 : true )) {
|
||||
let query = [];
|
||||
|
||||
query['postin'] = Array.isArray( this.itemMetadatum.value ) ? this.itemMetadatum.value : [ this.itemMetadatum.value ];
|
||||
query['nopaging'] = 1;
|
||||
query['order'] = 'asc';
|
||||
|
||||
this.fetchFromWikidata(this.wikidataEndpoint + + qs.stringify(query) )
|
||||
.then( res => {
|
||||
if (res.search) {
|
||||
for (let item of res.search) {
|
||||
this.selected.push({
|
||||
label: item.label,
|
||||
value: item.id,
|
||||
description: item.description
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
this.$console.log(error);
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchFromWikidata(url) {
|
||||
|
||||
try {
|
||||
const requestHeaders = new Headers({
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
const request = new Request(url, requestHeaders);
|
||||
const res = await fetch(request)
|
||||
const data = await res.json();
|
||||
return data;
|
||||
} catch(e) {
|
||||
console.log(e, e.response)
|
||||
return [];
|
||||
}
|
||||
},
|
||||
onInput(newSelected) {
|
||||
// First we reset the input
|
||||
this.search('');
|
||||
|
||||
this.selected = newSelected;
|
||||
this.$emit('input', newSelected.map((item) => item.value));
|
||||
},
|
||||
onBlur() {
|
||||
this.$emit("blur");
|
||||
},
|
||||
search: _.debounce(function(query) {
|
||||
|
||||
// String update
|
||||
if (query != this.searchQuery) {
|
||||
this.searchQuery = query;
|
||||
this.options = [];
|
||||
this.page = 1;
|
||||
}
|
||||
|
||||
// String cleared
|
||||
if (!query.length) {
|
||||
this.searchQuery = query;
|
||||
this.options = [];
|
||||
this.page = 1;
|
||||
}
|
||||
|
||||
// No need to load more
|
||||
if (this.page > 1 && this.options.length > this.totalItems*12)
|
||||
return;
|
||||
|
||||
// There is already one value set and is not multiple
|
||||
if (this.selected.length > 0 && this.itemMetadatum.metadatum.multiple === 'no')
|
||||
return;
|
||||
|
||||
if (this.searchQuery !== '') {
|
||||
this.isLoading = true;
|
||||
|
||||
this.fetchFromWikidata(this.wikidataEndpoint + this.getQueryString(this.searchQuery))
|
||||
.then( res => {
|
||||
if (res.search) {
|
||||
for (let item of res.search) {
|
||||
this.options.push({
|
||||
label: item.label,
|
||||
value: item.id,
|
||||
description: item.description,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (res['search-continue'])
|
||||
this.totalItems = Number(res['search-continue']) * 6;
|
||||
|
||||
this.page++;
|
||||
|
||||
this.isLoading = false;
|
||||
})
|
||||
.catch(error => {
|
||||
this.isLoading = false;
|
||||
this.$console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
}, 500),
|
||||
searchMore: _.debounce(function () {
|
||||
this.search(this.searchQuery)
|
||||
}, 250),
|
||||
getQueryString( search ) {
|
||||
let query = [];
|
||||
query['search'] = search;
|
||||
query['perpage'] = 12;
|
||||
query['paged'] = this.page;
|
||||
query['order'] = 'asc';
|
||||
|
||||
return qs.stringify(query);
|
||||
},
|
||||
removeFromSelected(itemId) {
|
||||
const indexOfRemovedItem = this.selected.findIndex(itemValue => itemValue.value == itemId);
|
||||
|
||||
if (indexOfRemovedItem >= 0) {
|
||||
this.selected.splice(indexOfRemovedItem, 1);
|
||||
this.onInput(this.selected);
|
||||
}
|
||||
},
|
||||
onMobileSpecialFocus() {
|
||||
this.$emit('mobileSpecialFocus');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.is-flex {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.add-link {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
.b-tabs {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
/deep/ .b-tabs .tab-content {
|
||||
padding: 0.5em 0px !important;
|
||||
}
|
||||
/deep/ .tabs {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
/deep/ .tabs ul {
|
||||
padding: 0;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container {
|
||||
border: 1px solid var(--tainacan-gray1);
|
||||
background-color: var(--tainacan-white);
|
||||
margin-top: calc(-1 * (0.5em + 1px));
|
||||
margin-bottom: calc(-1 * (0.5em + 1px));
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
padding: 12px;
|
||||
max-height: 40vh;
|
||||
transition: height 0.5s ease, min-height 0.5s ease;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group .tainacan-wiki-data-metadatum .tainacan-metadatum .label {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group .tainacan-wiki-data-metadatum a {
|
||||
pointer-events: auto;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group .tainacan-wiki-data-metadatum .tainacan-wiki-data-metadatum-header {
|
||||
padding-right: 64px;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group .tainacan-wiki-data-metadatum .tainacan-wiki-data-metadatum-header .label{
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/deep/ .tainacan-wiki-data-results-container .tainacan-wiki-data-group .tainacan-wiki-data-metadatum >div>.multivalue-separator {
|
||||
display: block;
|
||||
max-height: 1px;
|
||||
width: calc(100% - 40px);
|
||||
background: var(--tainacan-gray2);
|
||||
content: none;
|
||||
color: transparent;
|
||||
margin: 0.5em 0 0.5em 40px;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-group {
|
||||
width: 100%;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-group .tainacan-wiki-data-metadatum .label {
|
||||
font-size: 1em;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-group .tainacan-wiki-data-metadatum a {
|
||||
pointer-events: none;
|
||||
}
|
||||
/deep/ .tainacan-wiki-data-group .tainacan-wiki-data-metadatum p {
|
||||
font-size: 0.875em;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -11,6 +11,8 @@ module.exports = {
|
|||
tainacan_blocks_category_icon: './src/views/gutenberg-blocks/js/tainacan-blocks-category-icon.js',
|
||||
tainacan_blocks_query_variations: './src/views/gutenberg-blocks/js/tainacan-blocks-query-variations.js',
|
||||
|
||||
tainacan_wikidata_component: './src/classes/mappers/tainacan-wiki-data-component.js',
|
||||
|
||||
block_terms_list: './src/views/gutenberg-blocks/blocks/terms-list/index.js',
|
||||
block_items_list: './src/views/gutenberg-blocks/blocks/items-list/index.js',
|
||||
block_dynamic_items_list: './src/views/gutenberg-blocks/blocks/dynamic-items-list/index.js',
|
||||
|
|
Loading…
Reference in New Issue