Remove unused old assets

This commit is contained in:
Alice Gaudon 2021-11-20 22:26:22 +01:00
parent 569a50e43a
commit 257a407faf
20 changed files with 0 additions and 1330 deletions

View File

@ -20,7 +20,6 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5", "@babel/preset-env": "^7.9.5",
"@fortawesome/fontawesome-free": "^5.14.0",
"@tsconfig/svelte": "^2.0.1", "@tsconfig/svelte": "^2.0.1",
"@types/config": "^0.0.40", "@types/config": "^0.0.40",
"@types/express": "^4.17.6", "@types/express": "^4.17.6",

0
src/assets/sass/.gitkeep Normal file
View File

View File

@ -1,81 +0,0 @@
/* vietnamese */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Nunito Sans Light'), local('NunitoSans-Light'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8WAc5iU1EQVg.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Nunito Sans Light'), local('NunitoSans-Light'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8WAc5jU1EQVg.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Nunito Sans Light'), local('NunitoSans-Light'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8WAc5tU1E.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Nunito Sans Regular'), local('NunitoSans-Regular'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe0qMImSLYBIv1o4X1M8cceyI9tScg.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Nunito Sans Regular'), local('NunitoSans-Regular'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe0qMImSLYBIv1o4X1M8ccezI9tScg.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Nunito Sans Regular'), local('NunitoSans-Regular'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe0qMImSLYBIv1o4X1M8cce9I9s.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('Nunito Sans Bold'), local('NunitoSans-Bold'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8GBs5iU1EQVg.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('Nunito Sans Bold'), local('NunitoSans-Bold'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8GBs5jU1EQVg.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('Nunito Sans Bold'), local('NunitoSans-Bold'), url(https://fonts.gstatic.com/s/nunitosans/v5/pe03MImSLYBIv1o4X1M8cc8GBs5tU1E.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@ -1,33 +0,0 @@
$primary: darken(#242b33, 2%);
$primaryForeground: #f0f0f0;
$secondary: lighten(#00766c, 10%);
$secondaryForeground: $primaryForeground;
$backgroundColor: darken($primary, 4%);
$defaultTextColor: #ffffff;
$headerBackground: transparent;
$headerContainer: true;
$footerBackground: transparent;
$panelBackground: darken($backgroundColor, 3.2%);
$inputBackground: darken($panelBackground, 4%);
$info: #4499ff;
$infoText: darken($info, 42%);
$infoColor: desaturate($infoText, 50%);
$success: #55ff55;
$successText: darken($success, 45%);
$successColor: desaturate($successText, 50%);
$warning: #ffcc00;
$warningText: darken($warning, 30%);
$warningColor: desaturate($warningText, 50%);
$error: #ff0000;
$errorText: darken($error, 30%);
$errorColor: desaturate($errorText, 50%);
// Responsivity
$mobileThreshold: 632px;
$desktopThreshold: 940px;

View File

@ -1 +0,0 @@
@import "layout";

View File

@ -1,90 +0,0 @@
@import "layout";
header, footer {
margin: 0;
padding: 0;
height: 0;
}
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.messages {
margin-bottom: 32px;
}
.error-code {
font-size: 36px;
}
.error-message {
font-size: 32px;
}
.error-instructions {
margin-top: 32px;
font-size: 20px;
}
nav {
margin-top: 32px;
}
&::before {
content: "Oops";
position: absolute;
z-index: -1;
font-size: #{'min(50vh, 40vw)'};
opacity: 0.025;
}
}
.contact {
text-align: center;
padding: 8px;
}
.logo {
position: absolute;
top: 0;
left: 0;
width: 100%;
margin-top: 24px;
text-align: center;
a {
position: relative;
padding: 16px;
color: $defaultTextColor;
&:hover {
color: #fff;
&::before {
opacity: 0.2;
}
}
&::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: url(../img/logo.svg);
background-repeat: no-repeat;
background-position: center;
background-size: 64px;
opacity: 0.075;
filter: contrast(0);
}
}
}

View File

@ -1,843 +0,0 @@
@import "vars";
@import 'fonts';
@import "responsivity_tools";
* {
box-sizing: border-box;
}
html, body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
margin: 0;
font-family: "Nunito Sans", sans-serif;
font-size: 16px;
color: $defaultTextColor;
background-color: $backgroundColor;
}
@mixin tip {
position: relative;
.tip {
visibility: hidden;
position: absolute;
z-index: 10000;
pointer-events: none;
display: block;
width: max-content;
height: 30px;
padding: 4px 8px;
line-height: 22px;
top: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
text-align: center;
font-size: 18px;
color: $defaultTextColor;
opacity: 0;
transition: opacity ease-out 100ms, visibility step-end 150ms;
transition-delay: 0ms;
background-color: #000;
border-radius: 5px;
text-transform: initial;
font-weight: initial;
&.top {
top: auto;
bottom: calc(100% + 8px);
}
}
&:hover, &:active {
.tip {
visibility: visible;
opacity: 1;
transition: opacity ease-out 100ms;
transition-delay: 150ms;
}
}
}
body > header {
z-index: 50;
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
align-items: center;
$headerHeight: 64px;
height: $headerHeight;
line-height: $headerHeight;
background: $headerBackground;
@if $headerContainer {
@include container;
}
@media (max-width: $mobileThreshold) {
padding: 0;
}
.logo {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 16px 0 8px;
font-size: 24px;
color: $defaultTextColor;
&:hover {
color: lighten($defaultTextColor, 10%);
}
img {
width: initial;
height: calc(#{$headerHeight} - 16px);
margin-right: 8px;
flex-shrink: 0;
}
}
nav {
> ul {
position: fixed;
z-index: -1;
top: 0;
left: 0;
height: 100%;
transform: translateX(-100%);
transition: transform ease-out 150ms;
display: flex;
flex-direction: column;
margin: 0;
padding: $headerHeight 8px 8px;
font-size: 20px;
background: $panelBackground;
li {
position: relative;
list-style: none;
margin-top: 8px;
a, button {
position: relative;
margin: 0;
display: flex;
flex-direction: row;
align-items: center;
height: auto;
padding: 8px;
border-radius: 3px;
&:hover, &:active {
&:not(button) {
background-color: rgba(255, 255, 255, 0.07);
}
}
.feather {
--icon-size: 16px;
}
.tip {
position: static;
visibility: visible;
opacity: 1;
display: block;
height: auto;
margin-left: 8px;
padding: 0 0 0 4px;
transform: none;
font-size: 16px;
line-height: 16px;
color: inherit;
text-transform: uppercase;
font-weight: inherit;
background: transparent;
}
}
button {
margin: 0;
height: 32px;
.feather {
margin-right: 0;
}
}
form {
display: flex;
justify-content: center;
align-items: center;
padding: 0;
}
&.auth-user {
img {
width: 48px;
height: 48px;
border-radius: 3px;
margin-right: 8px;
}
}
.dropdown {
position: initial;
display: block;
padding-left: 0;
}
}
> li:not(:first-child) {
border-top: 1px solid transparentize($defaultTextColor, 0.8);
padding-top: 8px;
}
&.open {
transform: translateX(0%);
box-shadow: 0 0 5px darken($panelBackground, 20%);
}
}
#menu-button {
position: fixed;
top: 0;
left: 0;
display: block;
margin: 0;
padding: 0 16px;
line-height: $headerHeight;
cursor: pointer;
background: transparent;
border-radius: 0;
.feather {
--icon-size: 28px;
margin: 0 8px;
}
}
hr {
border: 0;
border-bottom: 1px solid $defaultTextColor;
opacity: 0.2;
}
}
@media (min-width: $mobileThreshold) {
flex-direction: row;
nav {
#menu-button {
display: none;
}
ul {
position: static;
flex-direction: row;
transform: none;
padding: 0;
background: transparent;
li {
margin-top: 0;
margin-left: 8px;
&:last-child {
a, button, .button {
.tip {
left: unset;
right: 4px;
transform: none;
}
}
}
.dropdown {
position: absolute;
z-index: -1;
top: 100%;
right: 0;
display: none;
padding: 8px;
white-space: nowrap;
background: $panelBackground;
border-radius: 0 0 3px 3px;
box-shadow: 0 2px 2px transparentize(darken($panelBackground, 20%), 0.75);
border-top: 4px solid lighten($panelBackground, 5%);
li {
margin-left: 0;
&:not(:first-child) {
margin-top: 8px;
}
}
}
&:hover .dropdown {
display: block;
}
}
> li:not(:first-child) {
border-top: 0;
padding-top: 0;
}
}
}
}
}
body > footer {
padding: 8px;
margin-top: 8px;
text-align: center;
background-color: $footerBackground;
}
main {
flex: 1;
padding: 8px 0;
button, .button {
@include tip;
}
}
h1 {
text-align: center;
font-size: 32px;
& + p {
text-align: center;
font-size: 20px;
}
}
h1, h2 {
font-weight: 100;
}
h3, h4 {
font-weight: 300;
}
section > h2, .panel > h2 {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
text-align: center;
margin-top: 4px;
font-size: 24px;
line-height: 1;
.feather {
margin: 0 16px 0 0;
opacity: 0.1;
}
&::after {
content: "";
flex: 1;
margin: 0 16px;
height: 0;
border-bottom: 1px solid $defaultTextColor;
opacity: 0.1;
}
}
section > hr, .panel > hr {
border: 0;
border-bottom: 1px solid $defaultTextColor;
opacity: 0.2;
margin: 8px 32px;
}
a {
color: $secondary;
text-decoration: none;
&:hover {
color: lighten($secondary, 30%);
}
.feather.feather-external-link {
--icon-size: 16px;
margin-left: 4px;
margin-top: -3px;
}
}
form {
padding: 8px 16px;
text-align: center;
.form-field:not(.hidden) {
display: flex;
flex-direction: column;
margin: 16px auto;
.control {
position: relative;
background: $inputBackground;
border-radius: 5px;
}
.feather.icon {
position: absolute;
top: 50%;
right: 8px;
transform: translateY(-50%);
z-index: 0;
--icon-size: 24px;
opacity: 0.75;
}
label {
position: absolute;
left: 8px;
top: 20px;
user-select: none;
font-size: 16px;
opacity: 0.75;
transition-property: top, font-size;
transition-duration: 150ms;
transition-timing-function: ease-out;
cursor: text;
}
[disabled] {
opacity: 0.5;
& ~ label {
opacity: 0.5;
cursor: default;
}
}
input, select, textarea, .input-group {
z-index: 1;
border: 0;
color: $defaultTextColor;
background: transparent;
font-size: 16px;
&:focus, &:not([value=""]), &[type="file"] {
~ label {
top: 8px;
font-size: 14px;
}
}
}
input, select, textarea, .form-display {
display: block;
padding: 32px 8px 8px 8px;
width: 100%;
height: 60px;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
&::-ms-expand {
display: none;
}
& + .feather {
position: absolute;
pointer-events: none;
right: 8px;
top: 30px;
transition: transform 150ms ease-out;
}
// Temporary
&:focus + .feather {
transform: rotateX(180deg);
}
}
textarea {
resize: vertical;
min-height: 100px;
font-family: inherit;
}
input[type=color] {
height: calc(32px + 8px + 32px);
}
&.inline {
display: flex;
flex-direction: row;
.control {
display: flex;
flex-direction: row;
align-items: center;
flex-grow: 1;
input[type=checkbox] {
width: min-content;
height: min-content;
margin: 8px;
text-align: left;
& ~ label {
position: static;
flex-grow: 1;
display: inline;
padding: 8px;
font-size: 16px;
text-align: left;
}
}
}
}
.input-group {
display: flex;
flex-grow: 1;
flex-direction: row;
div {
position: relative;
flex: 1;
input {
width: 100%;
border: 0;
background: transparent;
}
}
}
}
.inline-fields {
display: flex;
flex-direction: row;
align-items: start;
margin: 16px auto;
.form-field {
flex: 1;
margin: 0;
}
> :not(.form-field) {
padding: 32px 8px 8px 8px;
}
+ {
.error, .hint {
margin-top: -16px;
margin-bottom: 16px;
}
}
}
.form-field, .inline-fields + {
.error, .hint {
padding: 2px;
text-align: left;
font-size: 14px;
.feather {
--icon-size: 14px;
}
}
.error {
color: $error;
}
}
}
button, .button {
display: inline-flex;
margin: 8px;
padding: 12px 16px;
border: 0;
border-radius: 5px;
cursor: pointer;
text-transform: uppercase;
font-size: 16px;
font-weight: bolder;
line-height: 16px;
.feather {
--icon-size: 16px;
margin-right: 8px;
}
.feather.last {
margin-right: 0;
margin-left: 8px;
}
&, &.primary {
color: $primaryForeground;
background-color: darken($secondary, 10%);
&:hover {
background-color: $secondary;
}
}
&.info {
background-color: $infoColor;
}
&.success {
background-color: $successColor;
}
&.warning {
background-color: $warningColor;
&:hover {
background-color: lighten($warningColor, 10%);
}
}
&.error, &.danger {
background-color: $errorColor;
&:hover {
background-color: lighten($errorColor, 10%);
}
}
&.transparent {
background-color: transparent;
}
&:hover {
color: $primaryForeground;
}
}
// ---
// --- Tables
// ---
td.actions {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
form {
padding: 0;
display: inline;
}
button, .button {
margin: 0;
padding: 8px;
.feather {
margin-right: 0;
}
}
> *:not(:first-child) {
margin-left: 8px;
}
}
// ---
// --- Breadcrumb widget
// ---
.breadcrumb {
list-style: none;
display: flex;
flex-direction: row;
margin: 0;
padding: 8px;
> *:not(:first-child)::before {
content: '';
padding: 0 8px;
}
}
// ---
// --- Layout helpers
// ---
.center {
text-align: center;
}
.panel {
position: relative;
margin: 16px 0 48px;
padding: 8px;
background-color: $panelBackground;
border-radius: 5px;
p {
margin: 16px 8px;
}
> .feather:first-child {
position: absolute;
--icon-size: 24px;
opacity: 0.1;
top: 8px;
left: 8px;
}
}
.sub-panel {
margin: 32px 0;
padding: 1px 16px;
border: 2px solid lighten($panelBackground, 4%);
border-radius: 5px;
form > & {
margin: 32px -18px;
}
}
// ---
// --- Helper classes
// ---
.container > .messages:first-child {
margin-top: 16px;
}
.copyable-text {
display: flex;
flex-direction: row;
margin: 8px;
background-color: darken($backgroundColor, 2%);
border-radius: 5px;
overflow: hidden;
.title {
padding: 8px;
}
.content {
width: 0;
flex-grow: 1;
overflow: hidden;
white-space: nowrap;
padding: 8px;
}
.copy-button {
margin: 0;
padding: 0;
border-radius: 0;
.feather {
--icon-size: 20px;
margin: 8px;
}
}
}
.hidden {
display: none;
}
.progress-bar {
position: relative;
display: block;
margin: 8px;
padding: 4px;
background: #fff1;
border-radius: 5px;
overflow: hidden;
text-align: center;
.content {
position: relative;
}
&::before {
content: "";
display: block;
position: absolute;
left: 0;
top: 0;
width: var(--progress);
height: 100%;
transition: width ease-out 150ms;
background: $secondary;
}
}
.table-col-grow {
width: 100%;
}
.pagination {
ul {
display: flex;
flex-direction: row;
list-style: none;
padding: 8px;
justify-content: center;
li {
a, &.active, &.ellipsis {
display: block;
min-width: 40px;
height: 40px;
padding: 4px;
line-height: 32px;
text-align:center;
&:hover:not(.active):not(.ellipsis) {
background-color: #fff5;
}
}
}
}
}

View File

@ -1,19 +0,0 @@
@import "vars";
@mixin container {
width: 100%;
padding: 0 8px;
@media (min-width: $mobileThreshold) {
margin: 0 auto;
padding: 0 16px;
}
@media (min-width: $desktopThreshold) {
width: $desktopThreshold;
}
}
.container {
@include container;
}

View File

@ -1,39 +0,0 @@
export default class PersistentWebsocket {
private webSocket?: WebSocket;
public constructor(
protected readonly url: string,
private readonly handler: MessageHandler,
protected readonly reconnectOnClose: boolean = true,
) {
}
public run(): void {
const _webSocket = this.webSocket = new WebSocket(this.url);
this.webSocket.addEventListener('open', () => {
console.debug('Websocket connected');
});
this.webSocket.addEventListener('message', (e) => {
this.handler(_webSocket, e);
});
this.webSocket.addEventListener('error', (e) => {
console.error('Websocket error', e);
});
this.webSocket.addEventListener('close', (e) => {
this.webSocket = undefined;
console.debug('Websocket closed', e.code, e.reason);
if (this.reconnectOnClose) {
setTimeout(() => this.run(), 1000);
}
});
}
public send(data: string): void {
if (!this.webSocket) throw new Error('WebSocket not connected');
this.webSocket.send(data);
}
}
export type MessageHandler = (webSocket: WebSocket, e: MessageEvent) => void;

View File

@ -1,10 +0,0 @@
import './external_links';
import './message_icons';
import './forms';
import './copyable_text';
import './tooltips-and-dropdowns';
import './main_menu';
import './font-awesome';
// css
import '../sass/app.scss';

View File

@ -1,15 +0,0 @@
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.copyable-text').forEach(el => {
const contentEl = el.querySelector('.content');
const selection = window.getSelection();
if (contentEl && selection) {
contentEl.addEventListener('click', () => {
selection.selectAllChildren(contentEl);
});
el.querySelector('.copy-button')?.addEventListener('click', () => {
selection.selectAllChildren(contentEl);
document.execCommand('copy');
});
}
});
});

