|
|
Line 1: |
Line 1: |
| ORIGIN = 'http://localhost:8000'
| |
| API_URL = 'https://164-92-142-113.nip.io/api.php'
| |
|
| |
| var actions = []; | | var actions = []; |
| var progressItems = {}; | | var progressItems = {}; |
| var orgs = {} | | var orgs = {} |
| var org_name = null | | var org_name = null |
| var lang = 'fi'
| |
| var highlightedTerm = null
| |
| var highlights = null
| |
| var hightlightIndex = 0
| |
|
| |
| class_map = {
| |
| 'Tutkimusjulkaisut': 'field-border-1',
| |
| 'Toimintakulttuuri': 'field-border-2',
| |
| 'Oppiminen' : 'field-border-3',
| |
| 'Data' : 'field-border-4'
| |
| }
| |
| color_map = {
| |
| 'Tutkimusjulkaisut': '#007ECA',
| |
| 'Toimintakulttuuri': '#53BD9D',
| |
| 'Oppiminen' : '#93A0FF',
| |
| 'Data' : '#003EAD'
| |
| }
| |
|
| |
|
| |
| const scrollObserver = new IntersectionObserver(
| |
| ([e]) => e.target.classList.toggle('stuck', e.intersectionRatio < 1),
| |
| {threshold: [1]}
| |
| );
| |
|
| |
| //observer.observe(document.querySelector('.rowgroup-header'));
| |
|
| |
|
| |
|
| |
|
| |
| function prevMatch() {
| |
| var searchword = $("#searchtxt").val();
| |
| if(searchword != '') {
| |
| $('#overview_actions').addClass('search')
| |
|
| |
| if( hightlightIndex > 0) {
| |
| hightlightIndex--
| |
| }
| |
| replaceText()
| |
|
| |
| }
| |
| }
| |
| function nextMatch() {
| |
| var searchword = $("#searchtxt").val();
| |
| if(searchword != '') {
| |
|
| |
| $('#overview_actions').addClass('search')
| |
| replaceText()
| |
| if(hightlightIndex < highlights.length -1) {
| |
| hightlightIndex++
| |
| }
| |
| }
| |
| }
| |
| function replaceText() {
| |
| var searchword = $("#searchtxt").val();
| |
| console.log(hightlightIndex)
| |
| if(searchword != highlightedTerm) {
| |
| highlightedTerm = searchword
| |
| hightlightIndex = 0
| |
| $(".card-body").find(".highlight").removeClass("highlight");
| |
| var custfilter = new RegExp(searchword, "ig");
| |
| var repstr = "<span class='highlight'>" + searchword + "</span>";
| |
| if (searchword != "") {
| |
| $('.card-body').each(function() {
| |
| $(this).html($(this).html().replace(custfilter, repstr));
| |
| })
| |
| }
| |
| highlights = $('.highlight')
| |
| if(highlights.length >0) {
| |
| highlights[hightlightIndex].scrollIntoView()
| |
| $('html, body').animate({scrollTop: '-=70px'}, 0);
| |
|
| |
| }
| |
| }
| |
| else {
| |
| highlights[hightlightIndex].scrollIntoView()
| |
| $('html, body').animate({scrollTop: '-=70px'}, 0);
| |
| }
| |
| $('#numOfMatches').text((hightlightIndex + 1) + '/' + highlights.length)
| |
|
| |
| }
| |
|
| |
| function clearSearch() {
| |
| $("#searchtxt").val('');
| |
| $('#overview_actions').removeClass('search')
| |
| $(".card-body").find(".highlight").removeClass("highlight");
| |
| hightlightIndex = 0
| |
| $('#numOfMatches').text('')
| |
| }
| |
|
| |
| function getSelectedCheckboxes(selector) {
| |
| var selected = new Set()
| |
| $(selector + ' input:checked').each(function () {
| |
| selected.add($(this).val());
| |
| });
| |
| return selected
| |
| }
| |
|
| |
| function getSelectedRadio(selector) {
| |
| return $(selector + ' input:checked').val()
| |
| }
| |
|
| |
| function getSelectedOptions(selector) {
| |
| var selected = new Set();
| |
| $(selector + ' option:selected').each(function () {
| |
| selected.add($(this).val());
| |
| });
| |
| return selected
| |
| }
| |
|
| |
|
| function updateActionView() { | | function updateActionView() { |
Line 164: |
Line 53: |
| document.querySelectorAll('.rowgroup-header').forEach(function(e) { | | document.querySelectorAll('.rowgroup-header').forEach(function(e) { |
| scrollObserver.observe(e) | | scrollObserver.observe(e) |
| }); | | }); |
|
| |
| } | | } |
|
| |
|
| |
|
| |
| } | | } |
|
| |
|
| function renderActionHeader(org_actors) { | | function renderActionHeader(org_actors) { |
|
| |
| org_actors.forEach(org_actor => { | | org_actors.forEach(org_actor => { |
| var col = $('<div>', {class:'col'}).html('<h1>' + org_actor.name + '</h1>') | | var col = $('<div>', {class:'col'}).html('<h1>' + org_actor.name + '</h1>') |
| $('#selected-orgs-row').append(col) | | $('#selected-orgs-row').append(col) |
| }) | | }) |
|
| |
| } | | } |
|
| |
|
| function getSortedKeys(dictonary) {
| |
| var sorted = [];
| |
| for(var key in dictonary) {
| |
| sorted[sorted.length] = key;
| |
| }
| |
| sorted.sort();
| |
| return sorted
| |
| }
| |
| function renderActions(actions, org_actors) { | | function renderActions(actions, org_actors) { |
| for(var year = 2020; year < 2026; year++) { | | for(var year = 2020; year < 2026; year++) { |
Line 229: |
Line 104: |
| $('#org_actions').append(year_container) | | $('#org_actions').append(year_container) |
| } | | } |
| }
| |
|
| |
| function renderAction(obj) {
| |
| var policy_page = obj['action_id_raw'].substring(0, obj['action_id_raw'].indexOf('/'))
| |
| var policy_doc_link = '/' + policy_page + '#' + obj['section_type_name'] + '_' + obj['section_ordinal'] + ':_' + obj['section_name'].replace(' ', '_')
| |
| var action_card = $('<div>', {class: 'card mb-4 ' + class_map[obj.action_field]})
| |
| var action_header = $('<div>', {class: 'card-header', style:'color: #ffffff; background-color:' + color_map[obj.action_field]}).html(obj.action_field + ' - ' + obj['section_type_name'] + ' ' + obj.section_ordinal + '<a style="color:white" data-toggle="collapse" href="#collapse' + obj.action_id +'"><i class="bi bi-chevron-down float-right"></i></a>')
| |
| var action_body = $('<div>', {class: 'card-body'})
| |
| var field_badge = $('<span>', {class: 'badge float-right', style:'background-color:' + color_map[obj.action_field]}).text(obj.action_field)
| |
| var action_section = $('<div>', {class:'collapse', id: 'collapse' + obj.action_id }).html(
| |
| '<h5 style="margin-top: 1em">'+ obj.section_name + '<a style="color: white" href="' + policy_doc_link + '"><i title="Avaa linjausteksti" style="margin-left: 1em;" class="bi bi-box-arrow-up-right"></i></a></h5><p> ' + obj.section_desc + '</p>'
| |
| )
| |
| var action_title = $('<h5>', {class: 'card-title'}).text(obj.action_name)
| |
| //var action_title = $('<h5>', {class: 'card-title'}).html(obj.action_name+'<i class="bi bi-question-octagon-fill float-right" style="font-size: 2rem; color:'+ color_map[obj.action_field] +'" data-trigger"focus" data-container="body" data-toggle="popover" data-placement="top" data-content="' + obj.section_desc + ' "></i>')
| |
| var action_text = $('<p>', {class: 'card-text'}).text(obj.action_description)
| |
|
| |
|
| |
| var action_footer = $('<div>', {class: 'card-footer', style:'background-color: ' + color_map[obj.action_field]})
| |
|
| |
| var progressCount = 0
| |
| if(obj.action_id in progressItems) {
| |
| var p_items = progressItems[obj.action_id]
| |
| var progressCount = p_items.length
| |
| }
| |
| if(progressCount > 0) {
| |
| console.log(progressCount)
| |
| var progress_button = $('<button>', {class: 'btn btn-secondary float-right', type:'button', onclick:'$("#' + obj.action_id + '").modal("show")'}).html('Edistysaskeleita<span style="margin-left: 5px" class="badge badge-dark">' + progressCount +'</span>')
| |
| action_body.append(progress_button)
| |
| console.log(obj)
| |
| }
| |
| var progress_add = $('<a>', {class:'new-progress btn btn-outline-primary float-right', style: 'color: white; border-color: white;', href:'https://164-92-142-113.nip.io/index.php/Special:FormEdit/Progress?Progress[Action]='+encodeURIComponent(obj.action_id_raw) }).text('Add new')
| |
|
| |
| action_card.append(action_header)
| |
| action_card.append(action_body)
| |
|
| |
| action_header.append(action_section)
| |
|
| |
| action_body.append(action_title)
| |
| action_body.append(action_text)
| |
| //action_body.append(action_link)
| |
| addProgressModal(obj)
| |
|
| |
| return action_card
| |
| }
| |
|
| |
| function addProgressModal(action) {
| |
| if(action.action_id in progressItems) {
| |
| console.log(action)
| |
| var _progressItems = progressItems[action.action_id]
| |
|
| |
| var $modalContainer = $('<div>', {class:'modal', tabindex:'-1', role:'dialog', id:action.action_id})
| |
| var $modal = $('<div>', {class:'modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable', role:'document'})
| |
| var $modalContent = $('<div>', {class:'modal-content'})
| |
| var $modalHeader = $('<div>', {class:'modal-header'})
| |
| var $title = $('<h5>', {class:'modal-title'}).text(action.section_type_name)
| |
| var $titleClose = $('<button>', {type:'button', class:'close', 'data-dismiss':'modal'})
| |
| var $close = $('<span>').html('×')
| |
| $titleClose.append($close)
| |
|
| |
| var $actionText = $('<p>', {class:'card-text'}).text((action.action_name != '' ? action.action_name + '. ' : '') + action.action_description)
| |
| var $actionRole = $('<h6>', {class:'card-subtitle mb-2 text-muted'}).text(action.action_responsible_actor.join(','))
| |
| var $objectiveName = $('<h5>', {class:'card-title'}).text(action.section_name)
| |
| var $policyLink = $('<a>', {href:'#', class:'card-link'}).text(action.policy_name)
| |
| var $modalBody = $('<div>', {class:'modal-body'})
| |
| var $sectionType = $('<p>').text(action.section_type_name)
| |
| //$modalBody.append($sectionType)
| |
| $modalBody.append($objectiveName)
| |
| //$modalBody.append($actionRole)
| |
| //$modalBody.append($actionText)
| |
|
| |
| _progressItems.forEach(function(progressItem) {
| |
| $modalBody.append(createProgressCard(progressItem))
| |
| })
| |
| $modalHeader.append($title)
| |
| $modalHeader.append($titleClose)
| |
|
| |
| $modalContent.append($modalHeader)
| |
| $modalContent.append($modalBody)
| |
|
| |
| $modal.append($modalContent)
| |
|
| |
| $modalContainer.append($modal)
| |
|
| |
| $('#modals').append($modalContainer)
| |
| }
| |
| }
| |
|
| |
| function createProgressCard(data) {
| |
| var $card = $('<div>', {class:'card', style: 'margin-bottom: 1em;'})
| |
| var $cardBody = $('<div>', {class:'card-body'})
| |
| var $cardTitle = $('<h5>', {class: 'card-title'}).text(data.name)
| |
| var $cardSubTitle = $('<h6>', {class:'card-subtitle mb-2 text-muted'}).text(data.date)
| |
| var $cardSubTitle2 = $('<h6>', {class:'card-subtitle mb-2 text-muted'}).text(data.org)
| |
| $cardText = $('<p>', {class: 'card-text'}).text(data.desc)
| |
|
| |
| $cardBody.append($cardTitle)
| |
| $cardBody.append($cardSubTitle)
| |
| $cardBody.append($cardSubTitle2)
| |
| $cardBody.append($cardText)
| |
| $card.append($cardBody)
| |
|
| |
| return $card
| |
| } | | } |
|
| |
|
Line 337: |
Line 110: |
| groups = group_actions_by_year(actions) | | groups = group_actions_by_year(actions) |
| // then by org | | // then by org |
| console.log(groups)
| |
| groups = group_by_org(groups, org_actors) | | groups = group_by_org(groups, org_actors) |
| console.log(groups)
| |
| return groups | | return groups |
|
| |
| }
| |
| function group_actions_by_year(actions) {
| |
| return actions.reduce((groups, item) => {
| |
| year = getActionYear(item)
| |
| const group = (groups[year] || []);
| |
| group.push(item);
| |
| groups[year] = group;
| |
| return groups;
| |
| }, {});
| |
| } | | } |
|
| |
|
Line 385: |
Line 146: |
| }) | | }) |
| return groups | | return groups |
| }
| |
|
| |
|
| |
| function intersection(setA, setB) {
| |
| const _intersection = new Set();
| |
| for (const elem of setB) {
| |
| if (setA.has(elem)) {
| |
| _intersection.add(elem);
| |
| }
| |
| }
| |
| return _intersection;
| |
| }
| |
|
| |
| function getActionYear(action) {
| |
| if(action.action_deadline) {
| |
| return ''+action.action_deadline
| |
| }
| |
| if(action.section_deadline) {
| |
| return ''+action.section_deadline
| |
| }
| |
| return ''+action.policy_endyear
| |
| } | | } |
|
| |
|
| function filterActions(domains, years) { | | function filterActions(domains, years) { |
|
| |
| // actors
| |
| /*
| |
| result = actions.filter(action => {
| |
| return intersection(
| |
| new Set(action.action_responsible_actor.map(a=>a.fulltext)),
| |
| actors).size > 0
| |
| })
| |
| */
| |
| // years | | // years |
| var result = actions.filter(action => { | | var result = actions.filter(action => { |
Line 427: |
Line 158: |
| }) | | }) |
| return result | | return result |
| }
| |
|
| |
|
| |
|
| |
| /* shared */
| |
| async function updateProgressData(data) {
| |
| console.log(data)
| |
| items = {}
| |
| data.forEach(function (r) {
| |
| progressID = Object.keys(r)[0]
| |
| obj = r[progressID]
| |
| console.log(obj)
| |
| date = ''
| |
| if (obj.printouts['Date'].length > 0 && obj.printouts['Date'][0].timestamp) {
| |
| date = new Date(parseInt(obj.printouts['Date'][0].timestamp) * 1000)
| |
| }
| |
|
| |
| actionID = obj.printouts.Action[0].fulltext.replace('#', '').replace(/\s/g, '').replace(':', '').replace('/', '')
| |
| progressUrl = obj.printouts.Action[0].fullurl
| |
| name = obj.printouts.Name || ''
| |
| desc = obj.printouts.Description || ''
| |
| orgName = obj.printouts.OrgName || ''
| |
|
| |
| if (!(actionID in items)) {
| |
| items[actionID] = []
| |
| }
| |
| items[actionID].push({
| |
| url: obj.fullurl,
| |
| fulltext: obj.fulltext,
| |
| actionID: actionID,
| |
| url: progressUrl,
| |
| date: date,
| |
| name: name,
| |
| desc: desc,
| |
| org: orgName
| |
|
| |
| })
| |
| })
| |
| progressItems = items
| |
| }
| |
|
| |
| function updateActions(data) {
| |
| console.log(data)
| |
| actions = []
| |
| data.forEach(function (r) {
| |
| progressID = Object.keys(r)[0]
| |
| obj = r[progressID]
| |
|
| |
|
| |
| var section_desc = obj.printouts['sectionDesc'][0] || '' // footnotes!
| |
| section_desc = section_desc.replace(/\[\[.*\]\]/g, "");
| |
| var action_description = obj.printouts['Description'][0] || ''
| |
| //action_description = action_description.replace(/<\/?[^>]+(>|$)/g, "")
| |
| actions.push(
| |
| {
| |
| 'policy_name': obj.printouts['policyName'][0] || '',
| |
| 'policy_endyear': obj.printouts['policyEndYear'][0] || null,
| |
| 'section_name': obj.printouts['sectionName'][0] || '',
| |
| 'section_desc': section_desc,
| |
| 'section_deadline': obj.printouts['Section deadline'][0] || null,
| |
| 'section_ordinal': obj.printouts['sectionOrdinal'][0] || null,
| |
| 'section_type': obj.printouts['sectionType'][0].fulltext || '',
| |
| 'section_type_name': obj.printouts['sectionTypeName'][0] || '',
| |
| 'action_deadline': obj.printouts['Action deadline'][0] || null,
| |
| 'action_description': action_description,
| |
| 'action_field': obj.printouts['Field'][0] || '',
| |
| 'action_domain': obj.printouts['Domain'][0].fulltext || '',
| |
| 'action_name': obj.printouts['Name'][0] || '',
| |
| 'action_responsible_actor': obj.printouts['Responsible actor'],
| |
| 'action_id': obj.fulltext.replace('#', '').replace(/\s/g, '').replace(':', '').replace('/', ''),
| |
| 'action_id_raw': obj.fulltext
| |
|
| |
| }
| |
| )
| |
| })
| |
| }
| |
|
| |
|
| |
| function updateOrgs(data) {
| |
| console.log(data)
| |
| actions = []
| |
| data.forEach(function (r) {
| |
| progressID = Object.keys(r)[0]
| |
| obj = r[progressID]
| |
| console.log(obj)
| |
| var businessID = obj.printouts['BusinessID'][0] || ''
| |
| // handle localized string queries and separate properties - todo refactor this out
| |
| var actors = []
| |
| var actor_ids = obj.printouts['Responsible actor']
| |
| var actors_fi = obj.printouts['actors_fi']
| |
| var actors_sv = obj.printouts['actors_sv']
| |
| var actors_en = obj.printouts['actors_en']
| |
|
| |
| for (let i = 0; i < actor_ids.length; i++) {
| |
| actors.push({
| |
| id: actor_ids[i].fulltext,
| |
| fi: actors_fi[i],
| |
| sv: actors_sv[i],
| |
| en: actors_en[i]
| |
| })
| |
| }
| |
| orgs[''+businessID] = {
| |
| 'name': obj.printouts['Name'][0] || '',
| |
| 'businessID': businessID,
| |
| 'responsible_actors': actors,
| |
| }
| |
| })
| |
| console.log(orgs)
| |
| }
| |
|
| |
| function updateActors(data) {
| |
| console.log(data)
| |
| data.forEach(function (r) {
| |
| id = Object.keys(r)[0]
| |
|
| |
| var name = r[id].printouts['Name'][0]
| |
| $('#actors').append('<option value="'+id+'">'+name+'</option>')
| |
| console.log('test')
| |
| })
| |
|
| |
| }
| |
|
| |
| async function fetch_data(lang) {
| |
| // get all Actions
| |
|
| |
| const actionQuery = '[[Category:Action]]|?Part of document.Name ' + lang + '=sectionName|?Part of document.Type=sectionType|?Part of document.Type.Name ' + lang + '=sectionTypeName|?Part of document.Description ' + lang + '=sectionDesc|?Part of document.Ordinal=sectionOrdinal|?Part of document.Document.Name ' + lang + '=policyName|?Part of document.Document.Validity end=policyEndYear|?Part of document.Document.Field.Name ' + lang + '=Field|?Part of document.Document.Field=Domain|?Name ' + lang + '=Name|?Description ' + lang + '=Description|?Responsible actor|?Deadline year=Action deadline|?Part of document.Name ' + lang + '=Section name|?Part of document.Deadline year=Section deadline|limit=50'
| |
| const progressQuery = '[[Category:Progress]]|?Name|?Description|?Date|?Action|?Organization.Name=OrgName'
| |
|
| |
| const actorQuery = '[[Category:Actor]]|?Name ' + lang + '=Name|limit=500'
| |
|
| |
| const orgQuery = '[[Category:Organization]]|?Name|?BusinessID|?Responsible actor|?Responsible actor.Name fi=actors_fi|?Responsible actor.Name sv=actors_sv|?Responsible actor.Name en=actors_en|limit=500'
| |
|
| |
| $('#spinner').show()
| |
| $('#error').hide()
| |
|
| |
|
| |
| return Promise.all([
| |
| executeAsk(progressQuery)
| |
| .then(updateProgressData),
| |
| executeAsk(actionQuery)
| |
| .then(updateActions),
| |
| executeAsk(orgQuery)
| |
| .then(updateOrgs)
| |
|
| |
| ])
| |
| .then(() => {
| |
| console.log('data loaded')
| |
| $('#spinner').hide()
| |
| console.log(actions)
| |
| console.log(progressItems)
| |
| $('#orgs').selectpicker({
| |
| actionsBox: true,
| |
| selectedTextFormat: 'count',
| |
| liveSearch: true,
| |
| multiple: true,
| |
| maxOptions: 3,
| |
| width: 'fit'
| |
| })
| |
| //$('#actors').selectpicker('selectAll');
| |
| $('#filters').collapse('show')
| |
|
| |
| })
| |
|
| |
| }
| |
|
| |
|
| |
| async function executeAsk(query) {
| |
|
| |
| var results = [];
| |
| var res = null;
| |
| var offset = 0
| |
| try {
| |
| while (res == null || res.query.results.length == 50) {
| |
|
| |
| _query = query + '|offset=' + offset
| |
| console.log(_query)
| |
| res = await $.ajax({
| |
| url: API_URL,
| |
| data: {
| |
| action: 'ask',
| |
| format: 'json',
| |
| api_version: 3,
| |
| query: _query
| |
| },
| |
| xhrFields: {
| |
| withCredentials: false
| |
| },
| |
| dataType: 'json'
| |
| })
| |
| offset = offset + 50
| |
| results = results.concat(res.query.results)
| |
| }
| |
| return results
| |
| } catch (error) {
| |
| $('#spinner').hide()
| |
| $('#error').text(error)
| |
| $('#error').show()
| |
| console.log(error)
| |
| }
| |
|
| |
| } | | } |