~otheb/kb

5eb69b6fc8ef2b32bb2caeed6bc91df87d3a632c — Olie Ayre 2 months ago bffb801
Web UI is now feature complete

Now has the ability to edit and patch entries.
1 files changed, 92 insertions(+), 45 deletions(-)

M kb-web/main.d
M kb-web/main.d => kb-web/main.d +92 -45
@@ 114,6 114,14 @@ class entry {
		content = c            ;
		history = h.map!( e => tuple( e[0].fmtdate() , e[1] ) ).array ;
	}

	this( long i , string t , string[] tg , bool o , string c ) {
		id      = i  ;
		title   = t  ;
		tags    = tg ;
		old     = o  ;
		content = c  ;
	}
}

auto getindex() { return get( "http://" ~ SERVER ~ "/" ).waitForCompletion() ; }


@@ 137,6 145,16 @@ auto postnew( string j ) {
	                                 HttpVerb.POST , cast(ubyte[])j ,
	                                 "application/json" ).waitForCompletion() ;
}
auto postedit( string j , string id ) {
	return new HttpClient().request( Uri( "http://" ~ SERVER ~ "/" ~ id ) ,
	                                 HttpVerb.POST , cast(ubyte[])j ,
	                                 "application/json" ).waitForCompletion() ;
}
auto patchedit( string j , string id ) {
	return new HttpClient().request( Uri( "http://" ~ SERVER ~ "/" ~ id ) ,
	                                 HttpVerb.PATCH , cast(ubyte[])j ,
	                                 "application/json" ).waitForCompletion() ;
}