View File

@ -1,11 +0,0 @@
import feather from "feather-icons";
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('a[target="_blank"]').forEach(el => {
if (!el.classList.contains('no-icon')) {
el.innerHTML += `<i data-feather="external-link"></i>`;
}
});
feather.replace();
});

View File

@ -1,4 +0,0 @@
import '@fortawesome/fontawesome-free/scss/fontawesome.scss';
import '@fortawesome/fontawesome-free/scss/regular.scss';
import '@fortawesome/fontawesome-free/scss/solid.scss';
import '@fortawesome/fontawesome-free/scss/brands.scss';

View File

@ -1,43 +0,0 @@
/*
* For labels to update their state (css selectors based on the value attribute)
*/
import {ValidationError} from "swaf/db/Validator";
export function updateInputs(): void {
document.querySelectorAll<HTMLInputElement | HTMLTextAreaElement>('input, textarea').forEach(el => {
if (!el.dataset.inputSetup) {
el.dataset.inputSetup = 'true';
if (el.type !== 'checkbox') {
el.setAttribute('value', el.value);
el.addEventListener('change', () => {
el.setAttribute('value', el.value);
});
}
}
});
}
document.addEventListener('DOMContentLoaded', () => {
updateInputs();
});
export function applyFormMessages(
formElement: HTMLFormElement,
messages: { [p: string]: ValidationError<unknown> },
): void {
for (const fieldName of Object.keys(messages)) {
const field = formElement.querySelector('#field-' + fieldName);
if (!field) continue;
let parent = field.parentElement;
while (parent && !parent.classList.contains('form-field')) parent = parent.parentElement;
let err = field.querySelector('.error');
if (!err) {
err = document.createElement('div');
err.classList.add('error');
parent?.insertBefore(err, parent.querySelector('.hint') || parent);
}
err.innerHTML = `<i data-feather="x-circle"></i> ${messages[fieldName].message}`;
}
}

