view src/links.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 ipairs = Luan.ipairs or error()
local Html = require "luan:Html.luan"
local html_encode = Html.encode or error()
local Table = require "luan:Table.luan"
local concat = Table.concat 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 show_editable_link = Shared.show_editable_link or error()
local User = require "site:/lib/User.luan"
local Link = require "site:/lib/Link.luan"
local get_owner_links = Link.get_owner_links or error()
local Pic = require "site:/lib/Pic.luan"
local Utils = require "site:/lib/Utils.luan"
local to_list = Utils.to_list or error()
local Logging = require "luan:logging/Logging.luan"
local logger = Logging.logger "links.html"


local function hashtags(pic)
	local hashtags = to_list(pic.hashtags)
	for i, hashtag in ipairs(hashtags) do
		hashtags[i] = "#"..hashtag
	end
	return concat(hashtags," ")
end

local function div_links(links,pic_id)
%>
		<div links>
			<form add onsubmit="ajaxForm('add_link.js',this)" action="javascript:">
<%	if pic_id ~= nil then %>
				<input type=hidden name=pic value="<%=pic_id%>">
<%	end %>
				<input type=text required name=title placeholder="Title">
				<input type=url required name=url placeholder="URL">
				<button type=submit big>Add link</button>
			</form>
			<div start></div>
<%	for _, link in ipairs(links) do
			show_editable_link(link)
	end %>
		</div>
<%
end

return function()
	local user = User.current_required()
	if user==nil then return end
	local owner = user
	local pic = Http.request.parameters.pic
	if pic ~= nil then
		pic = Pic.get_by_id(pic)
		if pic == nil then
			logger.warn("pic not found\n"..Http.request.raw_head)
			Http.response.send_error(404)
			return
		end
		pic.user_id == user.id or error()
		owner = pic
	end
	local links = get_owner_links(owner.id)
	local pic_id = pic and pic.id
	Io.stdout = Http.response.text_writer()
%>
<!doctype html>
<html lang="en">
	<head>
<%		head() %>
		<title>Link My Style</title>
		<style>
			form[add] {
				margin-bottom: 40px;
			}
			input {
				margin-bottom: 5px;
			}
			input[type="url"],
			input[type="text"] {
				display: block;
			}
			div[link] {
				margin-bottom: 20px;
			}
			button[small] {
				font-size: 12px;
			}
			div[delete2] p {
				margin-bottom: 5px;
			}

			div[link] > div:first-of-type {
				border-radius: 12px / 50%;
				margin-bottom: 5px;
				overflow: hidden;
				position: relative;
				border: 1px solid #ebebeb;
			}
			div[link] a {
				border-radius: initial;
				margin-bottom: initial;
			}
			div[link] a:hover {
				background-color: #243F47;
			}
			div[link] img {
				position: absolute;
				top: 0;
				height: 100%;
				background-color: white;
				opacity: 0.3;
				padding: 4px;
				touch-action: none;
			}

<%	if pic == nil then %>
			div[links] {
				margin-top: 20px;
			}
<%	else %>
			div[msg] {
				margin-top: 20px;
				margin-left: 5%;
				color: darkgreen;
<%		if Http.request.parameters.saved == nil then %>
				display: none;
<%		end %>
			}
			div[body] {
				margin-top: 40px;
				margin-bottom: 20px;
			}
			div[pic] img {
				width: 100%;
				display: block;
				margin-bottom: 5px;
			}
			div[pic] form {
				margin-top: 20px;
			}
			div[field] {
				margin-top: 1px;
				margin-bottom: 10px;
			}
			div[hashtags] {
				margin-top: 20px;
			}
			@media (min-width: 888px) {
				div[body] {
					display: flex;
				}
				div[pic] {
					width: 45%;
					margin-left: 5%;
				}
				div[outer_links] {
					width: 55%;
					margin-left: 5%;
					margin-right: 5%;
				}
			}
			@media (max-width: 887px) {
				div[pic] {
					display: block;
					width: 90%;
					margin-left: auto;
					margin-right: auto;
					margin-bottom: 40px;
				}
			}
