Utilizador:Lucas.Belo/codex-test.js

Nota: Depois de publicar, poderá ter de contornar a cache do seu navegador para ver as alterações.

  • Firefox / Safari: Pressione Shift enquanto clica Recarregar, ou pressione Ctrl-F5 ou Ctrl-R (⌘-R no Mac)
  • Google Chrome: Pressione Ctrl-Shift-R (⌘-Shift-R no Mac)
  • Edge: Pressione Ctrl enquanto clica Recarregar, ou pressione Ctrl-F5.
function addStyleSheet(pageTitle, sucCallback) {
	var cssLink = $("<link>");
	$("head").append(cssLink);
	cssLink.attr({
		rel:  "stylesheet",
		type: "text/css",
		href: "https://pt.wikiversity.org/w/index.php?action=raw&ctype=text/css&title=" + pageTitle
	});
	console.log('loading CSS file ' + pageTitle);
	if (typeof sucCallback !== 'undefined') {
		checkForStyleSheet(pageTitle, sucCallback);
	}
}
// import CSS while not in global namespace
addStyleSheet('Template:Codex-test/styles.css');

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,
			};
		},
		template: `
<cdx-button action="progressive" weight="primary">Criar Grupo de Pesquisa</cdx-button>

<cdx-dialog v-model:open="showDialog" title="Grupo de Pesquisa" close-button-label="Close"
	:default-action="defaultAction" @default="open = false">
	
	<cdx-field>
		<template #label>Intituições</template>
		<template #help-text>
			Ao selecionar um item ele será automáticamente inserido no campo abaixo
		</template>
		<cdx-lookup v-model:selected="selection" :menu-items="menuItems" :menu-config="menuConfig"
			:clearable="true" placeholder="Pesquise no Wikidata"
			@input="onInput" @load-more="onLoadMore" @update:selected="temp">
			<template #no-results>Nenhum resultado encontrado.</template>
		</cdx-lookup>
	</cdx-field>
	
	<div id="chip-container"></div>

	
</cdx-dialog>
		`,
		methods: {
			openDialog() {
				this.showDialog = true;
			}
		},
		setup() {
			const selection = ref(null);
			const menuItems = ref([]);
			const currentSearchTerm = ref('');
			const exampleChips = ref([]);
			const lst = [];
			const menuConfig = {
				visibleItemLimit: 6
			};

			function ref(value) {
				return Vue.ref(value);
			}
			
			function temp() {
				if (selection.value !== null) {
					lst.push(selection.value);
					const chipContainer = document.getElementById('chip-container');
					
					function renderChips() {
				        chipContainer.innerHTML = '';
				        lst.forEach((word, index) => {
				            const chip = document.createElement('div');
				            chip.className = 'chip';
				            chip.innerHTML = `${word} <span class="closebtn" onclick="removeChip(${index})">x</span>`;
				            chipContainer.appendChild(chip);
				        });
				    }
				    
					window.removeChip = function(index) {
				        lst.splice(index, 1);
				        renderChips();
				    };
					    renderChips();
				};
			};
			
			function insertSelectedInChipInput() {
				// 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;
							var chips = exampleChips.value;
							for (let chip of chips) {
								if (payload == chip.value) {
									payloadInChips = true;
									break;
								}
							}
							if (payloadInChips == false) {
								chips.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: 'en',
					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 {
				selection,
				menuItems,
				menuConfig,
				onInput,
				onLoadMore,
				exampleChips,
				insertSelectedInChipInput,
				temp
			};
		},
		mounted() {
			elementGpgp.addEventListener('click', this.openDialog);
		},
		unMounted() {
			elementGpgp.removeEventListener(this.openDialog);
		}
	})
		.component('cdx-field', Codex.CdxField)
		.component('cdx-lookup', Codex.CdxLookup)
		.component('cdx-button', Codex.CdxButton)
		.component('cdx-dialog', Codex.CdxDialog)
		.component('cdx-chip-input', Codex.CdxChipInput)
		.mount(mountPoint);
});