Mercurial Hosting > freedit
changeset 42:0c1b820fff34
use push
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 08 Nov 2022 14:02:28 -0700 |
parents | acb730710328 |
children | 298c71e0c854 |
files | src/delete.js.luan src/edit.js.luan src/lib/Post.luan src/lib/Shared.luan src/new_post.js.luan src/new_thread.html.luan src/save_edit.js.luan src/site.css src/site.js src/thread.html.luan |
diffstat | 10 files changed, 210 insertions(+), 69 deletions(-) [+] |
line wrap: on
line diff
--- a/src/delete.js.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/delete.js.luan Tue Nov 08 14:02:28 2022 -0700 @@ -1,22 +1,23 @@ local Luan = require "luan:Luan.luan" local error = Luan.error local Io = require "luan:Io.luan" +local output_of = Io.output_of or error() local Http = require "luan:http/Http.luan" local Post = require "site:/lib/Post.luan" -local Db = require "site:/lib/Db.luan" +local Shared = require "site:/lib/Shared.luan" +local base_url = Shared.base_url or error() return function() local post = Http.request.parameters.post or error() - Db.run_in_transaction( function() - post = Post.get_by_id(post) or error() - post.author_is_current() or error() - post.is_deleted = true - post.save() - end ) - Io.stdout = Http.response.text_writer() + post = Post.get_by_id(post) or error() + local root_id = post.root_id + post.delete() + local js = output_of(function() %> -let postDiv = document.querySelector('[post="<%=post.id%>"]'); -postDiv.querySelector('[output]').innerHTML = 'deleted'; +deleted( '<%=post.id%>', <%=Post.thread_size(root_id)%> ); <% + end) + local url = base_url().."/thread.html?root="..root_id + Http.push(url,js) end
--- a/src/edit.js.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/edit.js.luan Tue Nov 08 14:02:28 2022 -0700 @@ -19,6 +19,7 @@ postDiv.querySelector('[edit]').innerHTML = document.querySelector('[hidden][edit]').innerHTML; let textarea = postDiv.querySelector('textarea'); textarea.innerHTML = <%= json_string(html_encode(post.content)) %>; + fixTextarea(textarea); textarea.focus(); <% end
--- a/src/lib/Post.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/lib/Post.luan Tue Nov 08 14:02:28 2022 -0700 @@ -6,6 +6,8 @@ local time_now = Time.now or error() local Html = require "luan:Html.luan" local html_encode = Html.encode or error() +local Number = require "luan:Number.luan" +local long = Number.long or error() local Db = require "site:/lib/Db.luan" @@ -42,14 +44,10 @@ date = doc.date author_name = doc.post_author_name root_id = doc.post_root_id - is_deleted = doc.is_deleted == "true" + is_root = doc.post_is_root == "true" -- root only subject = doc.subject - is_root = doc.post_is_root == "true" - - -- replies only - parent_id = doc.parent_id } end @@ -58,17 +56,13 @@ type = "post" id = post.id content = post.content or error() - date = post.date or time_now() + date = long(post.date) post_author_name = post.author_name or error() - post_root_id = post.root_id - is_deleted = post.is_deleted and "true" or nil + post_root_id = long(post.root_id) + post_is_root = post.is_root and "true" or nil -- root only subject = post.subject - post_is_root = post.is_root and "true" or nil - - -- replies only - parent_id = post.parent_id } end @@ -88,6 +82,7 @@ end function Post.new(post) + post.date = post.date or time_now() function post.save() local doc = to_doc(post) @@ -95,16 +90,10 @@ post.id = doc.id end - function post.reply(author,content) - return Db.run_in_transaction( function() - local post = Post.new{ - root_id = post.root_id - parent_id = post.id - content = content - author_name = author.name - } - post.save() - return post + function post.delete() + Db.run_in_transaction( function() + not post.is_root or Post.thread_size(post.root_id) == 1 or error "can't delete root post with replies" + Db.delete("id:"..post.id) end ) end @@ -162,4 +151,8 @@ return posts end +function Post.thread_size(root_id) + return Db.count("post_root_id:"..root_id) +end + return Post
--- a/src/lib/Shared.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/lib/Shared.luan Tue Nov 08 14:02:28 2022 -0700 @@ -3,6 +3,8 @@ local ipairs = Luan.ipairs or error() local set_metatable = Luan.set_metatable or error() local type = Luan.type or error() +local Html = require "luan:Html.luan" +local html_encode = Html.encode or error() local Http = require "luan:http/Http.luan" local Io = require "luan:Io.luan" local uri = Io.uri or error() @@ -96,4 +98,35 @@ end end +local function delete_post() + %><a href="javascript:" onclick="deletePost(parentNode)">delete</a><% +end +Shared.delete_post = delete_post + +function Shared.show_post(post,now) + local Bbcode = require "site:/lib/Bbcode.luan" + local bbcode_to_html = Bbcode.to_html or error() +%> + <div post="<%=post.id%>"> + <hr> + <div author> + <img src="/images/profile.png"> + <a href="/whatever"><%= post.author_name %></a> + <span ago date="<%=post.date%>"><% post.ago(now) %> ago</span> + </div> + <div output> + <% bbcode_to_html(post.content) %> + <p logged_in> + <a href="#">reply</a> + <span only_user="<%=html_encode(post.author_name)%>"> + - <a href="javascript:ajax('/edit.js?post=<%=post.id%>')">edit</a> + <span delete_opton> - <span delete><%delete_post()%></span> </span> + <span> + </p> + </div> + <div edit></div> + </div> +<% +end + return Shared
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/new_post.js.luan Tue Nov 08 14:02:28 2022 -0700 @@ -0,0 +1,43 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local String = require "luan:String.luan" +local to_number = String.to_number or error() +local Time = require "luan:Time.luan" +local time_now = Time.now or error() +local Parsers = require "luan:Parsers.luan" +local json_string = Parsers.json_string or error() +local Io = require "luan:Io.luan" +local output_of = Io.output_of or error() +local Http = require "luan:http/Http.luan" +local User = require "site:/lib/User.luan" +local Post = require "site:/lib/Post.luan" +local Db = require "site:/lib/Db.luan" +local Shared = require "site:/lib/Shared.luan" +local base_url = Shared.base_url or error() +local show_post = Shared.show_post or error() +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "new_post.js" + + +return function() + local user = User.current() or error() + local root_id = Http.request.parameters.root or error() + local text = Http.request.parameters.text or error() + local post = Post.new{ + root_id = to_number(root_id) or error() + content = text + author_name = user.name + } + Db.run_in_transaction( function() + post.save() + end ) + local html = output_of(function() show_post(post,time_now()) end) + local js = output_of(function() +%> +added( '<%=post.id%>', <%= json_string(html) %>, <%=Post.thread_size(root_id)%> ); +console.log(<%=post.id%>); +<% + end) + local url = base_url().."/thread.html?root="..root_id + Http.push(url,js) +end
--- a/src/new_thread.html.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/new_thread.html.luan Tue Nov 08 14:02:28 2022 -0700 @@ -29,6 +29,18 @@ <head> <% head() %> <title><%=forum_title%>: new thread</title> + <style> + textarea { + width: 100%; + } + </style> + <script> + function uploaded(input,url,filename) { + let textarea = document.querySelector('textarea'); + textarea.focus(); + textarea.setRangeText(url,textarea.selectionStart,textarea.selectionEnd,'select'); + } + </script> </head> <body> <% header() %> @@ -39,7 +51,11 @@ <label>Subject</label> <input name=subject required> </p> - <p><textarea name=content></textarea></p> + <p><textarea name=content oninput="fixTextarea(this)"></textarea></p> + <p> + <input type=file onchange="upload(this,uploaded)"> + <button type=button onclick="fileButtonClick(this)">Upload File</button> + </p> <p><input type=submit></p> </form> </div>
--- a/src/save_edit.js.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/save_edit.js.luan Tue Nov 08 14:02:28 2022 -0700 @@ -9,6 +9,10 @@ local Bbcode = require "site:/lib/Bbcode.luan" local bbcode_to_html = Bbcode.to_html or error() local Db = require "site:/lib/Db.luan" +local Shared = require "site:/lib/Shared.luan" +local base_url = Shared.base_url or error() +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "save_edit.js" return function() @@ -21,10 +25,11 @@ post.save() end ) local html = output_of(function() bbcode_to_html(post.content) end) - Io.stdout = Http.response.text_writer() + local js = output_of(function() %> -let postDiv = document.querySelector('[post="<%=post.id%>"]'); -cancelEdit(postDiv); -postDiv.querySelector('[message]').innerHTML = <%= json_string(html) %>; +updated( '<%=post.id%>', <%= json_string(html) %> ); <% + end) + local url = base_url().."/thread.html?root="..post.root_id + Http.push(url,js) end
--- a/src/site.css Sun Nov 06 17:39:21 2022 -0700 +++ b/src/site.css Tue Nov 08 14:02:28 2022 -0700 @@ -19,6 +19,7 @@ font: inherit; padding: 7px; border-color: #DDDDDD; + box-sizing: content-box; } div[header], div[footer] {
--- a/src/site.js Sun Nov 06 17:39:21 2022 -0700 +++ b/src/site.js Tue Nov 08 14:02:28 2022 -0700 @@ -63,3 +63,10 @@ function fileButtonClick(button) { button.parentNode.querySelector('input[type="file"]').click(); } + +function fixTextarea(textarea) { + let height = textarea.scrollHeight; + if( height > textarea.clientHeight ) { + textarea.style.height = height + "px"; + } +}
--- a/src/thread.html.luan Sun Nov 06 17:39:21 2022 -0700 +++ b/src/thread.html.luan Tue Nov 08 14:02:28 2022 -0700 @@ -3,12 +3,16 @@ local ipairs = Luan.ipairs or error() local Time = require "luan:Time.luan" local time_now = Time.now 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 header = Shared.header or error() local footer = Shared.footer or error() +local delete_post = Shared.delete_post or error() +local show_post = Shared.show_post or error() local Forum = require "site:/lib/Forum.luan" local forum_title = Forum.title or error() local Db = require "site:/lib/Db.luan" @@ -18,10 +22,6 @@ local User = require "site:/lib/User.luan" -local function deletePost() - %><a href="javascript:" onclick="deletePost(parentNode)">delete</a><% -end - return function() local root_id = Http.request.parameters.root or error() local docs, total_hits = Db.search("post_root_id:"..root_id,1,1000,{sort="id"}) @@ -60,9 +60,28 @@ textarea { width: 100%; xmax-width: 450px; - height: 100px; + xheight: 100px; + } +<% if user_name == nil then %> + [logged_in] { + display: none; + } +<% end %> + [only_user] { + display: none; } - </style> +<% if user_name ~= nil then %> + [only_user="<%=html_encode(user_name)%>"] { + display: initial; + } +<% end %> + div[post]:first-of-type [delete_opton] { + display: none; + } + body[thread_size="1"] div[post]:first-of-type [delete_opton] { + display: initial; + } + </style> <script> function getPostDiv(node) { do { @@ -80,9 +99,31 @@ let postDiv = getPostDiv(src); let post = postDiv.getAttribute('post'); let text = postDiv.querySelector('textarea').value; + cancelEdit(src); let postData = 'post=' + post + '&text=' + encodeURIComponent(text); ajax('save_edit.js',postData); } + function updated(postId,html) { + let postDiv = document.querySelector('[post="'+postId+'"]'); + if(postDiv) + postDiv.querySelector('[message]').innerHTML = html; + } + + function newPost() { + let postDiv = document.querySelector('[post="new"]'); + let textarea = postDiv.querySelector('textarea') + let text = textarea.value; + textarea.value = ''; + let postData = 'root=<%=root_id%>&text=' + encodeURIComponent(text); + ajax('new_post.js',postData); + } + function added(postId,html,thread_size) { + if( document.querySelector('[post="'+postId+'"]') ) + return; + let newDiv = document.querySelector('[post="new"]'); + newDiv.insertAdjacentHTML('beforebegin',html); + document.body.setAttribute('thread_size',thread_size); + } function uploaded(input,url,filename) { let postDiv = getPostDiv(input); @@ -101,6 +142,13 @@ let post = getPostDiv(span).getAttribute('post'); ajax( '/delete.js?post=' + post ); } + function deleted(postId,thread_size) { + let postDiv = document.querySelector('[post="'+postId+'"]'); + if(!postDiv) + return + postDiv.outerHTML = ''; + document.body.setAttribute('thread_size',thread_size); + } function init() { let spans = document.querySelectorAll('span[ago]'); @@ -111,43 +159,36 @@ span.title = new Date(date).toLocaleString(); } } + + let eventSource = new EventSource(location.href); + eventSource.onmessage = function(event) { + eval( event.data ); + }; </script> </head> - <body onload="init()"> + <body onload="init()" thread_size="<%=Post.thread_size(root_id)%>"> <% header() %> <div content> <h1><%=subject_html%></h1> <% for _, post in ipairs(posts) do - if post.is_deleted then - continue - end -%> - <hr> - <div post="<%=post.id%>"> - <div author> - <img src="/images/profile.png"> - <a href="/whatever"><%= post.author_name %></a> - <span ago date="<%=post.date%>"><% post.ago(now) %> ago</span> - </div> - <div output> - <% bbcode_to_html(post.content) %> - <p> - <a href="/reply.html?parent=<%=post.id%>">reply</a> -<% if post.author_name == user_name then %> - - <a href="javascript:ajax('/edit.js?post=<%=post.id%>')">edit</a> - - <span delete><%deletePost()%></span> -<% end %> - </p> - </div> - <div edit></div> + show_post(post,now) + end %> + <div post=new logged_in> + <hr> + <textarea oninput="fixTextarea(this)"></textarea> + <p> + <input type=file onchange="upload(this,uploaded)"> + <button onclick="fileButtonClick(this)">Upload File</button> + <button onclick="newPost()">save</button> + </p> </div> -<% end %> </div> <% footer() %> + <span hidden delete>Delete? <a href="javascript:" onclick="deleteYes(parentNode)">yes</a> / <a href="javascript:" onclick="deleteNo(parentNode)">no</a></span> - <span hidden undelete><%deletePost()%></span> + <span hidden undelete><%delete_post()%></span> <div hidden edit> - <textarea></textarea> + <textarea oninput="fixTextarea(this)"></textarea> <p> <input type=file onchange="upload(this,uploaded)"> <button onclick="fileButtonClick(this)">Upload File</button>