view src/theme.html.luan @ 3:b016e4b7c8da default tip

add read_me
author Franklin Schmidt <fschmidt@gmail.com>
date Sat, 12 Jul 2025 12:51:36 -0600
parents 8f4df159f06b
children
line wrap: on
line source

local Luan = require "luan:Luan.luan"
local error = Luan.error
local pairs = Luan.pairs or error()
local parse = Luan.parse or error()
local Html = require "luan:Html.luan"
local html_encode = Html.encode or error()
local Io = require "luan:Io.luan"
local Http = require "luan:http/Http.luan"
local Shared = require "site:/lib/Shared.luan"
local head = Shared.head or error()
local body_header = Shared.body_header or error()
local footer = Shared.footer or error()
local fields = Shared.theme_fields or error()
local User = require "site:/lib/User.luan"
local get_background_img_url = User.get_background_img_url or error()
local Logging = require "luan:logging/Logging.luan"
local logger = Logging.logger "theme.html"


local google_explanation = [[All Google fonts use this URL format.  You can change the font name and edit the font URL to use other Google fonts not listed here.]]

local fonts = {
	["Sans-Serif"] = {}
	["Times New Roman"] = {}
	["Optima"] = {}
	["Apple Chancery"] = {}
	["Courier"] = {}
	["Copperplate"] = {}
	["Bitter"] = {
		title = "Google: Bitter"
		url = "https://fonts.googleapis.com/css?family=Bitter"
		explanation = google_explanation
	}
	["Genos"] = {
		title = "Google: Genos"
		url = "https://fonts.googleapis.com/css?family=Genos"
		explanation = google_explanation
	}
	["Emblema One"] = {
		title = "Google: Emblema One"
		url = "https://fonts.googleapis.com/css?family=Emblema+One"
		explanation = google_explanation
	}
}
for name, font in pairs(fonts) do
	font.name = name
	font.title = font.title or name
	font.url = font.url or ""
	font.explanation = font.explanation or ""
end

local function color_input(user_data,color)
	local value = user_data[color]
	value = value and html_encode(value)
	local default = fields[color]
	local v = value or default
%>
				<div>
					<input type=color <%= v=="" and "" or [[value="]]..v..[["]] %> oninput="colorChange(this)">
					<span color <%= v=="" and "" or [[style="background-color:]]..v..[["]] %> onclick="colorClick(this)"></span>
					<input type=text name="<%=color%>" value="<%= value or "" %>" placeholder="<%=default%>" onchange="colorInputChange(this)">
				</div>
<%
end

local function radio_input(user_data,name,value)
	local current = user_data[name] or fields[name]
	local checked = value==current and "checked" or ""
	%><input type=radio name="<%=name%>" value="<%=value%>" <%=checked%> ><%
end

return function()
	local user = User.current_required()
	if user==nil then return end
	local user_data = user.theme_data
	user_data = user_data and parse(user_data) or {}
	local message
	Io.stdout = Http.response.text_writer()
%>
<!doctype html>
<html lang="en">
	<head>
<%		head() %>
		<title>Link My Style</title>
		<style>
<%
	for _, font in pairs(fonts) do
		if font.url ~= "" then
%>
			@import "<%=font.url%>";
<%
		end
%>
<%
	end
%>

			h1 {
				text-align: center;
			}
			div[body] {
				max-width: 600px;
				margin-left: auto;
				margin-right: auto;
			}
			@media (max-width: 700px) {
				div[body] {
					max-width: 90%;
				}
			}
			label {
				display: block;
			}
			form > div {
				display: flex;
				margin-top: 1px;
				margin-bottom: 10px;
				position: relative;
			}
			input[type="color"] {
				/* hide this useless modern piece of junk */
				position: absolute;
				z-index: 1;
				width: 42.5px;
				height: 42.5px;
				cursor: pointer;
				opacity: 0;
			}
			span[color] {
				width: 42.5px;
				cursor: pointer;
				border: 1px solid #E0E0E0;
			}
			form span[pulldown] {
				border: 1px solid #E0E0E0;
				display: flex;
				align-items: center;
			}
			form span[pulldown] > span {
				padding: 4px;
			}
			span[shape] a {
				margin: 12px;
				padding: 12px 100px;
				border: 1px solid black;
			}
			span[shape] a:hover {
				text-decoration: none;
			}
			input[type="text"] {
				display: initial;
				margin: 0;
				border-radius: 0;
			}
			label[clickable] {
				border: 1px solid grey;
				padding: 4px;
				padding-right: 8px;
			}
			label[white] {
				color: white;
				background-color: black;
			}
			div[background_img] {
				gap: 8px;
			}
			button[background_img] {
				width: 42.5px;
				height: 42.5px;
				padding: 0;
				border: 1px solid #E0E0E0;
			}
			button[background_img] img {
				display: block;
				width: 100%;
				height: 100%;
				object-fit: cover;
			}
			div[background_img] button[small] {
				flex-grow: 1;
				background-color: #E0E0E0;
				color: black;
			}
			div[background_img] button[small]:hover {
				background-color: #C0C0C0;
			}
			div[font] {
				gap: 8px;
			}
			div[font] input[name="font"] {
				width: 33%;
			}
			div[font] input[name="font_url"] {
				width: 66%;
			}
			div[font_explanation] {
				color: #808080;
			}
		</style>
		<script>
			'use strict';

			function colorClick(colorSpan) {
				console.log('colorClick');
				let colorInput = colorSpan.parentNode.querySelector('input[type="color"]');
				colorInput.click();
			}
			function colorChange(colorInput) {
				let parent = colorInput.parentNode;
				let color = colorInput.value;
				parent.querySelector('input[type="text"]').value = color;
				parent.querySelector('span[color]').style['background-color'] = color;
			}
			function colorInputChange(input) {
				let parent = input.parentNode;
				let color = input.value || input.placeholder;
				parent.querySelector('input[type="color"]').value = color;
				parent.querySelector('span[color]').style['background-color'] = color;
			}
			function setField(name,value) {
				document.querySelector('input[type="text"][name="'+name+'"]').value = value;
			}
			function setFont(font,url,explanation) {
				setField('font',font);
				setField('font_url',url);
				document.querySelector('div[font_explanation]').textContent = explanation;
			}

			function uploaded(uuid,filename) {
				document.querySelector('input[name="background_img_uuid"]').value = uuid;
				document.querySelector('input[name="background_img_filename"]').value = filename;
				document.querySelector('div[background_img] img').src = uploadcareUrl(uuid);
			}
			function clearImg() {
				document.querySelector('input[name="background_img_uuid"]').value = '';
				document.querySelector('input[name="background_img_filename"]').value = '';
				document.querySelector('div[background_img] img').src = '/images/nothing.svg';
			}
		</script>
	</head>
	<body>
	<div full>
