From c409e04db91589682dca2231c282ce6441b0cef5 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 24 Jul 2023 16:16:45 +0200
Subject: [PATCH] Add Events block on index.

---
 sass/_calendar.scss                           | 490 ++++++++++++++++++
 sass/style.scss                               |   1 +
 static/calendar.js                            |  12 +
 .../blocks/calendar/calendar_big.html         | 110 ++++
 .../blocks/calendar/calendar_compact.html     |  96 ++++
 templates/frontpage/blocks/events.html        |  17 +
 typescript/Makefile                           |   3 +
 typescript/calendar.ts                        |  12 +
 8 files changed, 741 insertions(+)
 create mode 100644 sass/_calendar.scss
 create mode 100644 static/calendar.js
 create mode 100644 templates/frontpage/blocks/calendar/calendar_big.html
 create mode 100644 templates/frontpage/blocks/calendar/calendar_compact.html
 create mode 100644 typescript/Makefile
 create mode 100644 typescript/calendar.ts

diff --git a/sass/_calendar.scss b/sass/_calendar.scss
new file mode 100644
index 00000000..6ea3e0bb
--- /dev/null
+++ b/sass/_calendar.scss
@@ -0,0 +1,490 @@
+// Copyright (c) 2023 Wikiki (https://codepen.io/wikiki/pen/KvqKzK)
+
+@function powerNumber($number, $exp) {
+  $value: 1;
+  @if $exp > 0 {
+    @for $i from 1 through $exp {
+      $value: $value * $number;
+    }
+  } @else if $exp < 0 {
+    @for $i from 1 through -$exp {
+      $value: $value / $number;
+    }
+  }
+  @return $value;
+}
+@function colorLuminance($color) {
+  $color-rgb: (
+    "red": red($color),
+    "green": green($color),
+    "blue": blue($color),
+  );
+  @each $name, $value in $color-rgb {
+    $adjusted: 0;
+    $value: $value / 255;
+    @if $value < 0.03928 {
+      $value: $value / 12.92;
+    } @else {
+      $value: ($value + 0.055) / 1.055;
+      $value: powerNumber($value, 2);
+    }
+    $color-rgb: map-merge(
+      $color-rgb,
+      (
+        $name: $value,
+      )
+    );
+  }
+  @return (map-get($color-rgb, "red") * 0.2126) +
+    (map-get($color-rgb, "green") * 0.7152) +
+    (map-get($color-rgb, "blue") * 0.0722);
+}
+@function findColorInvert($color) {
+  @if (colorLuminance($color) > 0.55) {
+    @return rgba(#000, 0.7);
+  } @else {
+    @return #fff;
+  }
+
+  ////////////////////////////////////////////////
+  ////////////////////////////////////////////////
+  // 1. Initial variables
+
+  // Colors
+}
+$black: hsl(0, 0%, 4%) !default;
+$black-bis: hsl(0, 0%, 7%) !default;
+$black-ter: hsl(0, 0%, 14%) !default;
+
+$grey-darker: hsl(0, 0%, 21%) !default;
+$grey-dark: hsl(0, 0%, 29%) !default;
+$grey: hsl(0, 0%, 48%) !default;
+$grey-light: hsl(0, 0%, 71%) !default;
+$grey-lighter: hsl(0, 0%, 86%) !default;
+
+$white-ter: hsl(0, 0%, 96%) !default;
+$white-bis: hsl(0, 0%, 98%) !default;
+$white: hsl(0, 0%, 100%) !default;
+
+$orange: hsl(14, 100%, 53%) !default;
+$yellow: hsl(48, 100%, 67%) !default;
+$green: hsl(141, 71%, 48%) !default;
+$turquoise: hsl(171, 100%, 41%) !default;
+$blue: hsl(217, 71%, 53%) !default;
+$purple: hsl(271, 100%, 71%) !default;
+$red: hsl(348, 100%, 61%) !default;
+
+// Typography
+$family-sans-serif:
+  BlinkMacSystemFont,
+  -apple-system,
+  "Segoe UI",
+  "Roboto",
+  "Oxygen",
+  "Ubuntu",
+  "Cantarell",
+  "Fira Sans",
+  "Droid Sans",
+  "Helvetica Neue",
+  "Helvetica",
+  "Arial",
+  sans-serif !default;
+$family-monospace: monospace !default;
+$render-mode: optimizeLegibility !default;
+
+$size-1: 3rem !default;
+$size-2: 2.5rem !default;
+$size-3: 2rem !default;
+$size-4: 1.5rem !default;
+$size-5: 1.25rem !default;
+$size-6: 1rem !default;
+$size-7: 0.75rem !default;
+
+$weight-light: 300 !default;
+$weight-normal: 400 !default;
+$weight-semibold: 500 !default;
+$weight-bold: 700 !default;
+
+// Body
+$body-background: #fff !default;
+$body-size: 16px !default;
+
+// Responsiveness
+// 960, 1152, and 1344 have been chosen because they are divisible by both 12 and 16
+$tablet: 769px !default;
+// 960px container + 40px
+$desktop: 1000px !default;
+// 1152px container + 40
+$widescreen: 1192px !default;
+// 1344px container + 40
+$fullhd: 1384px !default;
+
+// Miscellaneous
+$easing: ease-out !default;
+$radius-small: 2px !default;
+$radius: 3px !default;
+$radius-large: 5px !default;
+$speed: 86ms !default;
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+// 2. Primary colors
+
+$primary: $teckids-orange;
+
+$info: $teckids-blue;
+$success: map-get($project-colors, hack-n-fun);
+$warning: map-get($project-colors, schul-frei);
+$danger: map-get($project-colors, indiedact);
+
+$light: $white-ter !default;
+$dark: $grey-darker !default;
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+// 3. Applied variables
+
+// Invert colors
+
+$primary-invert: findColorInvert($primary);
+$info-invert: findColorInvert($info);
+$success-invert: findColorInvert($success);
+$warning-invert: findColorInvert($warning);
+$danger-invert: findColorInvert($danger);
+$light-invert: $dark;
+$dark-invert: $light;
+
+// General colors
+$background: $white-ter !default;
+
+$border: $grey-lighter !default;
+$border-hover: $grey-light !default;
+
+// Text colors
+$text: $grey-dark !default;
+$text-invert: findColorInvert($text) !default;
+$text-light: $grey !default;
+$text-strong: $grey-darker !default;
+
+// Code colors
+$code: $red !default;
+$code-background: $background !default;
+
+$pre: $text !default;
+$pre-background: $background !default;
+
+// Link colors
+$link: $primary !default;
+$link-invert: $primary-invert !default;
+$link-visited: $purple !default;
+
+$link-hover: $grey-darker !default;
+$link-hover-border: $grey-light !default;
+
+$link-focus: $grey-darker !default;
+$link-focus-border: $primary !default;
+
+$link-active: $grey-darker !default;
+$link-active-border: $grey-dark !default;
+
+// Typography
+$family-primary: $family-sans-serif !default;
+$family-code: $family-monospace !default;
+
+$size-small: $size-7 !default;
+$size-normal: $size-6 !default;
+$size-medium: $size-5 !default;
+$size-large: $size-4 !default;
+
+////////////////////////////////////////////////
+////////////////////////////////////////////////
+// 4. Lists and maps
+
+$colors: (
+  "white": (
+    $white,
+    $black,
+  ),
+  "black": (
+    $black,
+    $white,
+  ),
+  "light": (
+    $light,
+    $light-invert,
+  ),
+  "dark": (
+    $dark,
+    $dark-invert,
+  ),
+  "primary": (
+    $primary,
+    $primary-invert,
+  ),
+  "info": (
+    $info,
+    $info-invert,
+  ),
+  "success": (
+    $success,
+    $success-invert,
+  ),
+  "warning": (
+    $warning,
+    $warning-invert,
+  ),
+  "danger": (
+    $danger,
+    $danger-invert,
+  ),
+);
+
+$sizes: $size-1 $size-2 $size-3 $size-4 $size-5 $size-6 $size-7 !default;
+
+$calendar-border: 0.1rem solid $grey-lighter !default;
+$calendar-border-radius: $radius-small !default;
+
+.calendar {
+  border: $calendar-border;
+  border-radius: $calendar-border-radius;
+  display: block;
+  min-width: 28rem;
+  text-align: center;
+  .calendar-nav {
+    -webkit-align-items: center;
+    align-items: center;
+    background: $primary;
+    color: $white;
+    border-top-left-radius: $radius-small;
+    border-top-right-radius: $radius-small;
+    display: flex;
+    display: -ms-flexbox;
+    display: -webkit-flex;
+    -ms-flex-align: center;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    align-items: center;
+    -webkit-box-pack: justify;
+    -ms-flex-pack: justify;
+    justify-content: space-between;
+    font-size: $size-4;
+    padding: 0.5rem;
+    .calendar-nav-left,
+    .calendar-nav-right {
+      -ms-flex-preferred-size: auto;
+      flex-basis: auto;
+      -webkit-box-flex: 0;
+      -ms-flex-positive: 0;
+      flex-grow: 0;
+      -ms-flex-negative: 0;
+      flex-shrink: 0;
+      .button {
+        text-decoration: none;
+        color: $white;
+        &:hover {
+          background: transparent;
+          color: $grey-lighter;
+        }
+      }
+    }
+    .calendar-nav-left {
+      -webkit-box-align: center;
+      -ms-flex-align: center;
+      align-items: center;
+      -webkit-box-pack: start;
+      -ms-flex-pack: start;
+      justify-content: flex-start;
+    }
+    .calendar-nav-right {
+      -webkit-box-align: center;
+      -ms-flex-align: center;
+      align-items: center;
+      -webkit-box-pack: end;
+      -ms-flex-pack: end;
+      justify-content: flex-end;
+    }
+  }
+  .calendar-header,
+  .calendar-body {
+    display: flex;
+    display: -ms-flexbox;
+    display: -webkit-flex;
+    -ms-flex-pack: center;
+    -webkit-flex-wrap: wrap;
+    -ms-flex-wrap: wrap;
+    flex-wrap: wrap;
+    -webkit-justify-content: center;
+    justify-content: center;
+    padding: 0.2rem 0;
+  }
+  .calendar-header .calendar-date,
+  .calendar-body .calendar-date {
+    -webkit-flex: 0 0 14.28%;
+    -ms-flex: 0 0 14.28%;
+    flex: 0 0 14.28%;
+    max-width: 14.28%;
+  }
+  .calendar-header {
+    background: darken($primary, 5%);
+    color: $white;
+    font-size: $size-6;
+  }
+  .calendar-body {
+    color: $grey;
+  }
+
+  .calendar-date {
+    border: 0;
+    padding: 0.4rem;
+    .date-item {
+      -webkit-appearance: none;
+      -moz-appearance: none;
+      appearance: none;
+      background: transparent;
+      border: 0.1rem solid transparent;
+      border-radius: 100%;
+      color: $text;
+      cursor: pointer;
+      height: 2.8rem;
+      line-height: 2rem;
+      outline: none;
+      padding: 0.3rem;
+      position: relative;
+      text-align: center;
+      text-decoration: none;
+      transition: all 0.2s ease;
+      vertical-align: middle;
+      white-space: nowrap;
+      width: 2.8rem;
+      &.is-today {
+        border-color: $primary;
+        color: $primary;
+      }
+      &.is-active {
+        background: $primary;
+        border-color: $primary;
+        color: #fff;
+      }
+      &.is-highlighted {
+        background: findLightColor($primary);
+      }
+      &:focus {
+        background: $primary;
+        border-color: $primary;
+        color: $white;
+        text-decoration: none;
+      }
+      &:hover {
+        background: findLightColor($primary);
+        border-color: $primary;
+        color: $grey;
+        text-decoration: none;
+      }
+    }
+    &.is-disabled {
+      .date-item,
+      .calendar-event {
+        cursor: default;
+        opacity: 0.25;
+        pointer-events: none;
+      }
+    }
+  }
+  .calendar-range {
+    position: relative;
+    &::before {
+      background: lighten($primary, 50%);
+      content: "";
+      height: 2.8rem;
+      left: 0;
+      position: absolute;
+      right: 0;
+      top: 50%;
+      -webkit-transform: translateY(-50%);
+      -ms-transform: translateY(-50%);
+      transform: translateY(-50%);
+    }
+    &.range-start::before {
+      left: 50%;
+    }
+    &.range-end::before {
+      right: 50%;
+    }
+    .date-item {
+      color: $primary;
+    }
+  }
+  &.is-calendar-large {
+    .calendar-body {
+      padding: 0;
+      .calendar-date {
+        border-bottom: $calendar-border;
+        border-right: $calendar-border;
+        display: flex;
+        display: -ms-flexbox;
+        display: -webkit-flex;
+        -webkit-flex-direction: column;
+        -ms-flex-direction: column;
+        flex-direction: column;
+        height: 11rem;
+        padding: 0;
+        &:nth-child(7n) {
+          border-right: 0;
+        }
+        false {
+          border-bottom: 0;
+        }
+      }
+    }
+    .date-item {
+      -webkit-align-self: flex-end;
+      align-self: flex-end;
+      -ms-flex-item-align: end;
+      height: 2.8rem;
+      margin-right: 0.5rem;
+      margin-top: 0.5rem;
+    }
+    .calendar-range {
+      &::before {
+        top: 1.9rem;
+      }
+      &.range-start::before {
+        left: auto;
+        width: 1.9rem;
+      }
+      &.range-end::before {
+        right: 1.9rem;
+      }
+    }
+    .calendar-events {
+      -webkit-flex-grow: 1;
+      flex-grow: 1;
+      -ms-flex-positive: 1;
+      line-height: 1;
+      overflow-y: auto;
+      padding: 0.5rem;
+    }
+    .calendar-event {
+      background-color: $info;
+      border-radius: $radius-small;
+      color: $white;
+      display: block;
+      font-size: 1rem;
+      margin: 0.2rem auto;
+      overflow: hidden;
+      padding: 0.3rem 0.4rem;
+      text-align: left;
+      text-overflow: ellipsis;
+      vertical-align: baseline;
+      white-space: nowrap;
+      @each $name, $pair in $colors {
+        $color: nth($pair, 1);
+        $color-invert: nth($pair, 2);
+        &.is-#{$name} {
+          background-color: $color;
+          color: $color-invert;
+        }
+      }
+    }
+  }
+}
diff --git a/sass/style.scss b/sass/style.scss
index 7dee0d1d..8689be9d 100644
--- a/sass/style.scss
+++ b/sass/style.scss
@@ -8,3 +8,4 @@ $family-sans-serif: "Roboto", sans-serif;
 
 @import "./_menu.scss";
 @import "./_content.scss";
