Merge remote-tracking branch 'boilerplate/master' into develop
This commit is contained in:
commit
7870e4aa3c
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@ node_modules
|
||||
public
|
||||
dist
|
||||
yarn-error.log
|
||||
|
||||
src/package.json
|
||||
|
@ -6,9 +6,10 @@ $secondaryForeground: $primaryForeground;
|
||||
$backgroundColor: darken($primary, 4%);
|
||||
$defaultTextColor: #ffffff;
|
||||
|
||||
$headerBackground: darken($primary, 7.5%);
|
||||
$footerBackground: lighten($headerBackground, 1%);
|
||||
$panelBackground: lighten($headerBackground, 1%);
|
||||
$headerBackground: transparent;
|
||||
$headerContainer: true;
|
||||
$footerBackground: transparent;
|
||||
$panelBackground: darken($backgroundColor, 3.2%);
|
||||
$inputBackground: darken($panelBackground, 4%);
|
||||
|
||||
$info: #4499ff;
|
||||
@ -29,3 +30,4 @@ $errorColor: desaturate($errorText, 50%);
|
||||
|
||||
// Responsivity
|
||||
$mobileThreshold: 632px;
|
||||
$desktopThreshold: 940px;
|
||||
|
@ -1,5 +1,6 @@
|
||||
@import "vars";
|
||||
@import 'fonts';
|
||||
@import "responsivity_tools";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@ -69,21 +70,31 @@ body {
|
||||
body > header {
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
$headerHeight: 64px;
|
||||
height: $headerHeight;
|
||||
line-height: $headerHeight;
|
||||
|
||||
background-color: $headerBackground;
|
||||
background: $headerBackground;
|
||||
|
||||
@if $headerContainer {
|
||||
@include container;
|
||||
}
|
||||
|
||||
@media (max-width: $mobileThreshold) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
padding: 0 24px 0 16px;
|
||||
font-size: 32px;
|
||||
padding: 0 16px 0 8px;
|
||||
font-size: 24px;
|
||||
color: $defaultTextColor;
|
||||
|
||||
&:hover {
|
||||
@ -91,34 +102,48 @@ body > header {
|
||||
}
|
||||
|
||||
img {
|
||||
width: $headerHeight;
|
||||
height: $headerHeight;
|
||||
margin-right: 16px;
|
||||
width: initial;
|
||||
height: calc(#{$headerHeight} - 16px);
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
ul {
|
||||
> ul {
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
transform: translateX(-100%);
|
||||
transition: transform ease-out 150ms;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding: $headerHeight 8px 8px;
|
||||
|
||||
font-size: 20px;
|
||||
|
||||
background: $panelBackground;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
list-style: none;
|
||||
margin-top: 8px;
|
||||
|
||||
a, button {
|
||||
position: relative;
|
||||
height: 64px;
|
||||
margin: 0;
|
||||
padding: 0 24px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
padding: 8px;
|
||||
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover, &:active {
|
||||
&:not(button) {
|
||||
@ -127,13 +152,40 @@ body > header {
|
||||
}
|
||||
|
||||
.feather {
|
||||
--icon-size: 24px;
|
||||
--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;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tip {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity ease-out 100ms;
|
||||
transition-delay: 150ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 8px;
|
||||
padding: 24px;
|
||||
margin: 0;
|
||||
height: 32px;
|
||||
|
||||
.feather {
|
||||
@ -158,114 +210,117 @@ body > header {
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
|
||||
white-space: nowrap;
|
||||
background: $headerBackground;
|
||||
border-radius: 0 0 3px 3px;
|
||||
|
||||
a {
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .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 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
line-height: $headerHeight;
|
||||
|
||||
@media (max-width: $mobileThreshold) {
|
||||
flex-direction: row-reverse;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
|
||||
.logo {
|
||||
padding: 0 16px 0 8px;
|
||||
font-size: 24px;
|
||||
|
||||
img {
|
||||
margin-right: 8px;
|
||||
.feather {
|
||||
--icon-size: 28px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
#menu-button {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
line-height: $headerHeight;
|
||||
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
|
||||
.feather {
|
||||
--icon-size: 28px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> ul {
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
transition: transform ease-out 150ms;
|
||||
|
||||
background-color: $headerBackground;
|
||||
|
||||
&.open {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
li {
|
||||
a, button {
|
||||
.tip {
|
||||
display: block;
|
||||
margin-left: 8px;
|
||||
text-transform: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: initial;
|
||||
display: block;
|
||||
padding-left: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid $defaultTextColor;
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $mobileThreshold) {
|
||||
nav ul li {
|
||||
a, button, .button {
|
||||
@include tip;
|
||||
flex-direction: row;
|
||||
|
||||
nav {
|
||||
#menu-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
a, button, .button {
|
||||
.tip {
|
||||
left: unset;
|
||||
right: 4px;
|
||||
transform: 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
body > footer {
|
||||
padding: 8px;
|
||||
margin-top: 8px;
|
||||
text-align: center;
|
||||
@ -338,7 +393,7 @@ a {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: lighten($secondary, 10%);
|
||||
color: lighten($secondary, 30%);
|
||||
}
|
||||
|
||||
.feather.feather-external-link {
|
||||
@ -584,6 +639,10 @@ button, .button {
|
||||
|
||||
&.warning {
|
||||
background-color: $warningColor;
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($warningColor, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.error, &.danger {
|
||||
@ -603,6 +662,35 @@ button, .button {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---
|
||||
// --- 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;
|
||||
}
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
@ -629,6 +717,10 @@ button, .button {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---
|
||||
// --- Breadcrumb widget
|
||||
// ---
|
||||
.breadcrumb {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
@ -642,6 +734,7 @@ button, .button {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---
|
||||
// --- Layout helpers
|
||||
// ---
|
||||
@ -649,24 +742,6 @@ button, .button {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@mixin container {
|
||||
width: $mobileThreshold;
|
||||
padding: 0 16px;
|
||||
|
||||
@media (min-width: $mobileThreshold) {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media (max-width: $mobileThreshold) {
|
||||
width: 100%;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
@include container;
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
margin: 16px 0 48px;
|
||||
@ -688,10 +763,14 @@ button, .button {
|
||||
}
|
||||
|
||||
.sub-panel {
|
||||
margin: 32px -18px;
|
||||
margin: 32px 0;
|
||||
padding: 1px 16px;
|
||||
border: 2px solid lighten($panelBackground, 4%);
|
||||
border-radius: 5px;
|
||||
|
||||
form > & {
|
||||
margin: 32px -18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -715,6 +794,10 @@ button, .button {
|
||||
stroke-linejoin: miter;
|
||||
fill: none;
|
||||
vertical-align: middle;
|
||||
|
||||
h1 > &, h2 > &, h3 > & {
|
||||
--icon-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
19
assets/sass/responsivity_tools.scss
Normal file
19
assets/sass/responsivity_tools.scss
Normal file
@ -0,0 +1,19 @@
|
||||
@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;
|
||||
}
|
19
package.json
19
package.json
@ -4,23 +4,23 @@
|
||||
"description": "A simple redirection to serve a gitea instance's repositories' latest release files as an http file server. (302 redirections)",
|
||||
"repository": "https://eternae.ink/arisu/update.eternae.ink",
|
||||
"author": "Alice Gaudon <alice@gaudon.pro>",
|
||||
"main": "dist/src/main.js",
|
||||
"main": "dist/main.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dist-webpack": "webpack --mode production",
|
||||
"test": "jest --verbose --runInBand",
|
||||
"clean": "(test ! -d dist || rm -r dist)",
|
||||
"prepareSources": "cp package.json src/",
|
||||
"compile": "yarn clean && tsc",
|
||||
"build": "yarn compile && yarn dist-webpack",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"dev": "concurrently -k -n \"Typescript,Node,Webpack,Maildev\" -p \"[{name}]\" -c \"blue,green,red,yellow\" \"tsc --watch\" \"nodemon\" \"webpack --watch --mode development\" \"maildev\"",
|
||||
"start": "yarn build && node dist/src/main.js",
|
||||
"test": "jest --verbose --runInBand"
|
||||
"build": "yarn prepareSources && yarn compile && webpack --mode production",
|
||||
"dev": "yarn prepareSources && concurrently -k -n \"Typescript,Node,Webpack,Maildev\" -p \"[{name}]\" -c \"blue,green,red,yellow\" \"tsc --watch\" \"nodemon\" \"webpack --watch --mode development\" \"maildev\"",
|
||||
"start": "yarn build && node",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@fortawesome/fontawesome-free": "^5.14.0",
|
||||
"@types/config": "^0.0.36",
|
||||
"@types/config": "^0.0.38",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-session": "^1.17.0",
|
||||
"@types/feather-icons": "^4.7.0",
|
||||
@ -47,6 +47,7 @@
|
||||
"imagemin-svgo": "^8.0.0",
|
||||
"img-loader": "^3.0.1",
|
||||
"jest": "^26.1.0",
|
||||
"maildev": "^1.1.0",
|
||||
"mini-css-extract-plugin": "^1.2.1",
|
||||
"node-sass": "^5.0.0",
|
||||
"nodemon": "^2.0.3",
|
||||
@ -63,6 +64,6 @@
|
||||
"express": "^4.17.1",
|
||||
"mime": "^2.4.6",
|
||||
"send-ranges": "^4.0.0",
|
||||
"swaf": "^0.22.5"
|
||||
"swaf": "^0.23.0"
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import ExpressAppComponent from "swaf/components/ExpressAppComponent";
|
||||
import LogRequestsComponent from "swaf/components/LogRequestsComponent";
|
||||
import GiteaRepoLatestReleaseController from "./controllers/GiteaRepoLatestReleaseController";
|
||||
import NunjucksComponent from "swaf/components/NunjucksComponent";
|
||||
import packageJson = require('../package.json');
|
||||
import packageJson = require('./package.json');
|
||||
|
||||
export default class App extends Application {
|
||||
public constructor(
|
||||
|
25
src/controllers/HomeController.ts
Normal file
25
src/controllers/HomeController.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import Controller from "swaf/Controller";
|
||||
import {Request, Response} from "express";
|
||||
|
||||
export default class HomeController extends Controller {
|
||||
public routes(): void {
|
||||
this.get('/', this.getHome, 'home');
|
||||
this.get('/about', this.getAbout, 'about');
|
||||
this.get('/back', this.goBack, 'about');
|
||||
}
|
||||
|
||||
protected async getHome(req: Request, res: Response): Promise<void> {
|
||||
res.render('home');
|
||||
}
|
||||
|
||||
protected async getAbout(req: Request, res: Response): Promise<void> {
|
||||
res.render('about');
|
||||
}
|
||||
|
||||
/**
|
||||
* This is to test and assert that swaf extended types are available
|
||||
*/
|
||||
protected async goBack(req: Request, res: Response): Promise<void> {
|
||||
res.redirect(req.getPreviousUrl() || Controller.route('home'));
|
||||
}
|
||||
}
|
10
src/main.ts
10
src/main.ts
@ -2,19 +2,19 @@ import {delimiter} from "path";
|
||||
|
||||
// Load config from specified path or default + swaf/config (default defaults)
|
||||
process.env['NODE_CONFIG_DIR'] =
|
||||
__dirname + '/../../node_modules/swaf/config/'
|
||||
__dirname + '/../node_modules/swaf/config/'
|
||||
+ delimiter
|
||||
+ (process.env['NODE_CONFIG_DIR'] || __dirname + '/../../config/');
|
||||
+ (process.env['NODE_CONFIG_DIR'] || __dirname + '/../config/');
|
||||
|
||||
import {log} from "swaf/Logger";
|
||||
import {logger} from "swaf/Logger";
|
||||
import App from "./App";
|
||||
import config from "config";
|
||||
|
||||
(async () => {
|
||||
log.debug('Config path:', process.env['NODE_CONFIG_DIR']);
|
||||
logger.debug('Config path:', process.env['NODE_CONFIG_DIR']);
|
||||
|
||||
const app = new App(config.get<string>('listen_addr'), config.get<number>('port'));
|
||||
await app.start();
|
||||
})().catch(err => {
|
||||
log.error(err);
|
||||
logger.error(err);
|
||||
});
|
||||
|
@ -2,6 +2,7 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "public/js",
|
||||
"rootDir": "./assets",
|
||||
"target": "ES6",
|
||||
"strict": true,
|
||||
"lib": [
|
||||
|
@ -3,6 +3,7 @@
|
||||
"module": "CommonJS",
|
||||
"esModuleInterop": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "./src",
|
||||
"target": "ES6",
|
||||
"strict": true,
|
||||
"lib": [
|
||||
|
Loading…
Reference in New Issue
Block a user