~otheb/kb

7cbf4a16e0bfa09dbb3e36d4259382822214d4f3 — Olie Ayre 2 months ago 8399004
Started web project

Unfortunately though, code.dlang.org went down when I was doing this, so
I can't actually build or test the project.

If you're reading this commit message, then I forgot to rebase before
pushing...
4 files changed, 280 insertions(+), 0 deletions(-)

A web/dub.json
A web/main.d
A web/static/global.css
A web/static/index.html
A web/dub.json => web/dub.json +17 -0
@@ 0,0 1,17 @@
{
	"authors": [
		"Oliver Ayre"
	],
	"dependencies": {
		"arsd-official:dom": "~>5.0.0",
		"arsd-official:http": "~>5.0.0",
		"lighttp": "~>0.5.3"
	},
	"description": "Minimal WUI to the kb API server",
	"license": "AGPL-3.0",
	"name": "kbw",
	"sourceFiles": [
		"main.d"
	],
	"targetType": "executable"
}
\ No newline at end of file

A web/main.d => web/main.d +149 -0
@@ 0,0 1,149 @@
module kbw ;

import std.stdio ;
import std.json  ;

// default config file
const string CONFFILE = "/etc/kbw/config" ;
// basic settings
ushort PORT         = 80               ;
string FRIENDLYNAME = "KB Web UI"      ;
bool   LIGHTTHEME   = false            ;
string SERVER       = "localhost:8000" ;

const string globalcss = q"EOS
/* font sizes */
@media screen and ( min-width : 600px ) {
	:root {
		--normal : 14px ;
		--big    : 24px ;
		--title  : 50px ;
	}
}
@media screen and ( max-width : 599px ) {
	:root {
		--normal : 12px ;
		--big    : 16px ;
		--title  : 25px ;
	}
}

/* main body elements */
html , body { background-color : var( --bg ) ; }
body {
	max-width  : 800px           ;
	margin     : auto            ;
	padding    : 10px            ;
	color      : var( --fg )     ;
	font-size  : var( --normal ) ;
	text-align : right           ;
}
* {
	scrollbar-width : thin                     ;
	scrollbar-color : var( --dfg ) var( --bg ) ;
	tab-size        : 4                        ;
	-moz-tab-size   : 4                        ;
	-o-tab-size     : 4                        ;
}

/* title at top */
h1 {
	text-align : center         ;
	color      : var( --bfg )   ;
	font-size  : var( --title ) ;
}

/* sort link on home page */
a { transition-duration : 0.1s ; }
a.sort { color : var( --acc ) ; }
a.sort:hover { color : var( --bfg ) ; }

/* entry listing */
div {
	background-color : var( --bbg ) ;
	margin           : 10px 0px     ;
	padding          : 10px         ;
	text-align       : left         ;
	color            : var( --bg )  ;
}
div span.id {
	color     : var( --dfg ) ;
	font-size : var( --big ) ;
}
a.entry {
	color     : var( --bfg ) ;
	font-size : var( --big ) ;
}
a.entry:hover { color : var( --acc ) ; }
span.tag {
	display          : inline-block     ;
	background-color : var( --dfg )     ;
	padding          : 2px 4px          ;
	margin           : 10px 3px 0px 3px ;
}
EOS" ;

int main( string[] args ) {
	// read config
	// if an argument is provided, that is used as the config file
	// config file will softly default to /etc/kbw/config
	if ( args.length > 2 ) {
		writeln( "Usage: " , args[0] , " [CONFIG FILE]" ) ;
		return 1 ;
	} else if ( args.length == 2 ) {
		if ( ! exists( args[1] ) ) {
			writeln( "Config file " , args[1] ,
			         " does not exist or cannot be found" ) ;
			return 1 ;
		} else if ( isDir( args[1] ) ) {
			writeln( "Config file " , args[1] , " is a directory" ) ;
			return 1 ;
		}
		readconf( args[1].readText() ) ;
	}
	if ( exists( CONFFILE ) ) //
	if ( isFile( CONFFILE ) ) { readconf( CONFFILE.readText() ) ; }

	// display config options on startup
	writeln( "           Port : " , PORT ) ;
	writeln( "  Friendly name : " , FRIENDLYNAME ) ;
	writeln( "Use light theme : " , LIGHTTHEME ) ;
	writeln( "     API server : " , SERVER ) ;

	Server server = new Server() ;
	server.host( "0.0.0.0" , PORT ) ;
	server.host( "::" , PORT ) ;
	server.router.add( new router() ) ;
	server.run() ;
	return 0 ;
}