+@import "./_calendar";
diff --git a/static/calendar.js b/static/calendar.js
new file mode 100644
index 00000000..dd19ee25
--- /dev/null
+++ b/static/calendar.js
@@ -0,0 +1,12 @@
+document.addEventListener("DOMContentLoaded", function () {
+    var month = document.getElementById("year_and_month");
+    if (month == null) {
+        return;
+    }
+    var date = new Date();
+    month.innerHTML =
+        "" +
+            date.toLocaleString("de-de", { month: "long" }) +
+            " " +
+            date.getFullYear();
+});
diff --git a/templates/frontpage/blocks/calendar/calendar_big.html b/templates/frontpage/blocks/calendar/calendar_big.html
new file mode 100644
index 00000000..b5824031
--- /dev/null
+++ b/templates/frontpage/blocks/calendar/calendar_big.html
@@ -0,0 +1,110 @@
+<!-- Copyright (c) 2023 Wikiki (https://codepen.io/wikiki/pen/KvqKzK) -->
+
+<div class="calendar is-calendar-large">
+  <script src="/calendar.js"></script>
+  <div class="calendar-nav">
+    <div class="calendar-nav-left">
+      <button class="button is-link">
+        <i class="fa fa-chevron-left"></i>
+      </button>
+    </div>
+    <div>March 2017</div>
+    <div class="calendar-nav-right">
+      <button class="button is-link">
+        <i class="fa fa-chevron-right"></i>
+      </button>
+    </div>
+  </div>
+  <div class="calendar-container">
+    <!-- Days of the week -->
+    <div class="calendar-header">
+      <div class="calendar-date">Sun</div>
+      <div class="calendar-date">Mon</div>
+      <div class="calendar-date">Tue</div>
+      <div class="calendar-date">Wed</div>
+      <div class="calendar-date">Thu</div>
+      <div class="calendar-date">Fri</div>
+      <div class="calendar-date">Sat</div>
+    </div>
+    <div class="calendar-body">
+      <div class="calendar-date disabled">
+        <button class="date-item">26</button>
+      </div>
+      <div class="calendar-date disabled">
+        <button class="date-item">27</button>
+        <div class="calendar-events">
+          <a class="calendar-event">Default event</a>
+        </div>
+      </div>
+      <div class="calendar-date disabled">
+        <button class="date-item">28</button>
+      </div>
+      <div class="calendar-date"><button class="date-item">1</button></div>
+      <div class="calendar-date"><button class="date-item">2</button></div>
+      <div class="calendar-date"><button class="date-item">3</button></div>
+      <div class="calendar-date tooltip" data-tooltip="Today">
+        <button class="date-item date-today">4</button>
+      </div>
+      <div class="calendar-date">
+        <button class="date-item" disabled="">5</button>
+      </div>
+      <div class="calendar-date"><button class="date-item">6</button></div>
+      <div class="calendar-date"><button class="date-item">7</button></div>
+      <div class="calendar-date tooltip" data-tooltip="You have appointments">
+        <button class="date-item badge">8</button>
+        <div class="calendar-events">
+          <a class="calendar-event is-primary">Primary event</a>
+          <a class="calendar-event is-warning">Warning event</a>
+          <a class="calendar-event is-danger">Danger event</a>
+        </div>
+      </div>
+      <div class="calendar-date"><button class="date-item">9</button></div>
+      <div class="calendar-date"><button class="date-item">10</button></div>
+      <div class="calendar-date"><button class="date-item">11</button></div>
+      <div class="calendar-date">
+        <button class="date-item">12</button>
+        <div class="calendar-events">
+          <a class="calendar-event">Default event</a>
+        </div>
+      </div>
+      <div class="calendar-date"><button class="date-item">13</button></div>
+      <div class="calendar-date"><button class="date-item">14</button></div>
+      <div class="calendar-date"><button class="date-item">15</button></div>
+      <div class="calendar-date calendar-range range-start">
+        <button class="date-item is-active">16</button>
+      </div>
+      <div class="calendar-date calendar-range">
+        <button class="date-item">17</button>
+      </div>
+      <div class="calendar-date calendar-range">
+        <button class="date-item">18</button>
+      </div>
+      <div class="calendar-date calendar-range">
+        <button class="date-item">19</button>
+      </div>
+      <div class="calendar-date calendar-range range-end">
+        <button class="date-item is-active">20</button>
+        <div class="calendar-events">
+          <a class="calendar-event is-success">Success event</a>
+        </div>
+      </div>
+      <div class="calendar-date"><button class="date-item">21</button></div>
+      <div class="calendar-date"><button class="date-item">22</button></div>
+      <div class="calendar-date"><button class="date-item">23</button></div>
+      <div class="calendar-date"><button class="date-item">24</button></div>
+      <div class="calendar-date"><button class="date-item">25</button></div>
+      <div class="calendar-date"><button class="date-item">26</button></div>
+      <div class="calendar-date"><button class="date-item">27</button></div>
+      <div class="calendar-date"><button class="date-item">28</button></div>
+      <div class="calendar-date"><button class="date-item">29</button></div>
+      <div class="calendar-date"><button class="date-item">30</button></div>
+      <div class="calendar-date"><button class="date-item">31</button></div>
+      <div class="calendar-date disabled">
+        <button class="date-item">1</button>
+        <div class="calendar-events">
+          <a class="calendar-event">Second default event</a>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/templates/frontpage/blocks/calendar/calendar_compact.html b/templates/frontpage/blocks/calendar/calendar_compact.html
new file mode 100644
index 00000000..648c9c69
--- /dev/null
+++ b/templates/frontpage/blocks/calendar/calendar_compact.html
@@ -0,0 +1,96 @@
+<!-- Copyright (c) 2023 Wikiki (https://codepen.io/wikiki/pen/KvqKzK) -->
+
+<script src="/calendar.js"></script>
+<div class="column is-4">
+  <div class="calendar">
+    <div class="calendar-nav">
+      <div class="calendar-nav-left">
+        <button class="button is-link">
+          <i class="fa fa-chevron-left"></i>
+        </button>
+      </div>
+      <div id="year_and_month"></div>
+      <div class="calendar-nav-right">
+        <button class="button is-link">
+          <i class="fa fa-chevron-right"></i>
+        </button>
+      </div>
+    </div>
+    <div class="calendar-container">
+      <!-- Header with Day titles -->
+      <div class="calendar-header">
+        <div class="calendar-date">Mon</div>
+        <div class="calendar-date">Die</div>
+        <div class="calendar-date">Mit</div>
+        <div class="calendar-date">Don</div>
+        <div class="calendar-date">Fre</div>
+        <div class="calendar-date">Sam</div>
+        <div class="calendar-date">Son</div>
+      </div>
+
+      <div class="calendar-body">
+        <!-- Every item is a date -->
+
+        <div class="calendar-date is-disabled">
+          <button class="date-item">26</button>
+        </div>
+        <div class="calendar-date is-disabled">
+          <button class="date-item">27</button>
+        </div>
+        <div class="calendar-date is-disabled">
+          <button class="date-item">28</button>
+        </div>
+        <div class="calendar-date"><button class="date-item">1</button></div>
+        <div class="calendar-date"><button class="date-item">2</button></div>
+        <div class="calendar-date"><button class="date-item">3</button></div>
+        <div class="calendar-date">
+          <button class="date-item is-today">4</button>
+        </div>
+        <div class="calendar-date">
+          <button class="date-item" disabled="">5</button>
+        </div>
+        <div class="calendar-date"><button class="date-item">6</button></div>
+        <div class="calendar-date"><button class="date-item">7</button></div>
+        <div class="calendar-date">
+          <button class="date-item badge is-highlighted">8</button>
+        </div>
+        <div class="calendar-date"><button class="date-item">9</button></div>
+        <div class="calendar-date"><button class="date-item">10</button></div>
+        <div class="calendar-date"><button class="date-item">11</button></div>
+        <div class="calendar-date"><button class="date-item">12</button></div>
+        <div class="calendar-date"><button class="date-item">13</button></div>
+        <div class="calendar-date"><button class="date-item">14</button></div>
+        <div class="calendar-date"><button class="date-item">15</button></div>
+        <div class="calendar-date calendar-range range-start">
+          <button class="date-item is-highlighted">16</button>
+        </div>
+        <div class="calendar-date calendar-range">
+          <button class="date-item">17</button>
+        </div>
+        <div class="calendar-date calendar-range">
+          <button class="date-item">18</button>
+        </div>
+        <div class="calendar-date calendar-range">
+          <button class="date-item">19</button>
+        </div>
+        <div class="calendar-date calendar-range range-end is-highlighted">
+          <button class="date-item is-highlighted">20</button>
+        </div>
+        <div class="calendar-date"><button class="date-item">21</button></div>
+        <div class="calendar-date"><button class="date-item">22</button></div>
+        <div class="calendar-date"><button class="date-item">23</button></div>
+        <div class="calendar-date"><button class="date-item">24</button></div>
+        <div class="calendar-date"><button class="date-item">25</button></div>
+        <div class="calendar-date"><button class="date-item">26</button></div>
+        <div class="calendar-date"><button class="date-item">27</button></div>
+        <div class="calendar-date"><button class="date-item">28</button></div>
+        <div class="calendar-date"><button class="date-item">29</button></div>
+        <div class="calendar-date"><button class="date-item">30</button></div>
+        <div class="calendar-date"><button class="date-item">31</button></div>
+        <div class="calendar-date is-disabled">
+          <button class="date-item">1</button>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/templates/frontpage/blocks/events.html b/templates/frontpage/blocks/events.html
index e69de29b..38324a78 100644
--- a/templates/frontpage/blocks/events.html
+++ b/templates/frontpage/blocks/events.html
@@ -0,0 +1,17 @@
+<section class="section">
+  <div class="container">
+    <div class="columns is-centered is-half">
+      <h1 class="title is-1">Events</h1>
+    </div>
+    <div class="columns">
+      <div class="column is-two-thirds">
+        <div class="notification">Event 1</div>
+        <div class="notification">Event 2</div>
+        <div class="notification">Event 3</div>
+      </div>
+      <aside>
+        {% include "frontpage/blocks/calendar/calendar_compact.html" %}
+      </aside>
+    </div>
+  </div>
+</section>
diff --git a/typescript/Makefile b/typescript/Makefile
new file mode 100644
index 00000000..3583df36
--- /dev/null
+++ b/typescript/Makefile
@@ -0,0 +1,3 @@
+
+calendar:
+	tsc --outFile ../static/calendar.js ./calendar.ts
diff --git a/typescript/calendar.ts b/typescript/calendar.ts
new file mode 100644
index 00000000..8febfefc
--- /dev/null
+++ b/typescript/calendar.ts
@@ -0,0 +1,12 @@
+document.addEventListener("DOMContentLoaded", () => {
+  let month = document.getElementById("year_and_month");
+  if (month == null) {
+    return;
+  }
+  let date = new Date();
+  month.innerHTML =
+    "" +
+    date.toLocaleString("de-de", { month: "long" }) +
+    " " +
+    date.getFullYear();
+});
-- 
GitLab