Utilizador:LBelo (WMB)/gpgp.js: diferenças entre revisões
Aspeto
Conteúdo apagado Conteúdo adicionado
Sem resumo de edição |
Sem resumo de edição Etiqueta: Revertida |
||
Linha 29: | Linha 29: | ||
return { |
return { |
||
showDialog: false, |
showDialog: false, |
||
showFillButton: |
showFillButton: false, |
||
disableCreateButton: false, |
disableCreateButton: false, |
||
currentTab: 'Sobre', |
currentTab: 'Sobre', |
Revisão das 21h44min de 1 de novembro de 2024
/**
* Esse arquivo JavaScript é parte do Gerador de Perfis de Grupos de Pesquisa (GPGP) (https://pt.wikiversity.org/wiki/Gerador_de_Perfis_de_Grupos_de_Pesquisa).
*
* Autor:
* @author Wiki Movimento Brasil (WMB) (https://meta.wikimedia.org/wiki/Wiki_Movement_Brazil_User_Group)
*
* Contribuidores:
* @contributors Lucas Belo (https://en.wikiversity.org/wiki/User:LBelo_(WMB))
* @contributors Éder Porto (https://en.wikiversity.org/wiki/User:EPorto_(WMB))
*
* Os recursos ultilizados são:
* MediaWiki Frontend API (https://doc.wikimedia.org/mediawiki-core/master/js/index.html)
* Codex - Wikimedia Design System (https://doc.wikimedia.org/codex/latest/)
*/
/**
* Section for the Vue application and insertion of Codex components
*/
const elementGpgp = document.getElementById('gpgp-modal');
mw.loader.using('@wikimedia/codex').then(function (require) {
const Vue = require('vue');
const Codex = require('@wikimedia/codex');
const mountPoint = elementGpgp.appendChild(document.createElement('div'));
Vue.createMwApp({
data: function () {
return {
showDialog: false,
showFillButton: false,
disableCreateButton: false,
currentTab: 'Sobre',
tabsData: [{
name: 'Sobre',
label: 'Sobre'
}, {
name: 'Pesquisadores',
label: 'Pesquisadores'
}, {
name: 'Área',
label: 'Área'
}, {
name: 'Identidade visual',
label: 'Identidade visual'
}, {
name: 'Contato',
label: 'Contato'
}, {
name: 'Submeter',
label: 'Submeter'
}],
menuItemsSiteLanguage: [
{ label: 'Português brasileiro', value: 'Q750553' },
{ label: 'Português', value: 'Q5146' },
{ label: 'Inglês', value: 'Q1860'},
{ label: 'Espanhol', value: 'Q1321'},
{ label: 'Francês', value: 'Q150'},
{ label: 'Alemão', value: 'Q188'},
{ label: 'Jamponês', value: 'Q5287'}
],
selectionSiteLanguage: 'Q750553',
Wikidata: {
message: '',
type: 'notice',
url: '',
label: '',
qid: ''
},
Wikiversity: {
message: '',
type: 'notice',
url: '',
page: ''
}
};
},
template: `
<cdx-button action="progressive" weight="primary">Criar Grupo de Pesquisa</cdx-button>
<cdx-dialog v-model:open="showDialog" title="Criar Grupo de Pesquisa" close-button-label="Close"
:default-action="defaultAction" @default="open = false">
<cdx-tabs v-model:active="currentTab" :framed="framed">
<cdx-tab v-for="( tab, index ) in tabsData" :key="index" :name="tab.name" :label="tab.label"
:disabled="tab.disabled">
<template v-if="tab.name === 'Sobre'">
<br>
<cdx-button action="progressive" weight="primary" @click="fillFormButton" v-if="showFillButton">Preencher Formulário</cdx-button>
<cdx-field :status="statusName" :messages="messagesName">
<template #label>Nome</template>
<cdx-text-input v-model="inputName" @blur="warningName" aria-label="TextInput default demo"></cdx-text-input>
<template #help-text>Nome do grupo de pesquisa</template>
</cdx-field>
<cdx-field :status="statusDescription" :messages="messagesDescription">
<template #label>Descrição</template>
<cdx-text-area v-model="inputDescription" aria-label="TextArea default demo"></cdx-text-area>
</cdx-field>
<cdx-field optionalFlag="(opcional)">
<template #label>Sigla</template>
<template #help-text>Siglas ou abreviações do nome do grupo de pesquisa</template>
<cdx-chip-input v-model:input-chips="aliasChips" remove-button-label="Remove"></cdx-chip-input>
</cdx-field>
<cdx-field>
<template #label>Data de início das atividades</template>
<cdx-text-input v-model="inputDate" aria-label="TextInput date demo"
input-type="date"></cdx-text-input>
</cdx-field>
<cdx-field>
<template #label>Países de atuação</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionCountry" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata"
@input="onInput" @load-more="onLoadMore" @update:selected="insertSelectedInChipInput('selectionCountry')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-chip-input v-model:input-chips="countriesChips" remove-button-label="Remove"></cdx-chip-input>
<p>Se não localizar um item no Wikidata, insira-o no campo acima</p>
<cdx-field>
<template #label>Localização</template>
<template #help-text>Localização do grupo de pesquisa</template>
<cdx-lookup v-model:selected="selectionLocal" :menu-items="menuItems" :menu-config="menuConfig"
placeholder="Pesquise no Wikidata" @input="onInput" @load-more="onLoadMore">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #label>Instituições</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionInstitutions" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata"
@input="onInput" @load-more="onLoadMore" @update:selected="insertSelectedInChipInput('selectionInstitutions')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-chip-input v-model:input-chips="institutionsChips" remove-button-label="Remove"></cdx-chip-input>
<p>Se não localizar um item no Wikidata, insira-o no campo acima</p>
<br>
</template>
<template v-if="tab.name === 'Pesquisadores'">
<br>
<cdx-field>
<template #label>Pesquisador(es) principal(is)</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionPrincipalResearcher" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata" @input="onInput" @load-more="onLoadMore"
@update:selected="insertSelectedInChipInput('selectionPrincipalResearcher')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #help-text>
Se não localizar um item no Wikidata, insira-o no campo acima
</template>
<cdx-chip-input v-model:input-chips="principalResearcherChips" remove-button-label="Remove">
</cdx-chip-input>
</cdx-field>
<br>
<h5>Integrantes do grupo de pesquisa</h5>
<cdx-field>
<template #label>Pesquisadores associados</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionResearchers" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata" @input="onInput" @load-more="onLoadMore"
@update:selected="insertSelectedInChipInput('selectionResearchers')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #help-text>
Se não localizar um item no Wikidata, insira-o no campo acima
</template>
<cdx-chip-input v-model:input-chips="researchersChips" remove-button-label="Remove">
</cdx-chip-input>
</cdx-field>
<cdx-field>
<template #label>Juniores</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionJuniors" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata" @input="onInput" @load-more="onLoadMore"
@update:selected="insertSelectedInChipInput('selectionJuniors')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #help-text>
Se não localizar um item no Wikidata, insira-o no campo acima
</template>
<cdx-chip-input v-model:input-chips="juniorsChips" remove-button-label="Remove">
</cdx-chip-input>
</cdx-field>
<br>
</template>
<template v-if="tab.name === 'Área'">
<br>
<cdx-field>
<template #label>Área do conhecimento</template>
<template #description>Tema de pesquisa ou campo de trabalho</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionTheme" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata"
@input="onInput" @load-more="onLoadMore" @update:selected="insertSelectedInChipInput('selectionTheme')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #help-text>
Se não localizar um item no Wikidata, insira-o no campo acima
</template>
<cdx-chip-input v-model:input-chips="themeChips" remove-button-label="Remove">
</cdx-chip-input>
</cdx-field>
<cdx-field>
<template #label>Palavras-chave</template>
<template #help-text>
Ao selecionar um item ele será automáticamente inserido no campo abaixo
</template>
<cdx-lookup v-model:selected="selectionKeyWord" :menu-items="menuItems" :menu-config="menuConfig"
:clearable="true" placeholder="Pesquise no Wikidata"
@input="onInput" @load-more="onLoadMore" @update:selected="insertSelectedInChipInput('selectionKeyWord')">
<template #no-results>Nenhum resultado encontrado.</template>
</cdx-lookup>
</cdx-field>
<cdx-field>
<template #help-text>
Se não localizar um item no Wikidata, insira-o no campo acima
</template>
<cdx-chip-input v-model:input-chips="keyWordChips" remove-button-label="Remove">
</cdx-chip-input>
</cdx-field>
<br>
</template>
<template v-if="tab.name === 'Identidade visual'">
<br>
<cdx-field optionalFlag="(opcional)">
<template #label>Cor</template>
<template #help-text>Cor para o layout da página</template>
<input id="colorPicker" type="color" value="#3366cc">
</cdx-field>
<cdx-field optionalFlag="(opcional)">
<template #label>Logo</template>
<template #help-text>Logo ou imagem do grupo de pesquisa no Wikimedia Commons</template>
<cdx-text-input v-model="inputLogo" placeholder="Nome da imagem.jpg" aria-label="TextInput default demo"></cdx-text-input>
</cdx-field>
<br>
</template>
<template v-if="tab.name === 'Contato'">
<br>
<cdx-field optionalFlag="(opcional)">
<template #label>E-mail</template>
<cdx-text-input v-model="inputEmail" aria-label="TextInput default demo"></cdx-text-input>
</cdx-field>
<cdx-field optionalFlag="(opcional)">
<template #label>Site</template>
<cdx-text-input v-model="inputSite" aria-label="TextInput default demo"></cdx-text-input>
</cdx-field>
<cdx-field optionalFlag="(opcional)">
<template #label>Idioma do site</template>
<cdx-select v-model:selected="selectionSiteLanguage" :menu-items="menuItemsSiteLanguage"></cdx-select>
</cdx-field>
<br>
</template>
<template v-if="tab.name === 'Submeter'">
<br>
<cdx-message :type="Wikiversity.type" v-if="Wikiversity.message">
{{ Wikiversity.message }}
<p v-if="Wikiversity.url"><a :href="Wikiversity.url">{{ Wikiversity.page }}</a></p>
</cdx-message>
<cdx-message :type="Wikidata.type" v-if="Wikidata.message">
{{ Wikidata.message }}
<p v-if="Wikidata.url"><a :href="Wikidata.url">{{ Wikidata.label }} ({{ Wikidata.qid }})</a></p>
</cdx-message>
<center>
<br>
<cdx-button action="progressive" weight="primary" @click="createPages" :disabled="disableCreateButton">Criar Grupo de Pesquisa</cdx-button>
</center>
</template>
</cdx-tab>
</cdx-tabs>
</cdx-dialog>
`,
methods: {
openDialog() {
this.showDialog = true;
},
createPages() {
function wikiversity(payload) {
createWikiversityPages(payload) // see /addin-gpgp.js
.then((result) => {
payload.Wikiversity.message = 'Foi criada a página do grupo de pesquisa na Wikiversidade:';
payload.Wikiversity.type = 'success';
payload.Wikiversity.url = 'https://pt.wikiversity.org/wiki/' + payload.inputName;
payload.Wikiversity.page = payload.inputName;
wikidata(payload);
})
.catch((error) => {
payload.Wikiversity.message = 'Ocorreu um erro na criação da página do grupo de pesquisa na Wikiversidade.';
payload.Wikiversity.type = 'error';
console.log({ type: 'error', message: error });
});
}
function wikidata(payload) {
createWikidataItem(payload) // see /addin-gpgp.js
.then((result) => {
let qid = result.entity.id;
let label = result.entity.labels["pt-br"].value;
payload.Wikidata.message = 'Foi criado o item do grupo de pesquisa no Wikidata:';
payload.Wikidata.type = 'success';
payload.Wikidata.url = 'https://www.wikidata.org/wiki/' + qid;
payload.Wikidata.label = label;
payload.Wikidata.qid = qid;
})
.catch((error) => {
payload.Wikidata.message = 'Ocorreu um erro na criação do item no Wikidata.';
payload.Wikidata.type = 'error';
console.log({ type: 'error', message: error });
});
}
let checkName = false;
let checkDescription = false;
let inputName = this.inputName;
if(inputName == '' || inputName === undefined){
this.statusName = "error";
this.messagesName = { error: 'Este campo é obrigatório.' };
this.currentTab = 'Sobre';
} else {
this.statusName = "default";
checkName = true;
}
let inputDescription = this.inputDescription;
if(inputDescription == '' || inputDescription === undefined){
this.statusDescription = "error";
this.messagesDescription = { error: 'Este campo é obrigatório.' };
this.currentTab = 'Sobre';
} else {
this.statusDescription = "default";
checkDescription = true;
}
if(inputName.trim().toLowerCase() == inputDescription.trim().toLowerCase()) {
this.statusDescription = "error";
this.messagesDescription = { error: 'A descrição não pode ser igual ao nome do grupo de pesquisa.' };
this.currentTab = 'Sobre';
checkDescription = false;
}
if(checkName == true && checkDescription == true) {
this.disableCreateButton = true;
this.Wikiversity.message = 'Aguarde a criação da página do grupo de pesquisa na Wikiversidade...';
this.Wikidata.message = 'Aguarde a criação do item do grupo de pesquisa no Wikidata...';
wikiversity(this);
}
},
fillFormButton() {
fillForm(this); // see user:LBelo (WMB)/fillForm.js
}
},
setup() {
// selection objects
const selectionLocal = ref(null);
const selectionTheme = ref(null);
const selectionKeyWord = ref(null);
const selectionCountry = ref(null);
const selectionJuniors = ref(null);
const selectionResearchers = ref(null);
const selectionInstitutions = ref(null);
const selectionPrincipalResearcher = ref(null);
// chips objects
const themeChips = ref([]);
const aliasChips = ref([]);
const keyWordChips = ref([]);
const juniorsChips = ref([]);
const countriesChips = ref([]);
const researchersChips = ref([]);
const institutionsChips = ref([]);
const principalResearcherChips = ref([]);
// Lookup Wikidata
const currentSearchTerm = ref('');
const menuItems = ref([]);
const menuConfig = {
visibleItemLimit: 6,
boldLabel: true
};
const messagesName = ref(null);
const statusName = ref('default');
function warningName(){
statusName.value = 'warning';
messagesName.value = {warning: "Revise o nome do grupo de pesquisa e verifique se há erros ou caracteres indevidos. Esse nome será usado em várias páginas, o que dificultará alterações futuras."};
return;
}
function ref(value) {
return Vue.ref(value);
}
function insertSelectedInChipInput(field) {
var fields = {
'selectionTheme': {'selection': selectionTheme, 'chips': themeChips},
'selectionKeyWord': {'selection': selectionKeyWord, 'chips': keyWordChips},
'selectionCountry': {'selection': selectionCountry, 'chips': countriesChips},
'selectionJuniors': {'selection': selectionJuniors, 'chips': juniorsChips},
'selectionResearchers': {'selection': selectionResearchers, 'chips': researchersChips},
'selectionInstitutions': {'selection': selectionInstitutions, 'chips': institutionsChips},
'selectionPrincipalResearcher': {'selection': selectionPrincipalResearcher, 'chips': principalResearcherChips},
};
var selection = fields[field].selection;
var chips = fields[field].chips;
// selected value has a QID
if (selection.value !== null) {
// iterates over suggested items to find the selected item
for (let item of menuItems.value) {
if (item.value == selection.value) {
// manipulates chipInput values
var payload = item.label + " (" + item.value + ")";
var payloadInChips = false;
for (let chip of chips.value) {
if (payload == chip.value) {
payloadInChips = true;
break;
}
}
if (payloadInChips == false) {
chips.value.push({ value: payload });
return;
}
}
}
}
}
/**
* Get search results.
*
* @param {string} searchTerm
* @param {number} offset Optional result offset
*
* @return {Promise}
*/
function fetchResults(searchTerm, offset) {
const params = new URLSearchParams({
origin: '*',
action: 'wbsearchentities',
format: 'json',
limit: '10',
props: 'url',
language: 'pt-br',
uselang: 'pt-br',
search: searchTerm
});
if (offset) {
params.set('continue', String(offset));
}
return fetch(`https://www.wikidata.org/w/api.php?${params.toString()}`)
.then((response) => response.json());
}
/**
* Handle lookup input.
*
* TODO: this should be debounced.
*
* @param {string} value
*/
function onInput(value) {
// Internally track the current search term.
currentSearchTerm.value = value;
// Do nothing if we have no input.
if (!value) {
menuItems.value = [];
return;
}
fetchResults(value)
.then((data) => {
// Make sure this data is still relevant first.
if (currentSearchTerm.value !== value) {
return;
}
// Reset the menu items if there are no results.
if (!data.search || data.search.length === 0) {
menuItems.value = [];
return;
}
// Build an array of menu items.
const results = data.search.map((result) => {
return {
label: result.label,
value: result.id,
description: result.description
};
});
// Update menuItems.
menuItems.value = results;
})
.catch(() => {
// On error, set results to empty.
menuItems.value = [];
});
}
function deduplicateResults(results) {
const seen = new Set(menuItems.value.map((result) => result.value));
return results.filter((result) => !seen.has(result.value));
}
function onLoadMore() {
if (!currentSearchTerm.value) {
return;
}
fetchResults(currentSearchTerm.value, menuItems.value.length)
.then((data) => {
if (!data.search || data.search.length === 0) {
return;
}
const results = data.search.map((result) => {
return {
label: result.label,
value: result.id,
description: result.description
};
});
// Update menuItems.
const deduplicatedResults = deduplicateResults(results);
menuItems.value.push(...deduplicatedResults);
});
}
return {
// functions
onInput,
onLoadMore,
warningName,
insertSelectedInChipInput,
// Messages
messagesName,
statusName,
// lookup objects
menuItems,
menuConfig,
// chips objects
themeChips,
aliasChips,
keyWordChips,
juniorsChips,
countriesChips,
researchersChips,
institutionsChips,
principalResearcherChips,
// selection objects
selectionLocal,
selectionTheme,
selectionKeyWord,
selectionCountry,
selectionJuniors,
selectionResearchers,
selectionInstitutions,
selectionPrincipalResearcher,
};
},
mounted() {
elementGpgp.addEventListener('click', this.openDialog);
},
unMounted() {
elementGpgp.removeEventListener(this.openDialog);
}
})
.component('cdx-tab', Codex.CdxTab)
.component('cdx-tabs', Codex.CdxTabs)
.component('cdx-field', Codex.CdxField)
.component('cdx-lookup', Codex.CdxLookup)
.component('cdx-button', Codex.CdxButton)
.component('cdx-dialog', Codex.CdxDialog)
.component('cdx-select', Codex.CdxSelect)
.component('cdx-message', Codex.CdxMessage)
.component('cdx-text-area', Codex.CdxTextArea)
.component('cdx-accordion', Codex.CdxAccordion)
.component('cdx-text-input', Codex.CdxTextInput)
.component('cdx-chip-input', Codex.CdxChipInput)
.mount(mountPoint);
});