Widget: DCTList: Difference between revisions

From LINKS Community Center
Jump to: navigation, search
Eschmidt (talk | contribs)
No edit summary
Marterer (talk | contribs)
No edit summary
(537 intermediate revisions by 4 users not shown)
Line 1: Line 1:
<noinclude>Development verstion of the DCT List.<br><span style="color: red; font-weight: bold;">Not ready for production!</span></noinclude>
<noinclude>DCT list widget.<br><span style="color: red; font-weight: bold;">Currently in use &ndash; do not modify!</span></noinclude>
 
<includeonly>
<includeonly>
     <link href="https://unpkg.com/tabulator-tables@5.2.7/dist/css/tabulator.min.css" rel="stylesheet">
     <link href="/resources/assets/tabulator/dist/css/tabulator.min.css" rel="stylesheet">
     <script type="text/javascript" src="https://unpkg.com/tabulator-tables@5.2.7/dist/js/tabulator.min.js"></script>
     <script type="text/javascript" src="/resources/assets/tabulator/dist/js/tabulator.min.js"></script>
 
    <!-- STYLES BEGIN -->
<link rel="stylesheet" href="https://www.safetyinnovation.center/lcc/dct_list/styles.css">
<!-- STYLES END -->
 
    <!-- SCRIPT BEGIN -->
    <script type="text/javascript" src="https://www.safetyinnovation.center/lcc/dct_list/script.js"></script>
    <!-- SCRIPT END -->


     <style>
     <!-- Icon definitons -->
        #dct-list-wrapper { font-family: 'Open Sans'; }
    <img src="https://www.safetyinnovation.center/lcc/dct_list/img/unknown.svg">
        #dct-list-wrapper h1, #dct-list-wrapper h2, #dct-list-wrapper h3 {
            font-family: 'Raleway';
            font-weight: 300;
            letter-spacing: .06em;
        }
        #dct-list-wrapper h1 {
            margin-bottom: 2em;
            color: var(--links-blue);
        }
        #dct-list-wrapper h2 {
            margin-bottom: 1em;
        }
        #data-source-filter-wrapper button {
            border: 1px solid var(--links-blue);
            color: #fff;
            font-variant: small-caps;
            background: var(--links-blue);
            font-size: 1.2em;
            padding: 0.2em 0.4em;
            margin: 0.2em 0.4em;
        }
        #data-source-filter {
            font-size: 1.2em;
            margin-bottom: 4em;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(14em, 1fr));
            gap: 1em 1em;
        }
        #data-source-filter img { width: 2em; height: 2em; margin: 0 .5em; }
        #dct-tabulator.tabulator { border: 0 none; background-color: transparent; font-size: 1.2em; }
        #dct-tabulator.tabulator .tabulator-header { border-bottom: 4px double var(--links-blue); background-color: transparent; }
        #dct-tabulator.tabulator .tabulator-header .tabulator-col { border-right: 0 none; background: transparent; }
        #dct-tabulator.tabulator .tabulator-header .tabulator-col-content { padding: .5em 0; }
        #dct-tabulator.tabulator .tabulator-header .tabulator-col-sorter { right: 1em; }
        #dct-tabulator.tabulator .tabulator-row { background-color: transparent; }
        #dct-tabulator.tabulator .tabulator-cell { border-right: 0 none; border-bottom: 1px solid var(--links-blue); padding: .5em 0; }
        .data-source-img { width: 2em; height: 2em; }
    </style>


     <div id="dct-list-wrapper">
     <div id="dct-list-wrapper">
         <h1>Social Media and Crowdsourcing Technologies</h1>
         <h1>
        <h2>Filters</h2>
            <img src="https://www.safetyinnovation.center/lcc/dct_list/img/1-dct.svg">
        <div id="data-source-filter-wrapper">
            <div>
             <h3>Data Sources</h3>
                <div>Technologies</div>
            <button type="button" onclick="selectAll()">Select all</button>
                <div style="font-size:small; letter-spacing:.03em; margin-left: .6em;">Social Media and Crowdsourcing Library</div>
             <button type="button" onclick="deselectAll()">Deselect all</button>
             </div>
             <div id="data-source-filter"></div>
        </h1>
        <div id="dct-intro">
             <p>The overall goal of the Social Media and Crowdsourcing (SMCS) Technologies Library is to face the growing
                heterogeneous use of technologies in disasters and the overwhelming number of technologies on the
                market. It gathers and structures information about existing technologies to provide an up-to-date overview and
                thus support the selection of suitable technologies.
            </p>
             <p>
                You can use the filters to identify relevant technologies according to your needs and then click on the
                name of the technology to get further information.
            </p>
         </div>
         </div>
        <div id="dct-tabulator"></div>
    </div>


    <script>
        <div id="filter-bar">
    'use strict';
            <div style="display: flex; justify-content: space-between;">
                <div style="flex: 1 1;">
                    <h2 style="margin-bottom: 1rem;">Selected Filters</h2>
                    <div id="filter-summary">No filter. Showing all results.</div>
                </div>
                <div>
                    <button class="large-button open-filters" type="button" onclick="toggleFilter()">Open Filters</button>
                </div>
            </div>


    /**
            <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 2.5rem;">
    * @typedef {Object} DCT
                <h2 style="margin-bottom: 0;">Results: <span id="result-count"></span></h2>
    * @property {string} name
                <div><a href="/index.php/Form:Disaster_Community_Technology" style="color: var(--links-blue); font-size: 1.5em; font-variant:small-caps">Add new technology</a></div>
    * @property {string} url
            </div>
    * @property {string[]} dataSources
    * @property {string} logo
    */


    /** @param {string} title */
            <div id="dct-filters">
    const getUrl = title => {
                <h2 style="display: flex; justify-content: space-between;">
        return title ? '/index.php/Special:FilePath/' + title : title;
                    <div>
    }
                        <img src="filters.svg">
 
                        <span>Filters</span>
    /** @param {string} text */  
                    </div>
    const escapeAttr = text => {
                    <a onclick="toggleFilter()" id="close-filter-button">&times;</a>
        return text ? text.replace(/\s/g, '-') : text;
                </h2>
    }
                <div style="text-align: center;">
 
                    <button class="large-button" type="button" onclick="clearFilters()">Clear Filters</button>
    const table = new Tabulator("#dct-tabulator", {
                </div>
        layout: 'fitColumns',
                <div class="filter-wrapper">
        columns: [
                     <h4 class="filter-toggle">Functions <div class="plus icon"></div>
            {
                    </h4>
                title: 'Name',
                     <div class="filter-container">
                field: 'name',
                         <div class="filter-button-wrapper">
                formatter: function (cell) {
                            <button type="button" onclick="selectAll('#functions-filter')">Select all</button> |
                    /** @type {DCT} */
                            <button type="button" onclick="deselectAll('#functions-filter')">Clear all</button>
                    const dct = cell.getData();
                        </div>
                     return '<a href="' + dct.url + '">' + dct.name + '</a>';
                         <div class="filter-content loose" id="functions-filter"></div>
                }
                     </div>
            },
                </div>
            {
                 <div class="filter-wrapper">
                title: 'Data Sources',
                    <h4 class="filter-toggle">Supported Platforms <div class="plus icon"></div>
                field: 'dataSources',
                    </h4>
                formatter: function (cell) {
                    <div class="filter-container">
                     const output = cell.getValue().reduce((prev, curr) => {
                        <div class="filter-button-wrapper">
                         const src = dataSources.find(src => src.name === curr);
                            <button type="button" onclick="selectAll('#data-source-filter')">Select all</button> |
                        const url = src ? src.image : '';
                            <button type="button" onclick="deselectAll('#data-source-filter')">Clear all</button>
                         return url ? prev + '<img class="data-source-img" src="' + url + '">' : prev + ' ' + curr;
                        </div>
                     }, '');
                        <div class="filter-content loose" id="data-source-filter"></div>
                    return output;
                    </div>
                 }
                </div>
            }
                <div class="filter-wrapper">
        ]
                    <h4 class="filter-toggle">Pricing <div class="plus icon"></div>
    });
                    </h4>
 
                    <div class="filter-container">
    /**
                        <div class="filter-button-wrapper">
    * @param {DCT} dct
                            <button type="button" onclick="selectAll('#business-model-filter')">Select all</button> |
    * @param {DCT} filterState
                            <button type="button" onclick="deselectAll('#business-model-filter')">Clear all</button>
    */
                        </div>
    function dctFilter(dct, filterState) {
                        <div class="filter-content" id="business-model-filter"></div>
        return dct.dataSources.some(source => filterState.dataSources.includes(source));
                    </div>
    }
                </div>
 
                <!-- <div class="filter-wrapper">
    function updateFilter() {
                    <h4 class="filter-toggle">Used by Practitioners <div class="plus icon"></div>
 
                    </h4>
    }
                    <div class="filter-container">
 
                        <div class="filter-button-wrapper">
    async function getSources() {
                            <button type="button" onclick="selectAll('#dm-use-filter')">Select all</button> |
        const sourceQuery = '/api.php?action=ask&format=json&query=' + encodeURIComponent('[[Category:Social media platform]]|?IMAGE');
                            <button type="button" onclick="deselectAll('#dm-use-filter')">Clear all</button>
        const sourceResponse = await fetch(sourceQuery).then(response => response.json());
                        </div>
 
                        <div class="filter-content" id="dm-use-filter"></div>
        const results = sourceResponse.query.results;
                    </div>
        const sources = Object.getOwnPropertyNames(results).map(platformName => ({
                </div> -->
            name: platformName,
                <div id="bool-filters"
            image: getUrl(results[platformName].printouts['IMAGE'][0].fulltext.replace('PAGENAME:', ''))
                    style="border-top: 1px solid var(--links-blue); margin-top: 1em; padding-top: 1em;">
        }));
                    <div>
 
                        <input type="checkbox" id="used-by-practitioners" value="yes">
        return sources;
                        <label for="used-by-practitioners">Used by practitioners</label>
    }
                    </div>
 
                    <div>
    async function getDcts() {
                        <input type="checkbox" id="has-use-case" value="yes">
        const dctQuery = '[[Category:Disaster Community Technology]]' +
                        <label for="has-use-case">Use case available</label>
                        '|?Image' +
                    </div>
                        '|?Data Sources';
                    <div>
        const dctQueryUrl = '/api.php?action=ask&format=json&query=' + encodeURIComponent(dctQuery);
                        <input type="checkbox" id="show-archived" value="yes">
        const dctResponse = await fetch(dctQueryUrl).then(response => response.json());
                        <label for="show-archived">Show archived</label>
 
                    </div>
        const results = dctResponse.query.results;
                </div>
        const dctList = Object.getOwnPropertyNames(results).map(dctKey => {
             </div>
            /** @type {DCT} */
         </div>
            const dct = {};
        <div id="dct-tabulator"></div>
            dct.name = dctKey;
     </div>
            dct.url = results[dctKey].fullurl;
            dct.dataSources = results[dctKey].printouts['Data Sources'].map(source => source.fulltext).sort();
            dct.logo = results[dctKey].printouts['Image'][0] ? getUrl(results[dctKey].printouts['Image'][0].fulltext) : void 0;
            return dct;
        })
 
        return dctList;
    }
 
    // Load data and build page.
    Promise.all([getSources(), getDcts()]).then(data => {
        const dataSources = data[0];
        const dcts = data[1];
 
        console.log(data)
 
        // Create filters.
        const filterHtml = dataSources.reduce((prev, curr) => {
            const identifier = escapeAttr(curr.name);
            return prev +
                '<div><input type="checkbox" id="filter-' + identifier + '" value="' + curr.name + '" checked>' +
                '<label for="filter-' + identifier + '"><img src="' + curr.image + '"> ' + curr.name + '</label></div>'
        }, '');
        document.getElementById('data-source-filter').innerHTML = filterHtml;
 
        console.log(table)
        table.setData(dcts);
        table.on('tableBuilt', () => { console.log('set data', dcts);  });
        table.on('dataFiltered', (filters, rows) => {
            console.log(filters)
            //filters - array of filters currently applied
            //rows - array of row components that pass the filters
        });
 
        document.getElementById('data-source-filter').addEventListener('change', event => {
            const selectedSources = Array.from(
                document.querySelectorAll('#data-source-filter input[type="checkbox"]:checked')
            ).map(checkbox => checkbox.value);
 
             table.setFilter(dctFilter, { dataSources: selectedSources });
         }, { passive: true });
 
     });


    function selectAll() {
        // This won't trigger the 'change' event
        document.querySelectorAll('#data-source-filter input[type="checkbox"]').forEach(el => el.checked = true);
    }
    function deselectAll() {
        // This won't trigger the 'change' event
        document.querySelectorAll('#data-source-filter input[type="checkbox"]').forEach(el => el.checked = false);
    }
    </script>
</includeonly>
</includeonly>

Revision as of 22:22, 10 May 2024

DCT list widget.
Currently in use – do not modify!