void readconf( string content ) {
	auto j = content.parseJSON() ;
	if ( ( "port" in j ) !is null ) { PORT = cast(ushort)j["port"].integer ; }
	if ( ( "friendly-name" in j ) !is null ) {
		FRIENDLYNAME = j["friendly-name"].str ;
	}
	if ( ( "light-theme" in j ) !is null ) {
		LIGHTTHEME = j["light-theme"].boolean ;
	}
	if ( ( "server" in j ) !is null ) { SERVER = j["server"].str ; }
}

class router {
	@Get( "" )
	index( ServerRequest req , ServerResponse res ) {
		writeln( "GET /" ) ;
		bool sortrecent = ( "sort" in req.url.queryParams ) is null ? false :
			              req.url.queryParams["sort"] == "recent" ;
		// build base document
		auto doc = new Document() ;
		doc.title( FRIENDLYNAME ) ;
		doc.mainBody
			// add title at top
			.addChild( "h1" , FRIENDLYNAME )
			// add "sort by" node
			.addChild( "#text" , "Sort by " )

	}
}

A web/static/global.css => web/static/global.css +80 -0
@@ 0,0 1,80 @@
/* THEMES WILL BE IN SEPARATE FILES */
:root {
	--bg : #1f1f1f ;
	--fg : #d5d5d5 ;
	--bfg : #fff ;
	--bbg : #4e4e4e ;
	--dfg : #6e6e6e ;
	--acc : #1099eb ;
}

/* RESPONSIVE FONT SIZES */
@media screen and ( min-width : 600px ) {
	:root {
		--normal : 14px ;
		--big : 24px ;
		--title : 50px ;
	}
}
@media screen and ( max-width : 599px ) {
	:root {
		--normal : 12px ;
		--big : 16px ;
		--title : 25px ;
	}
}

/* GLOBAL */
html , body { background-color : var( --bg ) ; }
body {
	max-width : 800px ;
	margin : auto ;
	padding : 10px ;
	color : var( --fg ) ;
	font-size : var( --normal ) ;
	text-align : right ;
}
* {
	scrollbar-width : thin ;
	scrollbar-color : var( --dfg ) var( --bg ) ;
	tab-size : 4 ;
	-moz-tab-size : 4 ;
	-o-tab-size : 4 ;
}

/* HEADER AT TOP */
h1 {
	text-align : center ;
	color : var( --bfg ) ;
	font-size : var( --title ) ;
}

/* SORT LINKS FOR HOME PAGE */
a { transition-duration : 0.1s ; }
a.sort { color : var( --acc ) ; }
a.sort:hover { color : var( --bfg ) ; }

/* ENTRY LISTINGS */
div {
	background-color : var( --bbg ) ;
	margin : 10px 0px ;
	padding : 10px ;
	text-align : left ;
	color : var( --bg ) ;
}
div
span.id {
	color : var( --dfg ) ;
	font-size : var( --big ) ;
}
a.entry {
	color : var( --bfg ) ;
	font-size : var( --big ) ;
}
a.entry:hover { color : var( --acc ) ; }
span.tag {
	display : inline-block ;
	background-color : var( --dfg ) ;
	padding : 2px 4px ;
	margin : 10px 3px 0px 3px ;
}

A web/static/index.html => web/static/index.html +34 -0
@@ 0,0 1,34 @@
<!DOCTYPE html>
<head>
	<meta charset="utf-8">
	<link rel="stylesheet" type="text/css" href="/global.css">
	<title>FRIENDLYNAME</title>
</head>
<body>
	<h1>FRIENDLYNAME</h1>
	Sort by <a class="sort" href="/index.html?sort=recent">time</a> instead.
	<div>
		<span class="id">#ID</span>
		<a class="entry" href="/entry/0">[DEPRECATED] The title of this entry</a>
		<br>
		3 January 2020 @ 3:50pm
		<span class="tag">firsttag</span>
		<span class="tag">second</span>
	</div>
	<div>
		<span class="id">#ID</span>
		<a class="entry" href="/entry/0">[DEPRECATED] The title of this entry</a>
		<br>
		3 January 2020 @ 3:50pm
		<span class="tag">firsttag</span>
		<span class="tag">second</span>
	</div>
	<div>
		<span class="id">#ID</span>
		<a class="entry" href="/entry/0">[DEPRECATED] The title of this entry</a>
		<br>
		3 January 2020 @ 3:50pm
		<span class="tag">firsttag</span>
		<span class="tag">second</span>
	</div>
</body>