changeset 12:3e2cb946d511

form handling
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 30 Oct 2023 14:59:45 -0600
parents 62dd23f0b549
children af2b95854072
files src/add_server.html.luan src/add_server.js.luan src/choose_server.html.luan src/error_log.js.luan src/lib/Shared.luan src/site.css src/site.js
diffstat 7 files changed, 119 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/add_server.html.luan	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/add_server.html.luan	Mon Oct 30 14:59:45 2023 -0600
@@ -14,7 +14,8 @@
 	local parameters = Http.request.parameters
 	local id = parameters.id or error()
 	local name = parameters.name or error()
-	local icon = parameters.icon
+	name = html_encode(name)
+	local icon = parameters.icon or error()
 	Io.stdout = Http.response.text_writer()
 %>
 <!doctype html>
@@ -22,16 +23,30 @@
 	<head>
 <%		head() %>
 		<title>Disearch</title>
+		<style>
+			input[type="url"] {
+				width: 100%;
+			}
+		</style>
 	</head>
 	<body>
 <%		header() %>
 
 		<h1>Add server</h1>
 
-		<p><%=html_encode(name)%></p>
-<%	if icon ~= nil then %>
-		<p><img src="https://cdn.discordapp.com/icons/<%=id%>/<%=icon%>.png"></p>
-<%	end %>
+		<form page onsubmit="ajaxForm('/add_server.js',this); return false">
+			<input type=hidden name=id value="<%=id%>">
+			<input type=hidden name=name value="<%=name%>">
+			<input type=hidden name=icon value="<%=icon%>">
+			<p><%=name%></p>
+			<p><img icon src="https://cdn.discordapp.com/icons/<%=id%>/<%=icon%>.png"></p>
+			<p>
+				Invite URL:<br>
+				<input type=url required name=invite>
+				<span error=invite></span>
+			</p>
+			<p><input type=submit></p>
+		</form>
 
 <%		footer() %>
 	</body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/add_server.js.luan	Mon Oct 30 14:59:45 2023 -0600
@@ -0,0 +1,31 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local String = require "luan:String.luan"
+local regex = String.regex or error()
+local Io = require "luan:Io.luan"
+local Http = require "luan:http/Http.luan"
+local Shared = require "site:/lib/Shared.luan"
+local js_error = Shared.js_error or error()
+local Logging = require "luan:logging/Logging.luan"
+local logger = Logging.logger "add_server.js"
+
+
+local invite_regex = regex[[^https://discord.gg/(\w+)$]]
+
+return function()
+	Io.stdout = Http.response.text_writer()
+	local parameters = Http.request.parameters
+	local id = parameters.id or error()
+	local name = parameters.name or error()
+	local icon = parameters.icon or error()
+	local invite = parameters.invite or error()
+	invite = invite_regex.match(invite)
+	logger.info("invite = "..invite)
+	if invite==nil then
+		js_error( "invite", [[Invalid Discord invite URL]] )
+		return
+	end
+%>
+	location = '/servers.html';
+<%
+end
--- a/src/choose_server.html.luan	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/choose_server.html.luan	Mon Oct 30 14:59:45 2023 -0600
@@ -86,13 +86,16 @@
 		local id = server.id or error()
 		local name = server.name or error()
 		local icon = server.icon
-		local url = "add_server.html?id="..id.."&name="..url_encode(name)
 		if icon ~= nil then
-			url = url.."&icon="..icon
+			local url = "add_server.html?id="..id.."&name="..url_encode(name).."&icon="..icon
+%>
+			<p><a href="<%=url%>"><%=html_encode(name)%></a></p>
+<%
+		else
+%>
+			<p><%=html_encode(name)%> (missing icon)</p>
+<%
 		end
-%>
-		<p><a href="<%=url%>"><%=html_encode(name)%></a></p>
-<%
 	end
 %>
 <%		footer() %>
--- a/src/error_log.js.luan	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/error_log.js.luan	Mon Oct 30 14:59:45 2023 -0600
@@ -1,5 +1,7 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
+local String = require "luan:String.luan"
+local trim = String.trim or error()
 local Http = require "luan:http/Http.luan"
 local Logging = require "luan:logging/Logging.luan"
 local logger = Logging.logger "error_log.js"
--- a/src/lib/Shared.luan	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/lib/Shared.luan	Mon Oct 30 14:59:45 2023 -0600
@@ -1,6 +1,8 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local Time = require "luan:Time.luan"
+local Parsers = require "luan:Parsers.luan"
+local json_string = Parsers.json_string or error()
 local Http = require "luan:http/Http.luan"
 
 
@@ -58,4 +60,10 @@
 	return request.scheme.."://"..request.headers["Host"].."/login2.html"
 end
 
+function Shared.js_error(field,message)
+%>
+	showError( context.form, '<%=field%>', <%=json_string(message)%> );
+<%
+end
+
 return Shared
--- a/src/site.css	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/site.css	Mon Oct 30 14:59:45 2023 -0600
@@ -13,6 +13,7 @@
 	text-decoration: underline;
 }
 
+input[type="submit"],
 [onclick] {
 	cursor: pointer;
 }
@@ -49,3 +50,17 @@
 	right: 0;
 	margin-top: 20px;
 }
+
+[error] {
+	font-size: small;
+	color: firebrick;
+}
+[error][flash] {
+	color: red;
+}
+[error="success"] {
+	color: green;
+}
+[error="success"][flash] {
+	color: lime;
+}
--- a/src/site.js	Sun Oct 29 22:39:31 2023 -0600
+++ b/src/site.js	Mon Oct 30 14:59:45 2023 -0600
@@ -43,6 +43,41 @@
 	ajax( '/error_log.js', 'err='+encodeURIComponent(err) );
 };
 
+
+function ajaxForm(url,form) {
+	let post = '';
+	for( let i=0; i<form.length; i++ ) {
+		let input = form[i];
+		let name = input.name;
+		if( name === '' )
+			continue;
+		let type = input.type;
+		if( (type==='radio' || type==='checkbox') && !input.checked )
+			continue;
+		post += name + '=' + encodeURIComponent(input.value) + '&';
+	}
+	ajax(url,post,{form:form});
+}
+
+function clearErrors(form) {
+	let divs = form.querySelectorAll('div[error]');
+	for( let i=0; i<divs.length; i++ ) {
+		divs[i].textContent = '';
+	}
+}
+
+function showError(form,field,message) {
+	clearErrors(form);
+	let err = form.querySelector('[error="'+field+'"]');
+	err.textContent = message;
+	err.scrollIntoViewIfNeeded(false);
+	err.setAttribute('flash','');
+	setTimeout(function(){err.removeAttribute('flash')},2000);
+	let input = form.querySelector('input[name="'+field+'"]');
+	if(input) input.focus();
+}
+
+
 let currentPulldown = null;
 let newPulldown = null;