User:TomT0m/queries/sandbox.js

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
// <syntaxhighlight lang="javascript">
/*jshint esversion: 8, esnext:false */


// Experiment : building query from high level tem{plates that generates SPARQL. 
// Attempt to give a user interface to the [[Category:Partial query]] template members
(function () {
    

    
	async function load_templates_in_category(api, name){
		let pages = [];
		let result;
		do {
			result = await api.get({
				action:"query",
				format:"json",
				list:"categorymembers",
				cmtitle:name, 
				cmnamespace:10,
				cmlimit:500
			});
			pages = pages.concat(result.query.categorymembers);
		} while (result.continue);
		return pages;
	}
	function range_list(size, interval_len){
		let rest = size % interval_len;
		let num_intervals = (size - (rest)) / interval_len;

		let ranges = Array.from({length: num_intervals}, (_, interval) => [interval * interval_len, ((interval+1) * interval_len) -1 ]);
		if(rest !== 0){
			let bound = interval_len * num_intervals;
			ranges.push([bound, bound + rest]);
		}
		return ranges;
	}
	async function load_templatedatas(api, templates){
		let results = {};
		let range_size = 500;

		let ranges = range_list(templates.length, range_size);
		// https://www.wikidata.org/w/api.php?action=templatedata&format=json&titles=Template%3All&formatversion=2
		for (let [min, max] of ranges){
			let templatedatas = await api.get({
				action:"templatedata",
				format:"json",
				titles: templates.slice(min, max)
			});

			for (let [id, page] of Object.entries(templatedatas.pages)){
				results[page.title] = page;
			}
		}
		return results;
	}
	
    function create_app(require) {
        const Vue = require('vue');
        const Pinia = require("pinia");
        pinia = Pinia.createPinia();
        const Codex = require('@wikimedia/codex');

        const store = Pinia.defineStore("fragment", {
	        state : () => {
	        	return { 
		        	fragments : [
		        		{
		        			id:1,
			            	template: "Query instances",
			            	params : [
			            		{name:1, val:"?item", type:"variable"}, 
			            		{name:2, val : "Q5", type:"item"}
			            	],
			            },
			            {
		        			id:2,
			            	template: "Query instances",
			            	params : [
			            		{name:1, val:"?item", type:"variable"}, 
			            		{name:2, val : "Q42", type:"item"}
			            	],
			            }
			        ]
	        	};
	        },
	        actions: {
	        	update_param(id, val) {
                	this.params.id = val;
            	}
	        }
	    });

        const App = Vue.createMwApp({
            template: `
            <fragmentList/>
            
            `,
        }).use(pinia);
        
        App.component('fragment', {
			template:`<div style="background-color:Azure;margin:3px">
			  {{ fragment.template }} : [ <parameter v-for="param in fragment.params" :param="param" :key=param.name></parameter> ]</div>  
			`,
			props:{ fragment : Object}
			/*,
			data() {
				return {
					template : store().template,
					params : store().params
				};
			}*/
		});
        
        App.component("fragmentList", {
        	template:`
        	<ul>
			<li v-for="fragment of fragments" >
				<fragment :fragment="fragment" :key="fragment.id"></fragment>
			</li></ul>
        	`,
        	data() {
        		return {
        			fragments : store().fragments
        		};
        	}
        });
        
        App.component("parameter", {
        	props: {param : Object},
        	template:`
        		<span style="margin:5px;">{{ param.name }} : {{ param.val }}</span>
        	`
        });
        
		

		/*
        App.component('view', {
            template: `
            <div style="margin-bottom: 1rem">
                {{ store.template }} : [ {{ <span v-for=param of store.params> param = store.params[param] ;</span>}}]
            </div>
            `,
            setup: () => ({ store }),
            components: {
                CdxButton: Codex.CdxButton,
            },
        });*/

        return App;
    }




	// load gadget 
	mw.loader.using( ['vue','pinia', '@wikimedia/codex', 'jquery.ui', 'mediawiki.api'], (require) => {

		
		let app = create_app(require);
		
		mw.util.addCSS(`
	.query_editor_position {
		position: absolute;
		left: 300px;
		top: 350px;   
	}`
		);
		
		mw.messages.set({
			"queryfragment_link_title" : "Easy query",
			"gadget_name" : "Easy query"
		});
		

		
		function listify(tab){
			return $("<ul>").append(
				tab.map((x, y) => $("<li>").append(x))
			);
		}
		
		function install_menu_content(app_data_model){
			const interface_container = `<div id="gadget-query-view"></div>`;
				
			let popup = create_gadget_view(interface_container);
			let popup_interface = $(".mw-page-container").append(popup.$element);

			$("#gadget-query-view").append(
				listify(Object.entries(app_data_model.templates).map(([title, template]) => title))
			);
			
			let link =$(mw.util.addPortletLink("p-tb", "#", mw.messages.get("queryfragment_link_title")));
			link.on("click", ()=>popup.toggle(true ));
		}



		mw.hook('wikipage.content').add(
			async (page_content)=>{
				"use strict";
				//console.log("Init function launched");
				// console.log(page_content);
				const config = {
					fragment_site: "https://www.wikidata.org/" ,
					fragment_category : "Category:Partial query",
					talk_page_id_class : "FragmentQuery" // defined in Template:FragmentQuery div class to install the query editor components
				};

				// loading the datas
				
				const api = new  mw.Api(config.fragment_site + "/w/api.php");
			
				async function get_templates_titles(){
					return await load_templates_in_category(api, config.fragment_category);
				}
				let partial_pages = await get_templates_titles();

				
				console.log(partial_pages);
				
				let templatedatas = await load_templatedatas(api, partial_pages.map((x, y) => x.title));
				console.log(templatedatas);

				let app_data_model = { templates: templatedatas };
				let apps_places = $("." + config.talk_page_id_class);

               	// install gadget views
               	
				$('#toc').before($('<div id="plop" class=""></div>'));
								app.mount("#plop");
				

			}
		);
	});
})();

// </syntaxhighlight>