Difference between revisions of "Widget:DCTList"

From LINKS Community Center
Jump to: navigation, search
 
(32 intermediate revisions by the same user not shown)
Line 1: Line 1:
<noinclude>Current version of the DCT List.<br><span style="color: red; font-weight: bold;">Not ready for
+
<noinclude>DCT list widget.<br><span style="color: red; font-weight: bold;">Currently in use &ndash; do not modify!</span></noinclude>
        production!</span></noinclude>
 
 
<includeonly>
 
<includeonly>
     <link href="/resources/assets/tabulator.min.css" rel="stylesheet">
+
     <link href="/resources/assets/tabulator/dist/css/tabulator.min.css" rel="stylesheet">
     <script type="text/javascript" src="/resources/assets/tabulator.min.js"></script>
+
     <script type="text/javascript" src="/resources/assets/tabulator/dist/js/tabulator.min.js"></script>
  
 
     <style>
 
     <style>
Line 283: Line 282:
 
         * @property {FuncData} functions
 
         * @property {FuncData} functions
 
         * @property {string} usedByDmo
 
         * @property {string} usedByDmo
 +
        * @property {string} archived
 
         * @property {string} hasUC
 
         * @property {string} hasUC
 
         * @property {string} logo
 
         * @property {string} logo
Line 367: Line 367:
 
             const DMO_PROP = 'Used by Practitioners';
 
             const DMO_PROP = 'Used by Practitioners';
 
             const UC_PROP = 'Use Cases available';
 
             const UC_PROP = 'Use Cases available';
 +
            const ARCHIVED = 'Is Archived';
 
             const dctQuery = '[[Category:Disaster Community Technology]]'
 
             const dctQuery = '[[Category:Disaster Community Technology]]'
                 + '[[Is Archived::No]]'
+
                 // + '[[Is Archived::No]]'
 
                 + '|limit=500'
 
                 + '|limit=500'
 +
                + '|?' + ARCHIVED
 
                 + '|?' + IMG_PROP
 
                 + '|?' + IMG_PROP
 
                 + '|?' + DATASRC_PROP
 
                 + '|?' + DATASRC_PROP
Line 391: Line 393:
 
                 dct.usedByDmo = dctResult.printouts[DMO_PROP][0] === 't' ? 'yes' : 'no';    // not quite, but we only care about yes
 
                 dct.usedByDmo = dctResult.printouts[DMO_PROP][0] === 't' ? 'yes' : 'no';    // not quite, but we only care about yes
 
                 dct.hasUC = dctResult.printouts[UC_PROP][0] === 't' ? 'yes' : 'no';    // not quite, but we only care about yes
 
                 dct.hasUC = dctResult.printouts[UC_PROP][0] === 't' ? 'yes' : 'no';    // not quite, but we only care about yes
 +
                dct.archived = dctResult.printouts[ARCHIVED][0] === 't' ? 'yes' : 'no';    // not quite, but we only care about yes
  
 
                 dct.functions = new Map();
 
                 dct.functions = new Map();
Line 434: Line 437:
  
 
                 functionsCheck = checkEmpty && checkNonempty;
 
                 functionsCheck = checkEmpty && checkNonempty;
 +
                // TODO: Empty should no longer exist, once every category is fully listed in the filter.
 +
                // TODO: The filtering of functions therefore should be reduced to nonempty only.
 
             }
 
             }
  
Line 448: Line 453:
 
                 ? filterState.hasUC === dct.hasUC
 
                 ? filterState.hasUC === dct.hasUC
 
                 : true;
 
                 : true;
             return sourcesCheck && functionsCheck && businessModelCheck && dmUseCheck && ucCheck;
+
            const archivedCheck = filterState.showArchived
 +
                ? true
 +
                : dct.archived !== 'yes';
 +
 
 +
             return sourcesCheck && functionsCheck && businessModelCheck && dmUseCheck && ucCheck && archivedCheck;
 
         }
 
         }
  
Line 460: Line 469:
 
             }
 
             }
  
            /** @type {Partial<Omit<DCT, 'usedByDmo'> & { usedByDmo: string[]>}} */
 
 
             const filterState = {};
 
             const filterState = {};
  
Line 489: Line 497:
 
             if (document.getElementById('used-by-practitioners').checked) filterState.usedByDmo = 'yes';
 
             if (document.getElementById('used-by-practitioners').checked) filterState.usedByDmo = 'yes';
 
             if (document.getElementById('has-use-case').checked) filterState.hasUC = 'yes';
 
             if (document.getElementById('has-use-case').checked) filterState.hasUC = 'yes';
 +
            if (document.getElementById('show-archived').checked) filterState.showArchived = 'yes';
  
 
             table.setFilter(dctFilter, filterState);
 
             table.setFilter(dctFilter, filterState);
