From 1980b494e45a32924455a37cd26263fe9f291b7f Mon Sep 17 00:00:00 2001 From: Denys Konovalov Date: Thu, 19 Sep 2024 22:03:45 +0200 Subject: [PATCH] refactor charts --- assets/charts/abiturdurchschnitte.js | 86 ++++++ .../{data => charts}/abiturdurchschnitte.json | 0 assets/charts/schuelerzahlen.js | 125 ++++++++ assets/{data => charts}/schuelerzahlen.json | 0 assets/js/echarts-locale.js | 123 ++++++++ assets/js/script.js | 166 +++++----- assets/jsconfig.json | 11 + config.yml | 2 + content/chronikseiten/abiturdurchschnitte.md | 231 +------------- content/chronikseiten/schuelerzahlen.md | 286 +----------------- layouts/kontakt/list.html | 2 +- layouts/schulchronik/single.html | 2 +- layouts/shortcodes/chart.html | 14 + static/admin/config/collections/stats.js | 4 +- 14 files changed, 458 insertions(+), 594 deletions(-) create mode 100644 assets/charts/abiturdurchschnitte.js rename assets/{data => charts}/abiturdurchschnitte.json (100%) create mode 100644 assets/charts/schuelerzahlen.js rename assets/{data => charts}/schuelerzahlen.json (100%) create mode 100644 assets/js/echarts-locale.js create mode 100644 assets/jsconfig.json create mode 100644 layouts/shortcodes/chart.html diff --git a/assets/charts/abiturdurchschnitte.js b/assets/charts/abiturdurchschnitte.js new file mode 100644 index 00000000..3ae14498 --- /dev/null +++ b/assets/charts/abiturdurchschnitte.js @@ -0,0 +1,86 @@ +import * as json from "./abiturdurchschnitte.json"; + +(() => { + const data = json.abiturdurchschnitte; + var dom = document.getElementById("chart-container"); + // @ts-ignore + var chart = echarts.init(dom, null, { + renderer: "canvas", + useDirtyRect: false, + locale: "DE", + }); + const option = { + title: { + text: "Abiturdurchschnitte", + }, + tooltip: { + trigger: "axis", + }, + xAxis: { + data: data.map((item) => item["jahr"]), + }, + yAxis: { + min: 1.0, + inverse: true, + }, + toolbox: { + right: 10, + feature: { + dataZoom: { + yAxisIndex: "none", + }, + restore: {}, + saveAsImage: {}, + }, + }, + dataZoom: [ + { + startValue: "1992", + }, + { + type: "inside", + }, + ], + visualMap: { + top: 50, + right: 10, + precision: 1, + pieces: [ + { + gt: 1.0, + lte: 1.5, + color: "#06511c", + }, + { + gt: 1.5, + lte: 2.0, + color: "#0b9834", + }, + { + gt: 2.0, + lte: 2.5, + color: "#10df4c", + }, + ], + outOfRange: { + color: "#999", + }, + }, + series: { + name: "Abiturdurchschnitt", + type: "line", + data: data.map((item) => item["schnitt"]), + markLine: { + silent: true, + lineStyle: { + color: "#333", + }, + data: [1.25, 1.5, 1.75, 2.0, 2.25].map(n => ({ yAxis: n })), + }, + }, + }; + if (option && typeof option === "object") { + chart.setOption(option); + } + window.addEventListener("resize", chart.resize); +})(); diff --git a/assets/data/abiturdurchschnitte.json b/assets/charts/abiturdurchschnitte.json similarity index 100% rename from assets/data/abiturdurchschnitte.json rename to assets/charts/abiturdurchschnitte.json diff --git a/assets/charts/schuelerzahlen.js b/assets/charts/schuelerzahlen.js new file mode 100644 index 00000000..9a7b6e2b --- /dev/null +++ b/assets/charts/schuelerzahlen.js @@ -0,0 +1,125 @@ +import * as json from "./schuelerzahlen.json"; + +(() => { + const data = json.schuelerzahlen; + var dom = document.getElementById("chart-container"); + // @ts-ignore + var chart = echarts.init(dom, null, { + renderer: "canvas", + useDirtyRect: false, + locale: "DE", + }); + const option = { + title: { + text: "Schülerzahlen", + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + formatter: (params) => { + var lines = params.map( + (p) => `${p.seriesName}: ${p.value}${p.seriesName == "Anteil Mädchen" ? "%" : ""}` + ); + return lines.join("
"); + }, + }, + xAxis: { + data: data.map((item) => item["year"]), + }, + yAxis: [ + { + min: 0, + inverse: false, + }, + { + min: 0, + max: 100, + axisLabel: { + formatter: "{value}%", + }, + }, + ], + toolbox: { + right: 10, + feature: { + dataZoom: { + yAxisIndex: "none", + }, + restore: {}, + saveAsImage: {}, + }, + }, + dataZoom: [ + { + startValue: "1988", + }, + { + type: "inside", + }, + ], + series: [ + { + name: "Jungen", + type: "bar", + stack: "total", + color: "#7099dc", + data: data.map((item) => item["all"] - item["girls"]), + markLine: { + silent: true, + lineStyle: { + color: "#333", + }, + data: [100, 300, 500].map((n) => ({ yAxis: n })), + }, + }, + { + name: "Mädchen", + type: "bar", + color: "#ff6a6a", + stack: "total", + data: data.map((item) => item["girls"]), + markLine: { + silent: true, + lineStyle: { + color: "#333", + }, + data: [100, 300, 500].map((n) => ({ yAxis: n })), + }, + }, + { + name: "Insgesamt", + color: "#98e17f", + type: "line", + data: data.map((item) => item["all"]), + lineStyle: { + normal: { + width: 0, + }, + }, + symbolSize: 0, + markLine: { + silent: true, + lineStyle: { + color: "#333", + }, + data: [100, 300, 500].map((n) => ({ yAxis: n })), + }, + }, + { + name: "Anteil Mädchen", + type: "line", + color: "#4b4b4b", + yAxisIndex: 1, + data: data.map((item) => ((item["girls"] / item["all"]) * 100).toFixed(2)), + }, + ], + }; + + if (option && typeof option === "object") { + chart.setOption(option); + } + + window.addEventListener("resize", chart.resize); +})(); diff --git a/assets/data/schuelerzahlen.json b/assets/charts/schuelerzahlen.json similarity index 100% rename from assets/data/schuelerzahlen.json rename to assets/charts/schuelerzahlen.json diff --git a/assets/js/echarts-locale.js b/assets/js/echarts-locale.js new file mode 100644 index 00000000..9be2b8ff --- /dev/null +++ b/assets/js/echarts-locale.js @@ -0,0 +1,123 @@ +// @ts-ignore +echarts.registerLocale("DE", { + time: { + month: [ + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember", + ], + monthAbbr: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], + dayOfWeek: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], + dayOfWeekAbbr: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], + }, + legend: { + selector: { + all: "Alle", + inverse: "Invertiert", + }, + }, + toolbox: { + brush: { + title: { + rect: "Box Auswahl", + polygon: "Lasso Auswahl", + lineX: "Horizontale Auswahl", + lineY: "Vertikale Auswahl", + keep: "Bereich Auswahl", + clear: "Auswahl zurücksetzen", + }, + }, + dataView: { + title: "Daten Ansicht", + lang: ["Daten Ansicht", "Schließen", "Aktualisieren"], + }, + dataZoom: { + title: { + zoom: "Zoom", + back: "Zoom zurücksetzen", + }, + }, + magicType: { + title: { + line: "Zu Liniendiagramm wechseln", + bar: "Zu Balkendiagramm wechseln", + stack: "Stapel", + tiled: "Kachel", + }, + }, + restore: { + title: "Wiederherstellen", + }, + saveAsImage: { + title: "Als Bild speichern", + lang: ["Rechtsklick zum Speichern des Bildes"], + }, + }, + series: { + typeNames: { + pie: "Tortendiagramm", + bar: "Balkendiagramm", + line: "Liniendiagramm", + scatter: "Streudiagramm", + effectScatter: "Welligkeits-Streudiagramm", + radar: "Radar-Karte", + tree: "Baum", + treemap: "Baumkarte", + boxplot: "Boxplot", + candlestick: "Kerzenständer", + k: "K Liniendiagramm", + heatmap: "Heatmap", + map: "Karte", + parallel: "Parallele Koordinatenkarte", + lines: "Liniendiagramm", + graph: "Beziehungsgrafik", + sankey: "Sankey-Diagramm", + funnel: "Trichterdiagramm", + gauge: "Meßanzeige", + pictorialBar: "Bildlicher Balken", + themeRiver: "Thematische Flusskarte", + sunburst: "Sonnenausbruch", + }, + }, + aria: { + general: { + withTitle: 'Dies ist ein Diagramm über "{title}"', + withoutTitle: "Dies ist ein Diagramm", + }, + series: { + single: { + prefix: "", + withName: " mit Typ {seriesType} namens {seriesName}.", + withoutName: " mit Typ {seriesType}.", + }, + multiple: { + prefix: ". Es besteht aus {seriesCount} Serienzählung.", + withName: " Die Serie {seriesId} ist ein {seriesType} welcher {seriesName} darstellt.", + withoutName: " Die {seriesId}-Reihe ist ein {seriesType}.", + separator: { + middle: "", + end: "", + }, + }, + }, + data: { + allData: "Die Daten sind wie folgt: ", + partialData: "Die ersten {displayCnt} Elemente sind: ", + withName: "die Daten für {name} sind {value}", + withoutName: "{value}", + separator: { + middle: ",", + end: ".", + }, + }, + }, +}); diff --git a/assets/js/script.js b/assets/js/script.js index d052356c..817ef511 100644 --- a/assets/js/script.js +++ b/assets/js/script.js @@ -1,33 +1,33 @@ (($) => { - 'use strict'; + "use strict"; // adapt header to height - function adaptHeight () { - var height = $('.top-header').innerHeight(); - if ($('header').offset().top > 10) { - $('.top-header').addClass('hide'); - $('.navigation').addClass('nav-bg'); - $('.navigation').css('margin-top','-'+height+'px'); + function adaptHeight() { + var height = $(".top-header").innerHeight(); + if ($("header").offset().top > 10) { + $(".top-header").addClass("hide"); + $(".navigation").addClass("nav-bg"); + $(".navigation").css("margin-top", "-" + height + "px"); } else { - $('.top-header').removeClass('hide'); - if ( !$('#top-banner').length) { - $('.navigation').removeClass('nav-bg'); + $(".top-header").removeClass("hide"); + if (!$("#top-banner").length) { + $(".navigation").removeClass("nav-bg"); } - $('.navigation').css('margin-top','-'+0+'px'); + $(".navigation").css("margin-top", "-" + 0 + "px"); } } // load scripts - $(window).on('load', function() { - $('.preloader').fadeOut(100); + $(window).on("load", function () { + $(".preloader").fadeOut(100); adaptHeight(); - if ($('#top-banner').length) { - $('.navigation').addClass('nav-bg'); - $('.hero-section').addClass('hs-banner'); - $('.page-title-section').addClass('pts-banner'); + if ($("#top-banner").length) { + $(".navigation").addClass("nav-bg"); + $(".hero-section").addClass("hs-banner"); + $(".page-title-section").addClass("pts-banner"); } else { - $('.hero-section').removeClass('hs-banner'); - $('.page-title-section').removeClass('pts-banner'); + $(".hero-section").removeClass("hs-banner"); + $(".page-title-section").removeClass("pts-banner"); } }); @@ -35,105 +35,121 @@ $(window).scroll(adaptHeight); // hero slider - $('.hero-slider').slick({ + $(".hero-slider").slick({ autoplay: true, autoplaySpeed: 5000, pauseOnFocus: false, pauseOnHover: true, infinite: true, arrows: true, - prevArrow: '', - nextArrow: '', - dots: true + prevArrow: + '', + nextArrow: + '', + dots: true, }); // venobox popup - $(document).ready(function() { + $(document).ready(function () { + // @ts-ignore new VenoBox({ - selector: '.vb-video', - spinner: 'grid' + selector: ".vb-video", + spinner: "grid", }); + // @ts-ignore new VenoBox({ - selector: '.vb-gallery', + selector: ".vb-gallery", numeration: true, infinigall: true, share: true, - shareStyle: 'block', - spinner: 'grid', + shareStyle: "block", + spinner: "grid", fitView: true, navTouch: true, }); }); // filter - $(document).ready(function() { - if ($('.filter-container').length != 0) { - const shuffleInstance = new Shuffle($('.filter-container'), { - itemSelector: '.filter-item', - sizer: '.filter-sizer', - delimiter: ',', - isCentered: true + $(document).ready(function () { + if ($(".filter-container").length != 0) { + // @ts-ignore + const shuffleInstance = new Shuffle($(".filter-container"), { + itemSelector: ".filter-item", + sizer: ".filter-sizer", + delimiter: ",", + isCentered: true, }); - $('.filter-controls li').on('click', function() { - $('.filter-controls li').removeClass('active'); - $(this).addClass('active'); - shuffleInstance.filter($(this).data('filter')) + $(".filter-controls li").on("click", function () { + $(".filter-controls li").removeClass("active"); + $(this).addClass("active"); + shuffleInstance.filter($(this).data("filter")); }); } }); // counter - $(window).on('scroll', function() { - var oTop; - if ($('.count').length !== 0) { - oTop = $('.count').offset().top - window.innerHeight; + $(window).on("scroll", function () { + var oTop = 0; + if ($(".count").length !== 0) { + oTop = $(".count").offset().top - window.innerHeight; } if ($(window).scrollTop() > oTop) { - $('.count').each(function() { - var $this = $(this), countTo = $this.attr('data-count'); + $(".count").each(function () { + var $this = $(this), + countTo = $this.attr("data-count"); $({ countNum: $this.text() }).animate( { countNum: countTo }, { duration: 1000, - easing: 'swing', - step: function() { return $this.text(Math.floor(this.countNum)) }, - complete: function() { return $this.text(this.countNum) }, - }); + easing: "swing", + step: function () { + return $this.text(Math.floor(this.countNum)); + }, + complete: function () { + return $this.text(this.countNum); + }, + } + ); }); } }); - $(window).on('DOMContentLoaded', function() { - if (window.PagefindUI != undefined) { - new window.PagefindUI({ - element: "#search", - translations: { - placeholder: "Suchen...", - zero_results: "Leider konnten keine Ergebnisse zu [SEARCH_TERM] gefunden werden", - clear_search: "Löschen" - } - }); - - $('#pagefind-search').on('shown.bs.modal', function() { - $('.pagefind-ui__search-input').focus(); - }); - } + $(window).on("DOMContentLoaded", function () { + // @ts-ignore + new PagefindUI({ + element: "#search", + translations: { + placeholder: "Suchen...", + zero_results: "Leider konnten keine Ergebnisse zu [SEARCH_TERM] gefunden werden", + clear_search: "Löschen", + }, + }); + + $("#pagefind-search").on("shown.bs.modal", function () { + $(".pagefind-ui__search-input").focus(); + }); }); // enable matomo analytics - var _paq = window._paq = window._paq || []; + // @ts-ignore + var _paq = (window._paq = window._paq || []); _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.cantorgymnasium.de/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '1']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); + _paq.push(["trackPageView"]); + _paq.push(["enableLinkTracking"]); + (function () { + var u = "https://analytics.cantorgymnasium.de/"; + _paq.push(["setTrackerUrl", u + "matomo.php"]); + _paq.push(["setSiteId", "1"]); + var d = document, + g = d.createElement("script"), + s = d.getElementsByTagName("script")[0]; + g.async = true; + g.src = u + "matomo.js"; + s.parentNode.insertBefore(g, s); })(); + // @ts-ignore new LazyLoad(); - + // @ts-ignore })(jQuery); diff --git a/assets/jsconfig.json b/assets/jsconfig.json new file mode 100644 index 00000000..20055332 --- /dev/null +++ b/assets/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "checkJs": true, + "resolveJsonModule": true, + "lib": ["ES2015", "DOM"], + "baseUrl": ".", + "paths": { + "*": ["*"] + } + } +} diff --git a/config.yml b/config.yml index a3a16752..1cdb6a48 100644 --- a/config.yml +++ b/config.yml @@ -287,3 +287,5 @@ privacy: module: imports: - path: github.com/hugomods/icons/vendors/mdi +build: + noJSConfigInAssets: true diff --git a/content/chronikseiten/abiturdurchschnitte.md b/content/chronikseiten/abiturdurchschnitte.md index e197916c..6d3d220e 100644 --- a/content/chronikseiten/abiturdurchschnitte.md +++ b/content/chronikseiten/abiturdurchschnitte.md @@ -11,233 +11,4 @@ aliases: - /schulchronik/pages/abiturdurchschnitte --- - -
- +{{< chart id="abiturdurchschnitte" >}} diff --git a/content/chronikseiten/schuelerzahlen.md b/content/chronikseiten/schuelerzahlen.md index cbd2cf7a..1190c5a4 100644 --- a/content/chronikseiten/schuelerzahlen.md +++ b/content/chronikseiten/schuelerzahlen.md @@ -5,289 +5,5 @@ type: pages aliases: - /schulchronik/pages/schülerzahlen --- - -
- +{{< chart id="schuelerzahlen" >}} diff --git a/layouts/kontakt/list.html b/layouts/kontakt/list.html index 02640a46..a3c2b9a6 100644 --- a/layouts/kontakt/list.html +++ b/layouts/kontakt/list.html @@ -57,7 +57,7 @@ var marker = L.marker([51.473361, 11.965619]).addTo(map); map.on('click', (e) => { - marker.bindPopup('Georg-Cantor-Gymnasium
Torstraße 13
06110 Halle (Saale)
Route').openPopup(); + marker.bindPopup('Georg-Cantor-Gymnasium
Torstraße 13
06110 Halle (Saale)
Route').openPopup(); }); diff --git a/layouts/schulchronik/single.html b/layouts/schulchronik/single.html index a657139e..f3837d23 100644 --- a/layouts/schulchronik/single.html +++ b/layouts/schulchronik/single.html @@ -27,7 +27,7 @@

{{ .Title }}

- {{ range (resources.Get "data/abiturdurchschnitte.json" | transform.Unmarshal).abiturdurchschnitte }} + {{ range (resources.Get "charts/abiturdurchschnitte.json" | transform.Unmarshal).abiturdurchschnitte }} {{ if eq (string .jahr) $.Title }}Abiturdurchschnitt: {{ .schnitt }}{{ end }} {{ end }}
diff --git a/layouts/shortcodes/chart.html b/layouts/shortcodes/chart.html new file mode 100644 index 00000000..e8c961be --- /dev/null +++ b/layouts/shortcodes/chart.html @@ -0,0 +1,14 @@ +{{ with .Get "id" }} + {{ $chartId := . }} + + + {{ with resources.Get "js/echarts-locale.js" | resources.Minify }} + + {{ end }} + +
+ + {{ with resources.Get (print "charts/" $chartId ".js") | js.Build | resources.Minify }} + + {{ end }} +{{ end }} \ No newline at end of file diff --git a/static/admin/config/collections/stats.js b/static/admin/config/collections/stats.js index e179dab0..a99f32b0 100644 --- a/static/admin/config/collections/stats.js +++ b/static/admin/config/collections/stats.js @@ -12,7 +12,7 @@ const StatsCollection = { { name: "abiturdurchschnitte", label: "Abiturdurchschnitte", - file: "assets/data/abiturdurchschnitte.json", + file: "assets/charts/abiturdurchschnitte.json", fields: [ { name: "abiturdurchschnitte", @@ -43,7 +43,7 @@ const StatsCollection = { { name: "schuelerzahlen", label: "Schülerzahlen", - file: "assets/data/schuelerzahlen.json", + file: "assets/charts/schuelerzahlen.json", fields: [ { name: "schuelerzahlen",