View File

@ -1,21 +0,0 @@
document.addEventListener('DOMContentLoaded', () => {
const menuButton = document.getElementById('menu-button');
const mainMenu = document.getElementById('main-menu');
if (menuButton) {
menuButton.addEventListener('click', (e) => {
e.stopPropagation();
mainMenu?.classList.toggle('open');
});
}
if (mainMenu) {
mainMenu.addEventListener('click', (e) => {
e.stopPropagation();
});
document.addEventListener('click', () => {
mainMenu.classList.remove('open');
});
}
});

View File

@ -1,26 +0,0 @@
import feather from "feather-icons";
document.addEventListener('DOMContentLoaded', () => {
const messageTypeToIcon: { [p: string]: string } = {
info: 'info',
success: 'check',
warning: 'alert-triangle',
error: 'x-circle',
question: 'help-circle',
};
document.querySelectorAll<HTMLElement>('.message').forEach(el => {
const icon = el.querySelector('.icon');
const type = el.dataset['type'];
if (!icon || !type) return;
if (!messageTypeToIcon[type]) throw new Error(`No icon for type ${type}`);
const svgContainer = document.createElement('div');
svgContainer.innerHTML = feather.icons[messageTypeToIcon[type]].toSvg();
if (svgContainer.firstChild) el.insertBefore(svgContainer.firstChild, icon);
icon.remove();
});
feather.replace();
});