Line 501: Line 510:
 
             Array.from(functionsData).forEach(([fnCat, fnInfo], index) => {
 
             Array.from(functionsData).forEach(([fnCat, fnInfo], index) => {
 
                 const identifier = 'func-filter-' + escapeAttr(fnCat);
 
                 const identifier = 'func-filter-' + escapeAttr(fnCat);
                 funcFilterHtml +=
+
                 funcFilterHtml +=  
 
                     `<div class="func-filter-block">
 
                     `<div class="func-filter-block">
 
                         <div>
 
                         <div>
Line 509: Line 518:
  
 
                 // add subfunctions  
 
                 // add subfunctions  
                 if (index < 4) {
+
                 funcFilterHtml += '<div class="subfunc-filter-block">';
                    funcFilterHtml += '<div class="subfunc-filter-block">';
+
                for (const func of fnInfo.functions) {
                    for (const func of fnInfo.functions) {
+
                    const subfuncId = 'subfunc-filter-' + escapeAttr(func);
                        const subfuncId = 'subfunc-filter-' + escapeAttr(func);
+
                    funcFilterHtml +=
                        funcFilterHtml +=
+
                        `<div>
                            `<div>
+
                            <input type="checkbox" id="${subfuncId}" value="${func}">
                                <input type="checkbox" id="${subfuncId}" value="${func}">
+
                            <label for="${subfuncId}">${func}</label>
                                <label for="${subfuncId}">${func}</label>
+
                        </div>`;
                            </div>`;
 
                    }
 
                    funcFilterHtml += '</div>';
 
 
                 }
 
                 }
 +
                funcFilterHtml += '</div>';
 +
 
                 funcFilterHtml += '</div>';
 
                 funcFilterHtml += '</div>';
 
             });
 
             });
Line 563: Line 571:
 
             }, '');
 
             }, '');
 
             document.getElementById('business-model-filter').innerHTML = pricingFilterHtml;
 
             document.getElementById('business-model-filter').innerHTML = pricingFilterHtml;
 
            // const dmUse = ['Yes', 'Use Case', 'Unknown'];
 
            // let dmUseFilterHtml = dmUse.reduce((acc, curr) => {
 
            //    const identifier = escapeAttr(curr);
 
            //    return acc
 
            //        + '<div><input type="checkbox" id="dm-use-filter-' + identifier
 
            //        + '" value="' + curr + '">'
 
            //        + '<label for="dm-use-filter-' + identifier + '">' + curr + '</label></div>'
 
            // }, '');
 
            // document.getElementById('dm-use-filter').innerHTML = dmUseFilterHtml;
 
  
 
             // Set up table.
 
             // Set up table.