<%		body_header() %>
		<h1>My Theme</h1>
		<p top>Click the left side of every section to make quick changes or put exactly what you'd like in the input field. To remove a color or shadow, delete the text from the input field.</p>
		<div body>
			<form onsubmit="ajaxForm('/theme.js',this)" action="javascript:">
				<label>Background Image</label>
				<div background_img>
					<button type=button background_img onclick="uploadcare.upload(uploaded)">
						<img src="<%= get_background_img_url(user_data) or "/images/nothing.svg" %>" >
					</button>
					<input type=hidden name="background_img_uuid" value="<%= user_data.background_img_uuid or "" %>">
					<input type=hidden name="background_img_filename" value="<%= user_data.background_img_filename or "" %>">
					<button type=button small onclick="uploadcare.upload(uploaded)">Add</button>
					<button type=button small onclick="clearImg()">Clear</button>
				</div>
				<label>Background Color</label>
<%				color_input(user_data,"background_color") %>
				<label>Button Color</label>
<%				color_input(user_data,"link_background_color") %>
				<label>Button Hover Color</label>
<%				color_input(user_data,"link_hover_background_color") %>
				<label>Button Text Color</label>
<%				color_input(user_data,"link_text_color") %>
				<label>Title Color</label>
<%				color_input(user_data,"title_color") %>
				<label>Bio Color</label>
<%				color_input(user_data,"bio_color") %>
				<label>Social Icon Color</label>
				<div>
					<label clickable black><% radio_input(user_data,"icon_color","") %>Black</label>
					&nbsp; &nbsp;
					<label clickable white><% radio_input(user_data,"icon_color","white") %>White</label>
				</div>
				<label>Button Shape</label>
<%
	local field = "link_border_radius"
	local value = user_data[field]
	value = value and html_encode(value)
	local default = fields[field]
	local value_or_default = value or default
%>
				<div>
					<span shape pulldown>
						<span onclick="clickMenu(this)">Select...</span>
						<div pulldown_menu>
							<a style="border-radius:22px / 50%" href="javascript:setField('<%=field%>','22px / 50%')">Link</a>
							<a style="border-radius:12px / 50%" href="javascript:setField('<%=field%>','12px / 50%')">Link</a>
							<a style="border-radius:10px" href="javascript:setField('<%=field%>','10px')">Link</a>
							<a style="border-radius:0" href="javascript:setField('<%=field%>','0')">Link</a>
							<a style="border-radius:10px 100px" href="javascript:setField('<%=field%>','10px 100px')">Link</a>
						</div>
					</span>
					<input type=text name="<%=field%>" value="<%= value or "" %>" placeholder="<%=default%>">
				</div>
				<label>Button Border Color</label>
<%				color_input(user_data,"link_border_color") %>
				<label>Button Shadow</label>
<%
	local field = "link_shadow"
	local value = user_data[field]
	value = value and html_encode(value)
	local default = fields[field]
	local value_or_default = value or default
%>
				<div>
					<span shape pulldown>
						<span onclick="clickMenu(this)">Select...</span>
						<div pulldown_menu>
							<a style="box-shadow:5px 5px 2px 1px" href="javascript:setField('<%=field%>','5px 5px 2px 1px')">Link</a>
							<a style="box-shadow:1px 1px 10px 1px" href="javascript:setField('<%=field%>','1px 1px 10px 1px')">Link</a>
						</div>
					</span>
					<input type=text name="<%=field%>" value="<%= value or "" %>" placeholder="<%=default%>">
				</div>
				<label>Button Shadow Color</label>
<%				color_input(user_data,"link_shadow_color") %>
				<label>Font</label>
<%
	local value = user_data.font
	value = value and html_encode(value)
	local value_url = user_data.font_url
	value_url = value_url and html_encode(value_url)
	local default = fields.font
	local explanation = fonts[value] and fonts[value].explanation or ""
%>
				<div font>
					<span pulldown>
						<span onclick="clickMenu(this)">Select...</span>
						<div pulldown_menu>
<%	for _, font in pairs(fonts) do %>
							<a style="font-family:<%=font.name%>" href="javascript:setFont('<%=font.name%>','<%=font.url%>','<%=font.explanation%>')"><%=font.title%></a>
<%	end %>
						</div>
					</span>
					<input type=text name="font" value="<%= value or "" %>" placeholder="<%=default%>">
					<input type=text name="font_url" value="<%= value_url or "" %>" placeholder="URL">
				</div>
				<div font_explanation><%=explanation%></div>
				<button type=submit big>Save</button>
<%
	local msg = message and message.info
%>
				<div success><%= msg or "" %></div>
			</form>
		</div>
<%		footer() %>
	</div>
	</body>
</html>
<%
end