View File

@ -1,31 +0,0 @@
export function updateTooltips(): void {
console.debug('Updating tooltips');
const elements = document.querySelectorAll<HTMLElement>('.tip, .dropdown');
// Calculate max potential displacement
let max = 0;
elements.forEach(el => {
const box = el.getBoundingClientRect();
if (max < box.height) max = box.height;
});
// Prevent displacement
elements.forEach(el => {
if (!el.dataset.tooltipSetup) {
el.dataset.tooltipSetup = 'true';
const box = el.getBoundingClientRect();
if (box.bottom >= document.body.clientHeight - (max + 32)) {
el.classList.add('top');
}
}
});
}
document.addEventListener('DOMContentLoaded', () => {
window.addEventListener('popstate', () => {
updateTooltips();
});
window.requestAnimationFrame(() => {
updateTooltips();
});
});

View File

@ -1,14 +0,0 @@
{% extends 'layouts/base.njk' %}
{% set title = app.name + ' - About us' %}
{% block body %}
<h1>Very interesting</h1>
<div class="container">
<section class="panel">
<h2>This is us</h2>
<p class="center">And we like swaf!</p>
</section>
</div>
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends 'layouts/base.njk' %}
{% set title = app.name + ' - Hello world!' %}
{% block body %}
<h1>Hello world!</h1>
{% endblock %}

View File

@ -1,41 +0,0 @@
{% extends 'layouts/barebone.njk' %}
{% import 'macros.njk' as macros %}
{% block _stylesheets %}
{{ super() }}
<link rel="stylesheet" href="/css/app.css">
{% block stylesheets %}{% endblock %}
{% endblock %}
{% block _scripts %}
{{ super() }}
{% block scripts %}{% endblock %}
{% endblock %}
{% block header %}
<a href="/" class="logo"><img src="/img/logo.svg" alt="Logo"> {{ app.name }}</a>
<nav>
<button id="menu-button"><i data-feather="menu"></i></button>
<ul id="main-menu">
<li><a href="{{ route('about') }}"><i data-feather="info"></i> <span class="tip">About</span></a></li>
</ul>
</nav>
{% endblock %}
{% block _body %}
<div class="container">
{{ macros.messages(flash) }}
</div>
<main>
{% if h1 %}
<h1>{{ h1 }}</h1>
{% endif %}
{% if subtitle %}
<p>{{ subtitle }}</p>
{% endif %}
{% block body %}{% endblock %}
</main>
{% endblock %}
{% block footer %}{{ app.name }} v{{ app_version }} - all rights reserved.{% endblock %}