Mercurial Hosting > linkmystyle
diff src/links.html.luan @ 0:8f4df159f06b
start public repo
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 11 Jul 2025 20:57:49 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/links.html.luan Fri Jul 11 20:57:49 2025 -0600 @@ -0,0 +1,324 @@ +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