209 lines
7.6 KiB
JavaScript
209 lines
7.6 KiB
JavaScript
/* ============================================================================
|
|
SoftSPM - harmonogram z Akademii Wodociągowca
|
|
Podmienia wiersze tabeli terminów danymi z api/schedule.php.
|
|
Gdy API nie odpowiada albo nie ma pozycji, statyczne wiersze z HTML-a
|
|
zostają nietknięte - strona nigdy nie pokazuje pustej tabeli.
|
|
========================================================================= */
|
|
(function () {
|
|
'use strict';
|
|
|
|
var DICT = {
|
|
pl: {
|
|
dateHead: 'Data',
|
|
webinar: 'Webinar',
|
|
training: 'Szkolenie',
|
|
online: 'Online',
|
|
elearning: 'Online · e-learning',
|
|
onDemand: 'Na żądanie',
|
|
signUp: 'Zapisz się →',
|
|
viewCourse: 'Zobacz kurs →',
|
|
soldOut: 'Brak miejsc',
|
|
soon: 'Zapisy wkrótce',
|
|
note: 'Terminy pobierane na bieżąco z platformy kursowej Akademia Wodociągowca. Zapisy prowadzi Akademia.',
|
|
plateTitle: 'Terminy i kursy otwarte',
|
|
heading: 'Najbliższe szkolenia i webinaria',
|
|
intro: 'Poniżej pozycje otwarte w tej chwili na naszej platformie kursowej. Zapisy prowadzi Akademia Wodociągowca.',
|
|
locale: 'pl-PL',
|
|
levels: { BASIC: 'podstawowy', INTERMEDIATE: 'średni', ADVANCED: 'zaawansowany' }
|
|
},
|
|
en: {
|
|
dateHead: 'Date',
|
|
webinar: 'Webinar',
|
|
training: 'Training',
|
|
online: 'Online',
|
|
elearning: 'Online · e-learning',
|
|
onDemand: 'On demand',
|
|
signUp: 'Sign up →',
|
|
viewCourse: 'View course →',
|
|
soldOut: 'Fully booked',
|
|
soon: 'Registration soon',
|
|
note: 'Dates are pulled live from our Akademia Wodociagowca course platform, which also handles registration.',
|
|
plateTitle: 'Open dates and courses',
|
|
heading: 'Upcoming training and webinars',
|
|
intro: 'Everything currently open on our course platform. Registration is handled by Akademia Wodociagowca.',
|
|
locale: 'en-GB',
|
|
levels: { BASIC: 'basic', INTERMEDIATE: 'intermediate', ADVANCED: 'advanced' }
|
|
}
|
|
};
|
|
|
|
var lang = (document.documentElement.getAttribute('lang') || 'pl').slice(0, 2).toLowerCase();
|
|
var t = DICT[lang] || DICT.pl;
|
|
|
|
function el(tag, className, text) {
|
|
var node = document.createElement(tag);
|
|
if (className) { node.className = className; }
|
|
if (text !== undefined && text !== null) { node.textContent = text; }
|
|
return node;
|
|
}
|
|
|
|
function formatDate(iso, timezone) {
|
|
var date = new Date(iso);
|
|
if (isNaN(date.getTime())) { return null; }
|
|
var zone = timezone || 'Europe/Warsaw';
|
|
var opts = { day: '2-digit', month: '2-digit', year: 'numeric', timeZone: zone };
|
|
var timeOpts = { hour: '2-digit', minute: '2-digit', timeZone: zone };
|
|
try {
|
|
return {
|
|
day: new Intl.DateTimeFormat(t.locale, opts).format(date),
|
|
hour: new Intl.DateTimeFormat(t.locale, timeOpts).format(date)
|
|
};
|
|
} catch (e) {
|
|
// Nieznana strefa albo stary silnik - pokazujemy datę bez strefy.
|
|
return { day: date.toLocaleDateString(t.locale), hour: date.toLocaleTimeString(t.locale) };
|
|
}
|
|
}
|
|
|
|
function actionCell(item) {
|
|
var cell = el('td', 's-act');
|
|
if (item.kind === 'webinar' && item.soldOut) {
|
|
cell.appendChild(el('span', 'text-muted', t.soldOut));
|
|
return cell;
|
|
}
|
|
if (item.kind === 'webinar' && item.open === false) {
|
|
cell.appendChild(el('span', 'text-muted', t.soon));
|
|
return cell;
|
|
}
|
|
if (!item.url) {
|
|
cell.appendChild(el('span', 'text-muted', item.kind === 'webinar' ? t.soon : ''));
|
|
return cell;
|
|
}
|
|
var link = el('a', 'sign', item.kind === 'webinar' ? t.signUp : t.viewCourse);
|
|
link.href = item.url;
|
|
link.target = '_blank';
|
|
link.rel = 'noopener';
|
|
cell.appendChild(link);
|
|
return cell;
|
|
}
|
|
|
|
function buildRow(item) {
|
|
var row = document.createElement('tr');
|
|
|
|
var date = el('td', 's-date');
|
|
if (item.kind === 'webinar') {
|
|
var parts = formatDate(item.startsAt, item.timezone);
|
|
if (parts) {
|
|
date.appendChild(document.createTextNode(parts.day));
|
|
date.appendChild(el('span', 's-hour', parts.hour));
|
|
} else {
|
|
date.appendChild(el('span', 'tag tag-soon', t.onDemand));
|
|
}
|
|
} else {
|
|
date.appendChild(el('span', 'tag tag-soon', t.onDemand));
|
|
}
|
|
row.appendChild(date);
|
|
|
|
// textContent, nie innerHTML - tytuły przychodzą z innego systemu.
|
|
row.appendChild(el('td', 's-topic', item.title));
|
|
|
|
var form = el('td', 's-form');
|
|
form.appendChild(el(
|
|
'span',
|
|
item.kind === 'webinar' ? 'tag tag-outline' : 'tag tag-accent',
|
|
item.kind === 'webinar' ? t.webinar : t.training
|
|
));
|
|
row.appendChild(form);
|
|
|
|
var place = item.kind === 'webinar' ? t.online : t.elearning;
|
|
if (item.kind === 'course' && item.level && t.levels[item.level]) {
|
|
place = t.elearning + ' · ' + t.levels[item.level];
|
|
}
|
|
row.appendChild(el('td', 's-place', place));
|
|
|
|
row.appendChild(actionCell(item));
|
|
return row;
|
|
}
|
|
|
|
function render(table, items) {
|
|
var body = table.querySelector('tbody');
|
|
if (!body) { return; }
|
|
|
|
var fresh = document.createDocumentFragment();
|
|
for (var i = 0; i < items.length; i++) {
|
|
fresh.appendChild(buildRow(items[i]));
|
|
}
|
|
body.innerHTML = '';
|
|
body.appendChild(fresh);
|
|
|
|
// Mamy realne daty, więc nagłówek kolumny wraca z "Termin" na "Data".
|
|
var head = table.querySelector('[data-schedule-datehead]');
|
|
if (head) { head.textContent = t.dateHead; }
|
|
|
|
// Przy realnych terminach nagłówki mówiące "ustalamy terminy" przestają
|
|
// być prawdziwe, więc lecą razem z wierszami.
|
|
var section = table.closest ? table.closest('section') : null;
|
|
if (section) {
|
|
var heading = section.querySelector('[data-schedule-heading]');
|
|
if (heading) { heading.textContent = t.heading; }
|
|
var intro = section.querySelector('[data-schedule-intro]');
|
|
if (intro) { intro.textContent = t.intro; }
|
|
}
|
|
|
|
var plate = table.closest ? table.closest('.plate') : null;
|
|
var plateTitle = plate ? plate.querySelector('[data-schedule-title]') : null;
|
|
if (plateTitle) { plateTitle.textContent = t.plateTitle; }
|
|
|
|
var note = plate ? plate.querySelector('[data-schedule-note]') : null;
|
|
if (note) {
|
|
note.textContent = t.note + ' ';
|
|
var link = el('a', null, 'akademiawodociagowca.pl');
|
|
link.href = 'https://akademiawodociagowca.pl/';
|
|
link.target = '_blank';
|
|
link.rel = 'noopener';
|
|
note.appendChild(link);
|
|
}
|
|
table.setAttribute('data-schedule-state', 'live');
|
|
}
|
|
|
|
function boot() {
|
|
var tables = document.querySelectorAll('table[data-schedule]');
|
|
if (!tables.length) { return; }
|
|
|
|
var limit = 0;
|
|
for (var i = 0; i < tables.length; i++) {
|
|
limit = Math.max(limit, parseInt(tables[i].getAttribute('data-schedule-limit'), 10) || 12);
|
|
}
|
|
|
|
fetch('api/schedule.php?limit=' + limit, {
|
|
credentials: 'same-origin',
|
|
headers: { 'Accept': 'application/json' }
|
|
})
|
|
.then(function (response) { return response.json(); })
|
|
.then(function (data) {
|
|
if (!data || data.source !== 'api' || !data.items || !data.items.length) { return; }
|
|
for (var i = 0; i < tables.length; i++) {
|
|
var own = parseInt(tables[i].getAttribute('data-schedule-limit'), 10) || data.items.length;
|
|
render(tables[i], data.items.slice(0, own));
|
|
}
|
|
})
|
|
.catch(function () {
|
|
// Cisza jest właściwą reakcją: w tabeli zostają statyczne wiersze.
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', boot);
|
|
} else {
|
|
boot();
|
|
}
|
|
})();
|