Difference between revisions of "Widget:GuidelinesList"
From LINKS Community Center
(14 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | <noinclude>Current version of the List of Guidelines.<br><strong style="color:red;">Currently in use!</strong></noinclude> | + | <noinclude>Current version of the List of Guidelines.<br><strong style="color:red;">Currently in use – do not modify!</strong></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> | ||
#guideline-list-wrapper { | #guideline-list-wrapper { | ||
Line 132: | Line 132: | ||
align-items: start; | align-items: start; | ||
} | } | ||
− | + | ||
.filter-content.loose { | .filter-content.loose { | ||
gap: .5em .5em; | gap: .5em .5em; | ||
Line 210: | Line 210: | ||
#guideline-tabulator.tabulator .tabulator-row .tabulator-responsive-collapse { | #guideline-tabulator.tabulator .tabulator-row .tabulator-responsive-collapse { | ||
border: 0 none; | border: 0 none; | ||
− | |||
} | } | ||
Line 227: | Line 226: | ||
#guideline-tabulator.tabulator .tabulator-row .tabulator-responsive-collapse table { | #guideline-tabulator.tabulator .tabulator-row .tabulator-responsive-collapse table { | ||
font-size: smaller; | font-size: smaller; | ||
+ | } | ||
+ | |||
+ | #guideline-tabulator.tabulator .tabulator-row .tabulator-responsive-collapse table td { | ||
+ | white-space: normal; | ||
} | } | ||
Line 239: | Line 242: | ||
} | } | ||
− | + | /* .data-source-img, | |
− | .data-source-img, | ||
.func-img { | .func-img { | ||
width: 1.2rem; | width: 1.2rem; | ||
Line 247: | Line 249: | ||
margin-bottom: .4rem; | margin-bottom: .4rem; | ||
filter: grayscale(1); | filter: grayscale(1); | ||
− | } | + | } */ |
− | |||
</style> | </style> | ||
<script> | <script> | ||
Line 260: | Line 261: | ||
* @property {string[]} audienceTargets | * @property {string[]} audienceTargets | ||
* @property {string[]} languages | * @property {string[]} languages | ||
− | |||
* @property {string[]} techs | * @property {string[]} techs | ||
*/ | */ | ||
+ | |||
let table; // Tabulator instance | let table; // Tabulator instance | ||
// This defines how sources are grouped in the filter. | // This defines how sources are grouped in the filter. | ||
// Any source not listed here will be added to the last group entitled "More platforms". | // Any source not listed here will be added to the last group entitled "More platforms". | ||
− | const sourcesLayout = [ | + | // const sourcesLayout = [ |
− | + | // { | |
− | + | // title: 'General', | |
− | + | // sources: ['Crowd', 'Web'] | |
− | + | // }, | |
− | + | // { | |
− | + | // title: 'Platforms', | |
− | + | // sources: ['Facebook', 'Twitter', 'Instagram', 'YouTube'] | |
− | + | // } | |
− | ]; | + | // ]; |
const PHASES = ["Before", "During", "After"]; | const PHASES = ["Before", "During", "After"]; | ||
Line 287: | Line 288: | ||
const removePrefix = str => str.substring(str.indexOf(':') + 1); | const removePrefix = str => str.substring(str.indexOf(':') + 1); | ||
− | const DATASRC_PROP = 'Data Sources'; | + | // const DATASRC_PROP = 'Data Sources'; |
const PHASE_PROP = 'Disaster Management Phase'; | const PHASE_PROP = 'Disaster Management Phase'; | ||
const THEME_PROP = 'Covers Thematic'; | const THEME_PROP = 'Covers Thematic'; | ||
Line 295: | Line 296: | ||
const TA_PROP = 'Target Audience'; | const TA_PROP = 'Target Audience'; | ||
const TECH_PROP = 'Technologies' | const TECH_PROP = 'Technologies' | ||
+ | const PUB_PROP = 'Publishing Organisation'; | ||
const guidelineQuery = '[[Category:Guideline]]' | const guidelineQuery = '[[Category:Guideline]]' | ||
− | + '|?' + DATASRC_PROP | + | // + '|?' + DATASRC_PROP |
+ '|?' + PHASE_PROP | + '|?' + PHASE_PROP | ||
+ '|?' + THEME_PROP | + '|?' + THEME_PROP | ||
Line 305: | Line 307: | ||
+ '|?' + TA_PROP | + '|?' + TA_PROP | ||
+ '|?' + TECH_PROP | + '|?' + TECH_PROP | ||
+ | + '|?' + PUB_PROP | ||
+ '|limit=500'; | + '|limit=500'; | ||
Line 317: | Line 320: | ||
guideline.title = title; | guideline.title = title; | ||
guideline.url = guidelineResult.fullurl; | guideline.url = guidelineResult.fullurl; | ||
− | guideline[DATASRC_PROP] = guidelineResult.printouts[DATASRC_PROP].map(source => source.fulltext).sort(); | + | // guideline[DATASRC_PROP] = guidelineResult.printouts[DATASRC_PROP].map(source => source.fulltext).sort(); |
guideline[PHASE_PROP] = guidelineResult.printouts[PHASE_PROP].map(value => value.fulltext); | guideline[PHASE_PROP] = guidelineResult.printouts[PHASE_PROP].map(value => value.fulltext); | ||
guideline[THEME_PROP] = guidelineResult.printouts[THEME_PROP].map(value => value.fulltext); | guideline[THEME_PROP] = guidelineResult.printouts[THEME_PROP].map(value => value.fulltext); | ||
Line 325: | Line 328: | ||
guideline[YEAR_PROP] = guidelineResult.printouts[YEAR_PROP][0] && guidelineResult.printouts[YEAR_PROP][0].raw.slice(-4); | guideline[YEAR_PROP] = guidelineResult.printouts[YEAR_PROP][0] && guidelineResult.printouts[YEAR_PROP][0].raw.slice(-4); | ||
guideline[TECH_PROP] = guidelineResult.printouts[TECH_PROP].map(value => value.fulltext); | guideline[TECH_PROP] = guidelineResult.printouts[TECH_PROP].map(value => value.fulltext); | ||
+ | guideline[PUB_PROP] = guidelineResult.printouts[PUB_PROP].map(value => value.fulltext); | ||
return guideline; | return guideline; | ||
}); | }); | ||
} | } | ||
+ | // Fetches platform / data source information. | ||
+ | // async function getSources() { | ||
+ | // const IMG_KEY = 'IMAGE'; | ||
+ | // const sourceResponse = await fetch( | ||
+ | // getQueryUrl('[[Category:Social media platform]]|?' + IMG_KEY) | ||
+ | // ).then(response => response.json()); | ||
− | // | + | // return Object.keys(sourceResponse.query.results).map(platform => { |
− | + | // const img = sourceResponse.query.results[platform].printouts[IMG_KEY][0]; | |
− | + | // return { | |
− | + | // name: platform, | |
− | + | // image: img ? getFilePath(img.fulltext) : undefined | |
− | + | // }; | |
+ | // }); | ||
+ | // } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
function applyFilters(clear) { | function applyFilters(clear) { | ||
− | |||
if (!table) return; | if (!table) return; | ||
Line 378: | Line 381: | ||
if (selectedLang.length > 0) filterState.languages = selectedLang; | if (selectedLang.length > 0) filterState.languages = selectedLang; | ||
− | const selectedSources = Array.from(document.querySelectorAll('#data-source-filter input[type="checkbox"]:checked')) | + | // const selectedSources = Array.from(document.querySelectorAll('#data-source-filter input[type="checkbox"]:checked')) |
− | + | // .map(checkbox => checkbox.value); | |
− | if (selectedSources.length > 0) filterState.dataSources = selectedSources; | + | // if (selectedSources.length > 0) filterState.dataSources = selectedSources; |
const selectedTech = Array.from(document.querySelectorAll('#tech-filter input[type="checkbox"]:checked')) | const selectedTech = Array.from(document.querySelectorAll('#tech-filter input[type="checkbox"]:checked')) | ||
Line 412: | Line 415: | ||
? filterState.languages.every(lang => guideline[LANG_PROP].includes(lang)) | ? filterState.languages.every(lang => guideline[LANG_PROP].includes(lang)) | ||
: true; | : true; | ||
− | const sourcesCheck = filterState.dataSources | + | // const sourcesCheck = filterState.dataSources |
− | + | // ? filterState.dataSources.every(src => guideline[DATASRC_PROP].includes(src)) | |
− | + | // : true; | |
const techCheck = filterState.techs | const techCheck = filterState.techs | ||
? filterState.techs.every(tech => guideline[TECH_PROP].includes(tech)) | ? filterState.techs.every(tech => guideline[TECH_PROP].includes(tech)) | ||
: true; | : true; | ||
− | return phaseCheck && thematicCheck && audienceExperiencesCheck && audienceTargetCheck && langCheck & | + | return phaseCheck && thematicCheck && audienceExperiencesCheck && audienceTargetCheck && langCheck && techCheck; |
} | } | ||
− | Promise.all([getSources(), getGuidelines()]).then(data => { | + | Promise.all([ |
+ | // getSources(), | ||
+ | getGuidelines() | ||
+ | ]).then(data => { | ||
− | const [dataSources, guidelines] = data; | + | const [ |
+ | // dataSources, | ||
+ | guidelines | ||
+ | ] = data; | ||
let COVERS_THEMATIC_VALUES = [] | let COVERS_THEMATIC_VALUES = [] | ||
Line 457: | Line 466: | ||
// Set up sources filter | // Set up sources filter | ||
− | const groupedSources = []; | + | // const groupedSources = []; |
− | const sourcesCopy = Array.from(dataSources); | + | // const sourcesCopy = Array.from(dataSources); |
− | for (const layoutGroup of sourcesLayout) { | + | // for (const layoutGroup of sourcesLayout) { |
− | + | // const group = []; | |
− | + | // for (const source of layoutGroup.sources) { | |
− | + | // let idx = sourcesCopy.findIndex(src => src.name === source); | |
− | + | // if (idx !== -1) { group.push(sourcesCopy.splice(idx, 1)[0]); } | |
− | + | // } | |
− | + | // if (group.length > 0) { groupedSources.push({ title: layoutGroup.title, sources: group }); } | |
− | } | + | // } |
− | groupedSources.push({ title: 'More platforms', sources: sourcesCopy }); | + | // groupedSources.push({ title: 'More platforms', sources: sourcesCopy }); |
− | let dataSourceFilterHtml = ''; | + | // let dataSourceFilterHtml = ''; |
− | groupedSources.forEach(group => { | + | // groupedSources.forEach(group => { |
− | + | // dataSourceFilterHtml += '<div class="filter-group-header">' + group.title + '</div>'; | |
− | + | // dataSourceFilterHtml += group.sources.reduce((acc, curr, idx) => { | |
− | + | // const identifier = escapeAttr(curr.name); | |
− | + | // return acc + | |
− | + | // '<div ' + (idx === 0 ? ' class="filter-group-start">' : '>') + | |
− | + | // '<input type="checkbox" id="filter-' + identifier + '" value="' + curr.name + '">' + | |
− | + | // '<label for="filter-' + identifier + '"><img src="' + curr.image + '"> ' + curr.name + '</label></div>' | |
− | + | // }, ''); | |
− | }); | + | // }); |
− | document.getElementById('data-source-filter').innerHTML = dataSourceFilterHtml; | + | // document.getElementById('data-source-filter').innerHTML = dataSourceFilterHtml; |
Line 536: | Line 545: | ||
}, ''); | }, ''); | ||
document.getElementById('tech-filter').innerHTML = techHtml; | document.getElementById('tech-filter').innerHTML = techHtml; | ||
− | |||
const tabulator = new Tabulator('#guideline-tabulator', { | const tabulator = new Tabulator('#guideline-tabulator', { | ||
Line 552: | Line 560: | ||
title: 'Year', | title: 'Year', | ||
field: YEAR_PROP | field: YEAR_PROP | ||
+ | }, | ||
+ | { | ||
+ | title: 'Publishing Organisation', | ||
+ | field: PUB_PROP, | ||
+ | formatter: cell => cell.getValue().join(', ') | ||
}, | }, | ||
{ | { | ||
Line 583: | Line 596: | ||
formatter: cell => cell.getValue().join(', ') || '—' | formatter: cell => cell.getValue().join(', ') || '—' | ||
}, | }, | ||
− | { | + | // { |
− | + | // title: 'Mentions Platforms', | |
− | + | // field: DATASRC_PROP, | |
− | + | // minWidth: 300, // required for responsiveness when using fitColumns | |
− | + | // cssClass: 'data-sources-cell', | |
− | + | // formatter: function (cell) { | |
− | + | // const val = cell.getValue(); | |
− | + | // let out = ''; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | // groupedSources.forEach((group, gIndex) => { | |
+ | // // if (gIndex === groupedSources.length - 1) { out += '<div class="sources-collapse">'; } | ||
+ | // out += group.sources.reduce((prev, curr) => { | ||
+ | // const idx = val.findIndex(src => src === curr.name); | ||
+ | // if (idx === -1) { | ||
+ | // return prev; | ||
+ | // } else { | ||
+ | // return curr.image | ||
+ | // ? prev + '<img class="data-source-img" data-value="' + curr.name | ||
+ | // + '" src="' + curr.image | ||
+ | // + '" alt="' + curr.name | ||
+ | // + '" title="' + curr.name + '">' | ||
+ | // : prev + ' ' + curr.name; | ||
+ | // } | ||
+ | // }, ''); | ||
+ | // if (gIndex === groupedSources.length - 1) { | ||
+ | // // out += '<span class="sources-collapse-toggle"></span>'; | ||
+ | // // out += '</div>'; | ||
+ | // } | ||
+ | // }); | ||
− | + | // if (!out) { out = '—' } | |
− | |||
− | |||
+ | // return '<div>' + out + '</div>'; | ||
+ | // } | ||
+ | // } | ||
], | ], | ||
initialSort: [ | initialSort: [ | ||
Line 627: | Line 639: | ||
tabulator.on('tableBuilt', () => { | tabulator.on('tableBuilt', () => { | ||
tabulator.redraw(true); | tabulator.redraw(true); | ||
− | |||
table = tabulator; | table = tabulator; | ||
+ | // Set up the table if parameter was passed. | ||
+ | const params = new URLSearchParams(window.location.search); | ||
+ | const encoded = params.get('do'); | ||
+ | |||
+ | if (encoded) { | ||
+ | const actions = JSON.parse(decodeURIComponent(atob(encoded))); | ||
+ | const filter = actions.filter; | ||
+ | |||
+ | if (filter) { | ||
+ | const thematic = filter[THEME_PROP]; | ||
+ | if (thematic) { | ||
+ | Object.keys(thematic).forEach(theme => { | ||
+ | const box = document.getElementById('thematic-filter-' + escapeAttr(theme)); | ||
+ | box.checked = !!thematic[theme]; | ||
+ | box.dispatchEvent(new Event('change', { bubbles: true })); | ||
+ | }); | ||
+ | |||
+ | document.getElementById('thematic-filter').closest('.filter-wrapper').classList.toggle('open'); | ||
+ | } | ||
+ | |||
+ | const audience = filter[TA_PROP]; | ||
+ | if (audience) { | ||
+ | Object.keys(audience).forEach(ta => { | ||
+ | const box = document.getElementById('target-audience-filter-' + escapeAttr(ta)); | ||
+ | box.checked = !!audience[ta]; | ||
+ | box.dispatchEvent(new Event('change', { bubbles: true })); | ||
+ | }); | ||
+ | |||
+ | document.getElementById('target-audience-filter').closest('.filter-wrapper').classList.toggle('open'); | ||
+ | } | ||
+ | |||
+ | applyFilters(); | ||
+ | toggleFilter(); | ||
+ | } | ||
+ | |||
+ | // Further actions (e.g. open filter panel, etc.) | ||
+ | // ... | ||
+ | } | ||
}); | }); | ||
+ | |||
tabulator.on('dataFiltered', (filters, rows) => { | tabulator.on('dataFiltered', (filters, rows) => { | ||
const summary = document.getElementById('filter-summary'); | const summary = document.getElementById('filter-summary'); | ||
Line 643: | Line 693: | ||
// Exit if filter object/type doesn't exist (happens after Tabulator's own filter reset). | // Exit if filter object/type doesn't exist (happens after Tabulator's own filter reset). | ||
if (!(filter && filter.type)) { summary.textContent = 'No filter. Showing all results.'; return; } | if (!(filter && filter.type)) { summary.textContent = 'No filter. Showing all results.'; return; } | ||
− | |||
// Update filter text. | // Update filter text. | ||
Line 652: | Line 701: | ||
!filter.type.audienceTargets && | !filter.type.audienceTargets && | ||
!filter.type.audienceExperiences && | !filter.type.audienceExperiences && | ||
− | !filter.type.dataSources && | + | // !filter.type.dataSources && |
!filter.type.techs | !filter.type.techs | ||
) { summary.textContent = 'No filter. Showing all results.'; } | ) { summary.textContent = 'No filter. Showing all results.'; } | ||
Line 682: | Line 731: | ||
+ '</td></tr>'; | + '</td></tr>'; | ||
} | } | ||
− | if (filter.type.dataSources) { | + | // if (filter.type.dataSources) { |
− | + | // summaryHtml += '<tr><td><strong>Mentions Platforms</strong></td><td>' | |
− | + | // + (filter.type.dataSources.length > 0 ? filter.type.dataSources.join(', ') : 'none') | |
− | + | // + '</td></tr>'; | |
− | } | + | // } |
if (filter.type.techs) { | if (filter.type.techs) { | ||
summaryHtml += '<tr><td><strong>Mentions Technologies</strong></td><td>' | summaryHtml += '<tr><td><strong>Mentions Technologies</strong></td><td>' | ||
Line 696: | Line 745: | ||
} | } | ||
− | const markImages = () => { | + | // const markImages = () => { |
− | + | // const selectedSources = filter.type.dataSources; | |
− | + | // const selectedFunctions = filter.type.functions; | |
− | + | // // Mark data source images | |
− | + | // document.querySelectorAll('.data-sources-cell .data-source-img, .tabulator-responsive-collapse .data-source-img') | |
− | + | // .forEach(img => { | |
− | + | // if (!selectedSources || selectedSources.includes(img.dataset.value)) { img.classList.remove('unselected'); } | |
− | + | // else { img.classList.add('unselected'); } | |
− | + | // }); | |
− | + | // // Mark functions images | |
− | + | // document.querySelectorAll('.functions-cell .func-img').forEach(img => { | |
− | + | // if (!selectedFunctions || selectedFunctions.includes(img.dataset.value)) { img.classList.remove('unselected'); } | |
− | + | // else { img.classList.add('unselected'); } | |
− | + | // }); | |
− | + | // tabulator.off('renderComplete', markImages); | |
− | } | + | // } |
− | + | // // TODO: Prevent this from running if corresponding filters are not active. | |
+ | // tabulator.on('renderComplete', markImages); | ||
}); | }); | ||
Line 734: | Line 784: | ||
applyFilters(); | applyFilters(); | ||
}, { passive: true }); | }, { passive: true }); | ||
− | document.getElementById('data-source-filter').addEventListener('change', event => { | + | // document.getElementById('data-source-filter').addEventListener('change', event => { |
− | + | // applyFilters(); | |
− | }, { passive: true }); | + | // }, { passive: true }); |
document.getElementById('tech-filter').addEventListener('change', event => { | document.getElementById('tech-filter').addEventListener('change', event => { | ||
applyFilters(); | applyFilters(); | ||
Line 761: | Line 811: | ||
// TODO: Check the bugfix for a possible infinite event loop. | // TODO: Check the bugfix for a possible infinite event loop. | ||
// This will help detect it, in case it happens. | // This will help detect it, in case it happens. | ||
− | console.log('Table height bugfix: render complete.'); | + | // console.log('Table height bugfix: render complete.'); |
try { | try { | ||
Line 938: | Line 988: | ||
</div> | </div> | ||
</div> | </div> | ||
− | <div class="filter-wrapper"> | + | <!-- <div class="filter-wrapper"> |
<h4 class="filter-toggle">Mentions Platforms <div class="plus icon"></div></h4> | <h4 class="filter-toggle">Mentions Platforms <div class="plus icon"></div></h4> | ||
<div class="filter-container"> | <div class="filter-container"> | ||
Line 947: | Line 997: | ||
<div class="filter-content loose" id="data-source-filter"></div> | <div class="filter-content loose" id="data-source-filter"></div> | ||
</div> | </div> | ||
− | </div> | + | </div> --> |
<div class="filter-wrapper"> | <div class="filter-wrapper"> | ||
<h4 class="filter-toggle">Mentions Technologies <div class="plus icon"></div></h4> | <h4 class="filter-toggle">Mentions Technologies <div class="plus icon"></div></h4> |
Latest revision as of 14:48, 18 July 2023
Current version of the List of Guidelines.
Currently in use – do not modify!