Line 583: Line 581:
 
                         field: 'name',
 
                         field: 'name',
 
                         minWidth: 300, // required for responsiveness when using fitColumns
 
                         minWidth: 300, // required for responsiveness when using fitColumns
 +
                        widthGrow: 2,
 
                         formatter: function (cell) {
 
                         formatter: function (cell) {
 
                             /** @type {DCT} */
 
                             /** @type {DCT} */
 
                             const dct = cell.getData();
 
                             const dct = cell.getData();
                             let out = '<a href="' + dct.url + '">' + dct.name + '</a><br>';
+
                             let out = '<a href="' + dct.url + '" translate="no">' + dct.name + '</a><br>';
 +
                            if (dct.archived.toLowerCase() === 'yes') {
 +
                                out += '<small><span class="badge lcc-badge-grey">Archived</span></small> ';
 +
                            }
 
                             if (dct.businessModel.includes(FREE_KEY)) {
 
                             if (dct.businessModel.includes(FREE_KEY)) {
                                 out += '<small><span class="badge badge-success">' + FREE_KEY + '</span></small> ';
+
                                 out += '<small><span class="badge lcc-badge-green">' + FREE_KEY + '</span></small> ';
 
                             }
 
                             }
 
                             if (dct.businessModel.includes(FREE_PLAN_KEY)) {
 
                             if (dct.businessModel.includes(FREE_PLAN_KEY)) {
                                 out += '<small><span class="badge badge-success">' + FREE_PLAN_KEY + '</span></small> ';
+
                                 out += '<small><span class="badge lcc-badge-green">' + FREE_PLAN_KEY + '</span></small> ';
 
                             }
 
                             }
 
                             if (dct.usedByDmo.toLowerCase() === 'yes') {
 
                             if (dct.usedByDmo.toLowerCase() === 'yes') {
                                 out += '<small><span class="badge badge-danger">Used by practitioners</span></small> ';
+
                                 out += '<small><span class="badge lcc-badge-red">Used by practitioners</span></small> ';
 
                             }
 
                             }
 
                             if (dct.hasUC.toLowerCase() === 'yes') {
 
                             if (dct.hasUC.toLowerCase() === 'yes') {
                                 out += '<small><span class="badge badge-warning">Use case available</span></small> ';
+
                                 out += '<small><span class="badge lcc-badge-purple">Use case available</span></small> ';
 
                             }
 
                             }
  
Line 606: Line 608:
 
                         title: 'Functions',
 
                         title: 'Functions',
 
                         field: 'functions',
 
                         field: 'functions',
                         minWidth: 300, // required for responsiveness when using fitColumns
+
                         minWidth: 200, // required for responsiveness when using fitColumns
 
                         cssClass: 'functions-cell',
 
                         cssClass: 'functions-cell',
 
                         formatter: function (cell) {
 
                         formatter: function (cell) {
Line 663: Line 665:
  
 
                 if (encoded) {
 
                 if (encoded) {
                     const action = JSON.parse(decodeURIComponent(atob(encoded)));
+
                     const actions = JSON.parse(decodeURIComponent(atob(encoded)));
  
                     const filter = action.filter;
+
                     const filter = actions.filter;
 
                     if (filter) {
 
                     if (filter) {
 
                         // Functions filter
 
                         // Functions filter
 
                         const functions = filter.functions;
 
                         const functions = filter.functions;
 
                         if (functions) {
 
                         if (functions) {
                             Object.keys(functions).forEach(fnCat => {
+
                             Object.keys(functions).forEach(subfun => {
                                 document.getElementById('func-filter-' + escapeAttr(fnCat))
+
                                 const subfunEl = document.getElementById('subfunc-filter-' + escapeAttr(subfun));
                                    .closest('.func-filter-block')
+
                                subfunEl.checked = !!functions[subfun];
                                    .querySelectorAll('input[type="checkbox"]').forEach(box => box.checked = !!functions[fnCat]);
+
                                subfunEl.dispatchEvent(new Event('change', { bubbles: true }));
 
                             });
 
                             });
  
Line 689: Line 691:
 
                     // ...
 
                     // ...
 
                 }
 
                 }
 +
 +
                applyFilters();
 
             });
 
             });
  
Line 780: Line 784:
 
                     const checkedSubs = Array.from(subfunctions).filter(sub => sub.checked).length;
 
                     const checkedSubs = Array.from(subfunctions).filter(sub => sub.checked).length;
 
                     category.checked = checkedSubs > 0;
 
                     category.checked = checkedSubs > 0;
                    // if (checkedSubs > 0) { category.checked = true; } else { category.checked = false; }
 
 
                 }
 
                 }
  
Line 916: Line 919:
 
             </div>
 
             </div>
  
             <h2 style="margin-top: 2.5rem; margin-bottom: 0;">Results: <span id="result-count"></span></h2>
+
             <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 2.5rem;">
 +
                <h2 style="margin-bottom: 0;">Results: <span id="result-count"></span></h2>
 +
                <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>
 +
            </div>
  
 
             <div id="dct-filters">
 
             <div id="dct-filters">
Line 938: Line 944:
 
                 </h2>
 
                 </h2>
 
                 <div style="text-align: center;">
 
                 <div style="text-align: center;">
                     <button class="large-button" type="button" onclick="clearFilters()">Show All</button>
+
                     <button class="large-button" type="button" onclick="clearFilters()">Clear Filters</button>
 
                 </div>
 
                 </div>
 
                 <div class="filter-wrapper">
 
                 <div class="filter-wrapper">
Line 993: Line 999:
 
                         <input type="checkbox" id="has-use-case" value="yes">
 
                         <input type="checkbox" id="has-use-case" value="yes">
 
                         <label for="has-use-case">Use case available</label>
 
                         <label for="has-use-case">Use case available</label>
 +
                    </div>
 +
                    <div>
 +
                        <input type="checkbox" id="show-archived" value="yes">
 +
                        <label for="show-archived">Show archived</label>
 
                     </div>
 
                     </div>
 
                 </div>
 
                 </div>

Latest revision as of 15:30, 19 December 2023

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