<%	end %>
		</style>
		<script>
			'use strict';

			function clearAddForm() {
				let form = document.querySelector('form[add]');
				form.querySelector('[name="title"]').value = '';
				form.querySelector('[name="url"]').value = '';
			}

			function deleteLink1(button,linkId) {
				let div = button.parentNode;
				if( div.querySelector('div[delete2]') )
					return;
				let html = `
				<div delete2>
					<p>Are you sure that you want to delete this?</p>
					<button delete2 small onclick="deleteLink2('${linkId}')">Yes</button>
					<button small onclick="undelete1(this)">No</button>
				</div>
`				;
				div.insertAdjacentHTML( 'beforeEnd', html );
				div.scrollIntoViewIfNeeded(false);
			}
			function undelete1(button) {
				button.parentNode.outerHTML = '';
			}
			function deleteLink2(linkId) {
				ajax( '/delete_link.js?link='+linkId );
			}
			function deletePic1(button) {
				let div = button.parentNode;
				if( div.querySelector('div[delete2]') )
					return;
				let html = `
				<div delete2>
					<p>Are you sure that you want to delete this?</p>
					<button delete2 small onclick="deletePic2('<%=pic_id%>')">Yes</button>
					<button small onclick="undelete1(this)">No</button>
				</div>
`				;
				div.insertAdjacentHTML( 'beforeEnd', html );
				div.scrollIntoViewIfNeeded(false);
			}
			function deletePic2() {
				ajax( '/delete_pic.js?pic=<%=pic_id%>' );
			}

			function editLink(linkId) {
				ajax( '/edit_link.js?link='+linkId );
			}

			function cancel(linkId) {
				ajax( '/cancel_edit_link.js?link='+linkId );
			}

			dad.onDropped = function(event) {
				let dragging = event.original;
				if( iDragging === indexOf(dragging.parentNode.querySelectorAll(dropSelector),dragging) )
					return;
				let linkId = dragging.getAttribute('link');
				let prev = dragging.previousElementSibling;
				let prevId = prev && prev.getAttribute('link');
				ajax( '/move_link.js?link='+linkId+'&prev='+prevId );
			};

			dad.whatToDrag = function(draggable) {
				return draggable.parentNode.parentNode;
			};

			function dragInit() {
				dropSelector = 'div[link]';
				let items = document.querySelectorAll('div[link] img');
				for( let i=0; i<items.length; i++ ) {
					let item = items[i];
					dad.setDraggable(item);
					dad.setDropzone(item.parentNode.parentNode);
				}
			}

<%	if pic ~= nil then %>
			function changePic(uuid,filename) {
				ajax( '/change_pic.js', 'pic=<%=pic.id%>&uuid=' + uuid + '&filename=' + encodeURIComponent(filename) );
			}
			function startChangePic() {
				uploadcare.cropprOptions = {};
				uploadcare.upload(changePic);
			}
<%	end %>
		</script>
	</head>
	<body>
	<div full>
<%
	body_header()
	if pic == nil then
%>
		<p top>Enter your title and a URL to create a link. Once saved, you can drag-and-drop the icon on the left to change the order. The order on this page will also appear on your page.</p>
<%
		div_links(links,pic_id)
	else
%>
		<div back>
			<a href="/pics.html#p-<%=pic.id%>"><img src="/images/keyboard_backspace.svg"></a>
		</div>
		<div msg>
			Your image has been saved.
		</div>
		<div body>
			<div pic>
				<img <%=pic.title_attr()%> src="<%=pic.get_url()%>">
				<div>
					<button type=button small onclick="startChangePic()">Change</button>
					<button type=button small onclick="deletePic1(this)">Delete</button>
				</div>
				<div hashtags><%=pic.hashtags_html("pics.html")%></div>
				<form onsubmit="ajaxForm('/save_pic_title.js',this)" action="javascript:">
					<input type=hidden name=pic value="<%=pic_id%>">
					<label>Photo title</label>
					<div field>
						<input type=text required name=title placeholder="Title" value="<%= html_encode(pic.title or "") %>">
					</div>
					<label>Hashtags</label>
					<div field>
						<textarea name=hashtags placeholder="#hashtag1 #hashtag2"><%= hashtags(pic) %></textarea>
						<div error=hashtags></div>
					</div>
					<div field>
						<label clickable><input type=checkbox name=visible <%=pic.is_hidden and "" or "checked"%>> Visible</label>
					</div>
					<button type=submit small>Save</button>
					<div error=success></div>
				</form>
			</div>
			<div outer_links>
<%				div_links(links,pic_id) %>
			</div>
		</div>
<%
	end
%>
<%		footer() %>
	</div>
	<script> dragInit(); </script>
	</body>
</html>
<%
end