xssbook/public/js/components.js
Tyler Murphy b6fbeb5124 fix seo
2023-02-13 22:41:09 -05:00

260 lines
11 KiB
JavaScript

import { div, a, pfp, span, i, parse, parseDate, p, form, input, svg, path, parseMonth } from './main.js'
import { postlike, postcomment, loadcommentspage } from './api.js';
window.parse = parse;
export function header(home, people, user_id) {
return [
div({id: 'header'},
span({class: 'logo'},
a({href: '/', 'aria-label': 'xssbook.com'},
parse('xssbook')
)
),
div({class: 'buttons'},
a({id: 'home', class: home ? 'selected' : '', href: '/home', 'aria-label': 'xssbook home page'},
svg({viewBox: '0 0 28 28', fill: 'currentColor', height: '28', width: '28'},
path({d: "M25.825 12.29C25.824 12.289 25.823 12.288 25.821 12.286L15.027 2.937C14.752 2.675 14.392 2.527 13.989 2.521 13.608 2.527 13.248 2.675 13.001 2.912L2.175 12.29C1.756 12.658 1.629 13.245 1.868 13.759 2.079 14.215 2.567 14.479 3.069 14.479L5 14.479 5 23.729C5 24.695 5.784 25.479 6.75 25.479L11 25.479C11.552 25.479 12 25.031 12 24.479L12 18.309C12 18.126 12.148 17.979 12.33 17.979L15.67 17.979C15.852 17.979 16 18.126 16 18.309L16 24.479C16 25.031 16.448 25.479 17 25.479L21.25 25.479C22.217 25.479 23 24.695 23 23.729L23 14.479 24.931 14.479C25.433 14.479 25.921 14.215 26.132 13.759 26.371 13.245 26.244 12.658 25.825 12.29"})
)
),
a({id: 'people', class: people ? 'selected' : '', href: '/people', 'aria-label': 'xssbook people page'},
svg({viewBox: '0 0 28 28', fill: 'currentColor', height: '28', width: '28'},
path({d: "M10.5 4.5c-2.272 0-2.75 1.768-2.75 3.25C7.75 9.542 8.983 11 10.5 11s2.75-1.458 2.75-3.25c0-1.482-.478-3.25-2.75-3.25zm0 8c-2.344 0-4.25-2.131-4.25-4.75C6.25 4.776 7.839 3 10.5 3s4.25 1.776 4.25 4.75c0 2.619-1.906 4.75-4.25 4.75zm9.5-6c-1.41 0-2.125.841-2.125 2.5 0 1.378.953 2.5 2.125 2.5 1.172 0 2.125-1.122 2.125-2.5 0-1.659-.715-2.5-2.125-2.5zm0 6.5c-1.999 0-3.625-1.794-3.625-4 0-2.467 1.389-4 3.625-4 2.236 0 3.625 1.533 3.625 4 0 2.206-1.626 4-3.625 4zm4.622 8a.887.887 0 00.878-.894c0-2.54-2.043-4.606-4.555-4.606h-1.86c-.643 0-1.265.148-1.844.413a6.226 6.226 0 011.76 4.336V21h5.621zm-7.122.562v-1.313a4.755 4.755 0 00-4.749-4.749H8.25A4.755 4.755 0 003.5 20.249v1.313c0 .518.421.938.937.938h12.125c.517 0 .938-.42.938-.938zM20.945 14C24.285 14 27 16.739 27 20.106a2.388 2.388 0 01-2.378 2.394h-5.81a2.44 2.44 0 01-2.25 1.5H4.437A2.44 2.44 0 012 21.562v-1.313A6.256 6.256 0 018.25 14h4.501a6.2 6.2 0 013.218.902A5.932 5.932 0 0119.084 14h1.861z"})
)
)
),
a({class: 'pfp', id: 'profile', href: '/profile', 'aria-label': 'your xssbook profile'},
user_id === undefined ? parse('') : pfp(user_id)
)
),
div({class: 'spacer'})
]
}
export function parsePost(post, users, self) {
let content = post.content
let date = post.date
let likes = post.likes
let author = users[post.user_id]
let comments = []
for (const comment of post.comments) {
comments.push(parseComment(comment, users))
}
let liked = post.liked;
var page = 0
return (
div({class: 'post', postid: post.post_id},
div({class: 'postheader'},
a({class: 'pfp', href: `/profile?id=${author.user_id}`, 'aria-label': 'Post author profile like'},
pfp(author.user_id)
),
div({class: 'postname'},
span({class: 'bold'},
parse(author.firstname + ' ' + author.lastname)
),
span({class: 'gtext mtext'},
parse(parseDate(new Date(date)))
)
)
),
p({class: 'mtext', style: "color: var(--text);"},
parse(content.replace(/\n/g,'<br>'))
),
span({class: 'gtext mtext likes'},
parse(`${likes} Likes`)
),
div({class: 'fullline nb'}),
div({class: 'postbuttons'},
span({class: 'likeclicky', onclick: async (event) => {
var post = event.target;
while(post.parentElement) {
post = post.parentElement
if (post.getAttribute('postid')) {
break;
}
}
let likes = post.getElementsByClassName('likes')[0]
let post_id = parseInt(post.getAttribute('postid'))
let like_text = likes.textContent;
let like_count = parseInt(like_text.substring(0, like_text.indexOf(" Likes")))
const response = await postlike(post_id, !liked)
if (response.status !== 200) { return }
liked = !liked
let el = post.getElementsByClassName('liketoggle')
if (liked) {
el[0].classList.add('blue')
el[1].classList.add('blue')
like_count++
} else {
el[0].classList.remove('blue')
el[1].classList.remove('blue')
like_count--
}
likes.textContent = like_count + " Likes"
}},
i({class: `liketoggle icons like ${liked ? 'blue' : ''}`}),
span({class: `liketoggle bold ${liked ? 'blue' : ''}`},
parse('Like')
)
),
span({onclick: (event) => {
var post = event.target;
while(post.parentElement) {
post = post.parentElement
if (post.getAttribute('postid')) {
break;
}
}
post.getElementsByClassName('comments')[0].getElementsByClassName('newcomment')[0].focus()
}},
i({class: 'icons comm'}),
span({class: 'bold'},
parse('Comment')
)
)
),
div({class: 'fullline nb', style: 'margin-top: 0'}),
div({class: 'comments'},
div({class: 'comment commentsubmit', style: 'margin-top: 0'}),
...comments,
comments.length > 0 ?
div({class: 'cload', style: 'justify-content: inherit; margin-left: 3.5em; font-size: .9em; margin-bottom: -.5em;'},
span({class: 'blod gtext', onclick: async (event) => {
page++;
const response = await loadcommentspage(page, post.post_id)
if (response.status != 200) { return };
let comments = response.json
for (const comment of comments) {
event.target.parentElement.parentElement.insertBefore(
parseComment(comment, users),
event.target.parentElement
)
}
if (comments.length < 5) {
event.target.parentElement.remove()
}
}},
parse('Load more comments')
)
)
: parse(''),
div({class: 'comment commentsubmit'},
a({class: 'pfp', href: '/profile', 'aria-label': 'Your profile link'},
pfp(self.user_id)
),
form({onsubmit: async (event) => {
event.preventDefault()
let text = event.target.elements.text.value.trim();
if (text.length < 1) {
return
}
let post = event.target.parentElement.parentElement.parentElement
let post_id = parseInt(post.getAttribute('postid'))
const response = await postcomment(post_id, text)
if (response.status != 200) { return };
let comment = {
user_id: self.user_id,
content: text,
date: Date.now()
}
let comments = post.getElementsByClassName('comments')[0]
let load = comments.getElementsByClassName('cload')[0];
if (load == undefined) {
load = comments.lastChild
}
comments.insertBefore(
parseComment(comment, users),
load
)
event.target.elements.text.value = ''
}},
input({type: 'text', name: 'text', placeholder: 'Write a comment', class: 'newcomment'})
)
)
)
)
)
}
export function parseComment(comment, users) {
let author = users[comment.user_id]
return (
div({class: 'comment'},
a({class: 'pfp', href: `/profile?id=${comment.user_id}`, 'aria-label': 'Comment author profile link'},
pfp(comment.user_id)
),
span({},
span({class: 'bold mtext'},
parse(author.firstname + ' ' + author.lastname),
span({class: 'gtext mtext', style: 'margin-left: 1em'},
parse(parseDate(new Date(comment.date)))
)
),
p({class: 'mtext'},
parse(comment.content)
)
)
)
)
}
export function parseUser(user) {
return (
a({class: 'person', href: `/profile?id=${user.user_id}`, 'aria-label': 'User profile link'},
div({class: 'profile'},
pfp(user.user_id)
),
div({class: 'info'},
span({class: 'bold ltext'},
parse(user.firstname + ' ' + user.lastname)
),
span({class: 'gtext'},
parse('Joined ' + parseDate(new Date(user.date)))
),
span({class: 'gtext'},
parse('Gender :' + user.gender)
),
span({class: 'gtext'},
parse('Birthday: ' + parseMonth(user.month) + ' ' + user.day + ', ' + user.year)
),
span({class: 'gtext', style: 'margin-bottom: -100px'},
parse('User ID: ' + user.user_id)
)
)
)
)
}