diff options
Diffstat (limited to 'public/js')
| -rw-r--r-- | public/js/api.js | 57 | ||||
| -rw-r--r-- | public/js/header.js | 2 | ||||
| -rw-r--r-- | public/js/home.js | 144 | ||||
| -rw-r--r-- | public/js/login.js | 29 | ||||
| -rw-r--r-- | public/js/people.js | 48 | ||||
| -rw-r--r-- | public/js/profile.js | 88 |
6 files changed, 292 insertions, 76 deletions
diff --git a/public/js/api.js b/public/js/api.js new file mode 100644 index 0000000..371ecf3 --- /dev/null +++ b/public/js/api.js @@ -0,0 +1,57 @@ +const endpoint = 'https://xssbook.com/api' + +const request = async (url, body, method) => { + if (method === undefined) method = 'POST' + const response = await fetch(endpoint + url, { + method, + body: JSON.stringify(body), + headers: { + 'Content-Type': 'application/json' + } + }); + if (response.status == 401) { + location.href = 'login' + } + const json = await response.json() + return { status: response.status, msg: json.msg, json } +} + +const login = async (email, password) => { + return await request('/auth/login', {email, password}) +} + +const register = async (first, last, email, password, gender, month, day, year) => { + return await request('/auth/register', {first, last, email, password, gender, month, day, year}) +} + +const loadposts = async (page) => { + return await request('/posts/load', {page}) +} + +const loadusersposts = async (id) => { + return await request('/posts/user', {id}) +} + +const loadusers = async (ids) => { + return await request('/users/load', {ids}) +} + +const loadallusers = async () => { + return await request('/users/all', {}) +} + +const loadself = async () => { + return await request("/auth/self", {}) +} + +const postcomment = async (id, content) => { + return await request('/posts/comment', {id, content}, 'PUT') +} + +const postlike = async (id, state) => { + return await request('/posts/like', {id, state}, 'PUT') +} + +const createpost = async (content) => { + return await request('/posts/create', {content}) +}
\ No newline at end of file diff --git a/public/js/header.js b/public/js/header.js index 24643d6..8fe03e5 100644 --- a/public/js/header.js +++ b/public/js/header.js @@ -1,7 +1,7 @@ function header(home, people) { const html = ` <div id="header"> - <span class="logo">xssbook</span> + <span class="logo"><a href="/">xssbook</a></span> <div class="buttons"> <a id="home" ${home ? 'class="selected"' : ''} href="home"> <svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28"> diff --git a/public/js/home.js b/public/js/home.js index 289ce9b..e0186a8 100644 --- a/public/js/home.js +++ b/public/js/home.js @@ -5,22 +5,24 @@ function parseDate(date) { return months[date.getUTCMonth()] + ' ' + date.getUTCDate() + ', ' + date.getUTCFullYear() + ' ' + date.toLocaleTimeString(); } -function parseComment(data) { +function parseComment(comment) { + const author = data.users[comment.user] const html = ` <div class="comment"> <a class="pfp"> </a> <span> - <span class="bold mtext">${data.firstname + ' ' + data.lastname}</span> - <p class="mtext">${data.content}</p> + <span class="bold mtext">${author.first + ' ' + author.last}</span> + <p class="mtext">${comment.content}</p> </span> </div> ` return html } -function parsePost(post, likes) { +function parsePost(post) { + const author = data.users[post.user] const html = ` <div class="post" postid=${post.id}> <div class="postheader"> @@ -28,21 +30,21 @@ function parsePost(post, likes) { </a> <div class="postname"> - <span class="bold">${post.author.firstname + ' ' + post.author.lastname}</span> - <span class="gtext mtext">${parseDate(new Date(post.time))}</span> + <span class="bold">${author.first + ' ' + author.last}</span> + <span class="gtext mtext">${parseDate(new Date(post.date))}</span> </div> </div> <p class="mtext"> - ${post.content} + ${post.content.replace(/\n/g,'<br>')} </p> <span class="gtext mtext"> - ${post.likes} Likes + ${post.likes.length} Likes </span> <div class="fullline nb"></div> <div class="postbuttons"> <span onclick="like(this)"> - <i class="icons like ${likes.includes(post.id) ? 'blue' : ''}"></i> - <span class="bold ${likes.includes(post.id) ? 'blue' : ''}">Like</span> + <i class="icons like ${post.likes.includes(data.user.id) ? 'blue' : ''}"></i> + <span class="bold ${post.likes.includes(data.user.id) ? 'blue' : ''}">Like</span> </span> <span onclick="this.parentElement.parentElement.getElementsByClassName('newcomment')[0].focus()"> <i class="icons comm"></i> @@ -76,53 +78,60 @@ function getPost(id) { return -1 } -function like(span) { +async function like(span) { const id = parseInt(span.parentElement.parentElement.getAttribute('postid')) - const index = data.user.likes.indexOf(id) - if (index === -1) { - data.user.likes.push(id) - data.posts[getPost(id)].likes++ + const post = data.posts[getPost(id)] + const index = post.likes.indexOf(data.user.id) + const state = index === -1; + const response = await postlike(id, state) + if (response.status != 200) return; + if (index == -1) { + post.likes.push(data.user.id) } else { - data.user.likes.splice(index, 1) - data.posts[getPost(id)].likes-- + post.likes.splice(index, 1) } - load() + render() } -function comment(event) { +async function comment(event) { event.preventDefault(); const text = event.target.elements.text.value.trim(); if (text.length < 1) return; const id = parseInt(event.target.parentElement.parentElement.parentElement.getAttribute('postid')) var index = getPost(id); - console.log(index) if (index === -1) return; + const response = await postcomment(id, text) + if (response.status != 200) return; + event.target.elements.text.value = ''; data.posts[index].comments.push({ - firstname: data.user.firstname, - lastname: data.user.lastname, + user: data.user.id, content: text }) - load() + render() } -function post(event) { +async function post() { const text = document.getElementById("text").value.trim() + const error = document.getElementsByClassName('error')[0] if (text.length < 1) return; + const response = await createpost(text); + if (response.status != 200) { + error.innerHTML = response.msg + return; + } + error.innerHTML = ''; data.posts.unshift({ id: data.posts[0].id + 1, - author: { - firstname: data.user.firstname, - lastname: data.user.lastname - }, - time: Date.now(), + user: data.user.id, + date: Date.now(), content: text, - likes: 0, + likes: [], comments: [] }) - load() + render() } -function load() { +function render() { const html = ` <div id="posts"> <div class="create"> @@ -131,11 +140,11 @@ function load() { </a> <button class="pfp"> <p class="gtext" onclick="document.getElementById('popup').classList.remove('hidden')"> - What's on your mind, ${data.user.firstname}? + What's on your mind, ${data.user.first}? </p> </button> </div> - ${data.posts.map(p => parsePost(p, data.user.likes)).join('')} + ${data.posts.map(p => parsePost(p)).join('')} </div> ` @@ -152,11 +161,12 @@ function load() { </a> <div class="postname"> - <span class="bold">${data.user.firstname + ' ' + data.user.lastname}</span>and ho + <span class="bold">${data.user.first + ' ' + data.user.last}</span> <span class="gtext mtext">Now</span> </div> </div> - <textarea type="text" name="text" id="text" placeholder="What's on your mind, ${data.user.firstname}?"></textarea> + <textarea type="text" name="text" id="text" placeholder="What's on your mind, ${data.user.first}?"></textarea> + <span class="error ctext" style="padding-bottom: 15px; margin-top: -30px;"></span> <button class="primary" onclick="post(this)">Post</button> </div> </div> @@ -165,43 +175,29 @@ function load() { add(popup, 'popup') } -var data = { - user: { - firstname: 'John', - lastname: 'Doe', - likes: [1] - }, - posts: [ - { - id: 1, - author: { - firstname: 'Joe', - lastname: 'Biden', - }, - time: 1674269687905, - content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', - likes: 2, - comments: [], - }, - { - id: 0, - author: { - firstname: 'Amazon', - lastname: 'Employee', - }, - time: 0, - content: 'I dont like working at amazon >:(', - likes: 69, - comments: [ - { - firstname: 'Jeff', - lastname: 'Bezos', - content: 'You\'re fired.' - }, - ], - } - ] +var page = 0 +const data = { + user: {}, + users: {}, + posts: [] } -header(true, false) -load();
\ No newline at end of file +async function load() { + header(true, false) + const posts = (await loadposts(page)).json + page++; + data.posts.push(... posts) + const batch = [] + for (const post of posts) { + if (data.users[post.user] !== undefined) continue + if (batch.includes(post.user)) continue + batch.push(post.user) + } + const users = (await loadusers(batch)).json + for (const id in users) { + data.users[id] = users[id] + } + data.user = (await loadself()).json + data.users[data.user.id] = data.user + render() +}
\ No newline at end of file diff --git a/public/js/login.js b/public/js/login.js new file mode 100644 index 0000000..5d51299 --- /dev/null +++ b/public/js/login.js @@ -0,0 +1,29 @@ +async function onlogin() { + const email = document.getElementById('email').value + const password = document.getElementById('pass').value + const response = await login(email, password) + if (response.status !== 200) { + const error = document.getElementsByClassName('error')[0] + error.innerHTML = response.msg + } else { + location.href = '/home' + } +} + +async function onregister() { + const first = document.getElementById('firstname').value + const last = document.getElementById('lastname').value + const email = document.getElementById('newemail').value + const pass = document.getElementById('newpass').value + const month = document.getElementById('month').value + const day = document.getElementById('day').value + const year = document.getElementById('year').value + const gender = document.querySelector('input[name="gender"]:checked').value + const response = await register(first, last, email, pass, gender, month, parseInt(day), parseInt(year)) + if (response.status !== 200) { + const error = document.getElementsByClassName('error')[1] + error.innerHTML = response.msg + } else { + location.href = '/home' + } +}
\ No newline at end of file diff --git a/public/js/people.js b/public/js/people.js index 992fd45..415dd16 100644 --- a/public/js/people.js +++ b/public/js/people.js @@ -1 +1,47 @@ -header(false, true)
\ No newline at end of file +function parseDate(date) { + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + + return months[date.getUTCMonth()] + ' ' + date.getUTCDate() + ', ' + date.getUTCFullYear() + ' ' + date.toLocaleTimeString(); +} + +function parseUser(user) { + const html = ` + <a class="person" href="/profile?id=${user.id}"> + <div class="profile"> + + </div> + <div class="info"> + <span class="bold ltext">${user.first + ' ' + user.last}</span> + <span class="gtext">Joined ${parseDate(new Date(user.date))}</span> + <span class="gtext">Gender: ${user.gender}</span> + <span class="gtext">Birthday: ${user.month + ' ' + user.day + ', ' + user.year}</span> + </div> + </a> + ` + return html +} + +function render() { + const html = ` + <div id="users"> + ${data.users.map(u => parseUser(u)).join('')} + </div> + ` + + add(html, 'usres') +} + +var data = { + users: [] +} + +async function load() { + const users = (await loadallusers()).json + console.log(users) + data.users = users + render() +} + +header(false, true) +load()
\ No newline at end of file diff --git a/public/js/profile.js b/public/js/profile.js new file mode 100644 index 0000000..63d2ec0 --- /dev/null +++ b/public/js/profile.js @@ -0,0 +1,88 @@ +function render() { + const html = ` + <div id="top"> + <div id="banner"> + <div> + + </div> + </div> + <div id="info"> + <div class="face"> + + </div> + <div class="infodata"> + <span class="bold ltext">${data.user.first + ' ' + data.user.last}</span> + <span class="gtext">Joined ${parseDate(new Date(data.user.date))}</span> + </div> + </div> + <div class="fullline" style="width: 80em; margin-bottom: 0;"></div> + <div class="profilebuttons"> + <button class="${posts ? 'selected' : ''}" onclick="posts = true; render()"> + Posts + </button> + <button class="${posts ? '' : 'selected'}" onclick="posts = false; render()"> + About + </button> + </div> + </div> + ` + + add(html, 'top') + + const postsh = ` + <div id="posts" class="${posts ? '' : 'hidden'}"> + ${data.posts.map(p => parsePost(p)).join('')} + </div> + ` + + add(postsh, 'posts') + + const about = ` + <div id="about" class="post ${posts ? 'hidden' : ''}"> + <span class="bold ltext">About</span> + <div class="data"> + <span class="gtext bold">Name: ${data.user.first + ' ' + data.user.last}</span> + <span class="gtext bold">Email: ${data.user.email}</span> + <span class="gtext bold">Gender: ${data.user.gender}</span> + <span class="gtext bold">Birthday: ${data.user.month + ' ' + data.user.day + ', ' + data.user.year}</span> + <span class="gtext bold">User ID: ${data.user.id}</span> + </div> + </div> + ` + + add(about, 'about') +} + +var posts = true + +async function load() { + header(false, false) + + var params = {}; + for (const [key, value] of new URLSearchParams(location.search)) { + params[key] = value + } + + const id = params.id !== undefined && !isNaN(params.id) ? parseInt(params.id) : (await loadself()).json.id + const posts = (await loadusersposts(id)).json + data.posts.push(... posts) + const batch = [id] + for (const post of posts) { + for(const comment of post.comments) { + if (data.users[comment.user] !== undefined) continue + if (batch.includes(comment.user)) continue + batch.push(comment.user) + } + if (data.users[post.user] !== undefined) continue + if (batch.includes(post.user)) continue + batch.push(post.user) + } + const users = (await loadusers(batch)).json + for (const id in users) { + data.users[id] = users[id] + } + data.user = data.users[id] + render() +} + +load()
\ No newline at end of file |