Mercurial Hosting > linkmystyle
comparison src/account.html.luan @ 0:8f4df159f06b
start public repo
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Fri, 11 Jul 2025 20:57:49 -0600 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:8f4df159f06b |
|---|---|
| 1 local Luan = require "luan:Luan.luan" | |
| 2 local error = Luan.error | |
| 3 local Html = require "luan:Html.luan" | |
| 4 local html_encode = Html.encode or error() | |
| 5 local Io = require "luan:Io.luan" | |
| 6 local Http = require "luan:http/Http.luan" | |
| 7 local Shared = require "site:/lib/Shared.luan" | |
| 8 local head = Shared.head or error() | |
| 9 local body_header = Shared.body_header or error() | |
| 10 local footer = Shared.footer or error() | |
| 11 local show_user_icons = Shared.show_user_icons or error() | |
| 12 local password_input = Shared.password_input or error() | |
| 13 local User = require "site:/lib/User.luan" | |
| 14 local Logging = require "luan:logging/Logging.luan" | |
| 15 local logger = Logging.logger "account.html" | |
| 16 | |
| 17 | |
| 18 return function() | |
| 19 local user = User.current_required() | |
| 20 if user==nil then return end | |
| 21 local title = user.title | |
| 22 local bio = user.bio | |
| 23 local username = user.name | |
| 24 local password = user.password | |
| 25 local email = user.email | |
| 26 local mp_id = user.mp_id | |
| 27 Io.stdout = Http.response.text_writer() | |
| 28 %> | |
| 29 <!doctype html> | |
| 30 <html lang="en"> | |
| 31 <head> | |
| 32 <% head() %> | |
| 33 <title>Link My Style</title> | |
| 34 <style> | |
| 35 h1 { | |
| 36 text-align: center; | |
| 37 } | |
| 38 div[body] { | |
| 39 max-width: 600px; | |
| 40 margin-left: auto; | |
| 41 margin-right: auto; | |
| 42 } | |
| 43 @media (max-width: 700px) { | |
| 44 div[body] { | |
| 45 max-width: 90%; | |
| 46 } | |
| 47 } | |
| 48 div[body] > * { | |
| 49 margin-bottom: 64px; | |
| 50 } | |
| 51 h2 { | |
| 52 margin-top: 20px; | |
| 53 margin-bottom: 20px !important; | |
| 54 } | |
| 55 label { | |
| 56 display: block; | |
| 57 } | |
| 58 div[field] { | |
| 59 margin-bottom: 10px; | |
| 60 } | |
| 61 button[delete1] { | |
| 62 background-color: red; | |
| 63 } | |
| 64 button[delete1]:hover, | |
| 65 button[delete2]:hover { | |
| 66 background-color: #7F1B1B; | |
| 67 } | |
| 68 div[delete2] { | |
| 69 display: none; | |
| 70 } | |
| 71 | |
| 72 div[pic] { | |
| 73 display: flex; | |
| 74 margin-bottom: 20px; | |
| 75 } | |
| 76 div[pic] img { | |
| 77 width: 100px; | |
| 78 height: 100px; | |
| 79 object-fit: cover; | |
| 80 border-radius: 50%; | |
| 81 background-color: grey; | |
| 82 flex-shrink: 0; | |
| 83 } | |
| 84 div[pic] div { | |
| 85 width: 100%; | |
| 86 display: flex; | |
| 87 flex-direction: column; | |
| 88 align-items: center; | |
| 89 justify-content: space-around; | |
| 90 } | |
| 91 div[pic] button { | |
| 92 width: 90%; | |
| 93 } | |
| 94 | |
| 95 div[icons] div[list] { | |
| 96 display: flex; | |
| 97 gap: 5px; | |
| 98 flex-wrap: wrap; | |
| 99 margin-bottom: 8px; | |
| 100 } | |
| 101 span[icon] { | |
| 102 border: 1px solid; | |
| 103 display: flex; | |
| 104 padding-right: 4px; | |
| 105 } | |
| 106 span[icon] img { | |
| 107 display: block; | |
| 108 height: 40px; | |
| 109 } | |
| 110 span[icon] > img { | |
| 111 opacity: 0.3; | |
| 112 touch-action: none; | |
| 113 } | |
| 114 </style> | |
| 115 <script> | |
| 116 'use strict'; | |
| 117 | |
| 118 function delete1() { | |
| 119 let delete2 = document.querySelector('div[delete2]'); | |
| 120 delete2.style.display = 'block'; | |
| 121 delete2.scrollIntoViewIfNeeded(false); | |
| 122 } | |
| 123 function undelete1() { | |
| 124 document.querySelector('div[delete2]').style.display = 'none'; | |
| 125 } | |
| 126 function delete2() { | |
| 127 ajax( '/delete_user.js' ); | |
| 128 } | |
| 129 | |
| 130 function removePic() { | |
| 131 let img = document.querySelector('div[pic] img'); | |
| 132 img.src = '/images/nothing.svg'; | |
| 133 let pic_uuid = document.querySelector('input[name="pic_uuid"]'); | |
| 134 pic_uuid.value = 'remove'; | |
| 135 } | |
| 136 function uploaded(uuid,filename) { | |
| 137 document.querySelector('input[name="pic_uuid"]').value = uuid; | |
| 138 document.querySelector('input[name="pic_filename"]').value = filename; | |
| 139 let img = document.querySelector('div[pic] img'); | |
| 140 img.src = uploadcareUrl(uuid); | |
| 141 } | |
| 142 function startUpload() { | |
| 143 uploadcare.cropprOptions = {aspectRatio: 1}; | |
| 144 uploadcare.upload(uploaded); | |
| 145 } | |
| 146 | |
| 147 dad.onDropped = function(event) { | |
| 148 let dragging = event.original; | |
| 149 if( iDragging === indexOf(dragging.parentNode.querySelectorAll(dropSelector),dragging) ) | |
| 150 return; | |
| 151 let iconId = dragging.getAttribute('icon'); | |
| 152 let prev = dragging.previousElementSibling; | |
| 153 let prevId = prev && prev.getAttribute('icon'); | |
| 154 ajax( '/move_icon.js?icon='+iconId+'&prev='+prevId ); | |
| 155 }; | |
| 156 dad.whatToDrag = function(draggable) { | |
| 157 return draggable.parentNode; | |
| 158 }; | |
| 159 function dragInit() { | |
| 160 dropSelector = 'span[icon]'; | |
| 161 let items = document.querySelectorAll('span[icon] > img'); | |
| 162 for( let i=0; i<items.length; i++ ) { | |
| 163 let item = items[i]; | |
| 164 dad.setDraggable(item); | |
| 165 dad.setDropzone(item.parentNode); | |
| 166 } | |
| 167 } | |
| 168 </script> | |
| 169 </head> | |
| 170 <body> | |
| 171 <div full> | |
| 172 <% body_header() %> | |
| 173 <h1>My Account</h1> | |
| 174 <div body> | |
| 175 <form onsubmit="ajaxForm('/save_account.js',this)" action="javascript:"> | |
| 176 <h2>My information</h2> | |
| 177 <div pic> | |
| 178 <img src="<%= user.get_pic_url() or "/images/nothing.svg" %>"> | |
| 179 <div> | |
| 180 <input type=hidden name="pic_uuid"> | |
| 181 <input type=hidden name="pic_filename"> | |
| 182 <button type=button big onclick="startUpload()">Pick an image</button> | |
| 183 <button type=button big onclick="removePic()">Remove</button> | |
| 184 </div> | |
| 185 </div> | |
| 186 <label>Profile Title</label> | |
| 187 <div field> | |
| 188 <input type=text name=title value="<%= html_encode(title or username) %>"> | |
| 189 </div> | |
| 190 <label>Profile Bio</label> | |
| 191 <div field> | |
| 192 <textarea name=bio><%= html_encode(bio or "") %></textarea> | |
| 193 </div> | |
| 194 <label>Username</label> | |
| 195 <div field> | |
| 196 <input type=text required name=username placeholder="Username" value="<%= username %>"> | |
| 197 <div error=username></div> | |
| 198 </div> | |
| 199 <label>Password</label> | |
| 200 <div field> | |
| 201 <% password_input(password) %> | |
| 202 </div> | |
| 203 <button type=submit big>Save</button> | |
| 204 <div error=success></div> | |
| 205 </form> | |
| 206 | |
| 207 <% | |
| 208 %> | |
| 209 <h2 icons>Social icons</h2> | |
| 210 <div icons> | |
| 211 <% show_user_icons(user) %> | |
| 212 </div> | |
| 213 | |
| 214 <form onsubmit="ajaxForm('/save_email.js',this)" action="javascript:"> | |
| 215 <h2>My email</h2> | |
| 216 <label>Email</label> | |
| 217 <div field> | |
| 218 <input type=email required name=email placeholder="Email" value="<%= email %>"> | |
| 219 <div error=email></div> | |
| 220 </div> | |
| 221 <button type=submit big>Change</button> | |
| 222 </form> | |
| 223 | |
| 224 <form onsubmit="ajaxForm('/save_mp.js',this)" action="javascript:"> | |
| 225 <h2>Custom analytics</h2> | |
| 226 <label>Mixpanel Project Token</label> | |
| 227 <div field> | |
| 228 <input type=text name=mp_id value="<%= html_encode(mp_id or "") %>"> | |
| 229 </div> | |
| 230 <button type=submit big>Save</button> | |
| 231 <div error=success></div> | |
| 232 </form> | |
| 233 | |
| 234 <div> | |
| 235 <h2>Delete account</h2> | |
| 236 <button type=button delete1 big onclick="delete1()">Delete account</button> | |
| 237 <div delete2> | |
| 238 <p>Are you sure that you want to delete this account?</p> | |
| 239 <button type=button delete2 small onclick="delete2()">Yes</button> | |
| 240 <button type=button small onclick="undelete1()">No</button> | |
| 241 </div> | |
| 242 </div> | |
| 243 </div> | |
| 244 <% footer() %> | |
| 245 </div> | |
| 246 </body> | |
| 247 <script> dragInit(); </script> | |
| 248 </html> | |
| 249 <% | |
| 250 end |