auto noapi() {
	return mkdoc(


@@ 256,29 274,12 @@ class router {

	@Get( "new" )
	createpage( ServerRequest req , ServerResponse res ) {
		res.body = makenewpage() ;
		res.body = makeeditpage() ;
	}
	@Post( "new" )
	handlecreate( ServerRequest req , ServerResponse res ) {
		// get parameters
		string[string] items ;
		foreach ( string param ; req.body.split( "&" ) ) {
			Tuple!( string , string ) kv = param.split( "=" )[0..2] ;
			items[ kv[0] ] = kv[1].tr( "+" , " " ).decodeComponent()
			// we split lines and join again to remove nasty CRLF line endings
			                 .splitLines().join( "\n" ) ;
		}
		// adjust parameters for better formatting
		items["title"] = items["title"].tr( "\n" , " " ) ;
		string[] lines ;
		foreach ( string l ; items["content"].splitLines() ) {
			l = l.stripRight() ;
			while ( l.startsWith( "    " ) && l.length > 4 ) {
				l = "\t" ~ l[4..$] ;
			}
			lines ~= l ;
		}
		items["content"] = lines.join( "\n" ).wrap( 80 ) ;
		auto items = getparams( req.body ) ;
		writeln( "Creating new entry with data : " , items ) ;

		// build json


@@ 324,12 325,62 @@ class router {
			return ;
		}

		auto j = apires.contentText.parseJSON() ;
		auto e = apires.fromjson() ;

		res.body = makeeditpage( true , e ) ;
	}
	@Post( "edit" , "([0-9]+)" )
	handleedit( ServerRequest req , ServerResponse res , string id ) {
		auto items = getparams( req.body ) ;
		writeln( "Editing entry with data : " , items ) ;

		// build json
		auto j = JSONValue( [
			"title" : JSONValue( items["title"] ) ,
			"old"   : JSONValue( ( "old" in items ) !is null ) ,
			"tags"  : JSONValue( items.get( "tags" , "" ).split()
			                     .filter!( t => t != "" ).array ) ,
			"content" : JSONValue( items["content"] )
		] ).toString() ;

		// make API request
		HttpResponse apires ;
		try { apires = ( "ispatch" in items ) !is null ?
		             patchedit( j , id ) : postedit( j , id ) ;
		} catch ( SocketOSException e ) {
			res.status = StatusCodes.badGateway ;
			res.body = noapi() ;
			return ;
		}
		auto newentry = apires.contentText.parseJSON()["id"].integer.to!string ;

		// redirect to new entry page
		writeln( "Edited entry " , newentry , ", redirecting" ) ;
		res.status = StatusCodes.seeOther ;
		res.headers["Location"] = "/entry/" ~ newentry ;
	}
}

		res.body = makeeditpage( id , j["title"].str ,
		                         j["tags"].array.map!( t => t.str ).array ,
		                         j["old"].boolean , j["content"].str ) ;
string[string] getparams( string q ) {
	string[string] items ;
	foreach ( string param ; q.split( "&" ) ) {
		Tuple!( string , string ) kv = param.split( "=" )[0..2] ;
		items[ kv[0] ] = kv[1].tr( "+" , " " ).decodeComponent()
			// we split lines and join again to remove nasty CRLF line endings
			.splitLines().join( "\n" ) ;
	}
	// adjust parameters for better formatting
	items["title"] = items["title"].tr( "\n" , " " ) ;
	string[] lines ;
	foreach ( string l ; items["content"].splitLines() ) {
		l = l.stripRight() ;
		while ( l.startsWith( "    " ) && l.length > 4 ) {
			l = "\t" ~ l[4..$] ;
		}
		lines ~= l ;
	}
	items["content"] = lines.join( "\n" ).wrap( 80 ) ;
	return items ;
}

entry fromjson( JSONValue j ) {


@@ 449,26 500,38 @@ string makeentry( entry e ) {
	) ;
}

string makenewpage() {
string makeeditpage( bool editing = false , entry e = null ) {
	string title = editing ?
	               "Editing entry #" ~ e.id.text ~ " '" ~ e.title ~ "'" :
	               "Create a new entry" ;
	return mkdoc(
		makehead( "Create a new entry - " ~ FRIENDLYNAME ) ,
		makehead( title ~ " - " ~ FRIENDLYNAME ) ,
		body(
			h1( a( "/" , FRIENDLYNAME ) ) ,
			div(
				h2( "Create a new entry" ) ,
				form( "/new" ,
				h2( title ) ,
				form( editing ? "/edit/" ~ e.id.text : "/new" ,
					span( "Title" ).class_( "label" ) ,
					input().attr( "type" , "text" ).attr( "name" , "title" )
						.attr( "value" , editing ? e.title : "" )
						.attr( "placeholder" , "Title" )
						.attr( "required" , "" ) , br ,
					span( "Tags" ).class_( "label" ) ,
					input().attr( "type" , "text" ).attr( "name" , "tags" )
						.attr( "value" , editing ? e.tags.join( " " ) : "" )
						.attr( "placeholder" , "first second third" ) , br ,
					span( "Deprecated" ).class_( "label" ) ,
					editing && e.old ?
					input().attr( "type" , "checkbox" ).attr( "name" , "old" )
						.attr( "checked" , "" ) :
					input().attr( "type" , "checkbox" ).attr( "name" , "old" ) ,
					br ,
					textarea( "" ).attr( "name" , "content" )
						.attr( "cols" , "80" )
					editing ? span( "Is Patch" ).class_( "label" ) : nothing ,
					editing ? input().attr( "type" , "checkbox" )
						.attr( "name" , "ispatch" ) : nothing ,
					editing ? br : nothing ,
					textarea( editing ? e.content : "" )
						.attr( "name" , "content" ).attr( "cols" , "80" )
						.attr( "placeholder" , "Message content" )
						.attr( "required" , "" ) ,
					input().attr( "type" , "submit" ).attr( "value" , "Submit" )


@@ 477,19 540,3 @@ string makenewpage() {
		)
	) ;
}

string makeeditpage( string id , string ) {
	return mkdoc(
		makehead( "Edit entry #" ~ id ~ " - " ~ FRIENDLYNAME ) ,
		body(
			h1( a( "/" , FRIENDLYNAME ) ) ,
			div(
				h2( "Edit entry #" , id ) ,
				form( "/edit/" ~ id ,
					span( "Title" ).class_( "label" ) ,
					input( )
				).id( "form").attr( "method" , "post" )
			)
		)
	) ;
}