From 3bbbcaa19f6e5e6bb6e6146f9410d52cad58b516 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:54:22 +0100 Subject: [PATCH 01/29] edited some html and added registration function --- index.html | 178 ++++------------------------------- profile/login/index.html | 97 +++++++++++++++++++ profile/register/index.html | 109 +++++++++++++++++++++ profile/register/index.js | 43 +++++++++ src/js/api/auth/register.mjs | 20 ++++ src/js/api/constants.mjs | 4 + src/js/handlers/register.mjs | 15 +++ src/js/index.mjs | 3 + 8 files changed, 310 insertions(+), 159 deletions(-) create mode 100644 profile/login/index.html create mode 100644 profile/register/index.html create mode 100644 profile/register/index.js create mode 100644 src/js/api/auth/register.mjs create mode 100644 src/js/api/constants.mjs create mode 100644 src/js/handlers/register.mjs create mode 100644 src/js/index.mjs diff --git a/index.html b/index.html index 06409846a..7d5852aed 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ - Sign In | Hello! + Welcome | Hello! @@ -10,12 +10,13 @@ integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous" > +
-
+

Everything begins at
Hello!
@@ -23,174 +24,33 @@

Sign in to say hello to your friends and to make new friends!

+
-

Not a member yet?

+

Not a member yet?

- +

- -
-
-

Sign in

-
-
-
- - -
-
- Please fill in a valid email address. -
-
- -
- - -
-
- The password needs to contain 8 characters. -
-
- -
- -
-
-
- - diff --git a/profile/login/index.html b/profile/login/index.html new file mode 100644 index 000000000..b3d888fac --- /dev/null +++ b/profile/login/index.html @@ -0,0 +1,97 @@ + + + Sign In | Hello! + + + + + + + +
+ + +
+
+
+
+
+

Sign in

+
+
+
+ + +
+
+ Please fill in a valid email address. +
+
+ +
+ + +
+
+ The password needs to contain 8 characters. +
+
+ +
+ +
+
+
+

Not a member yet?

+ +
+
+
+
+
+
+ + diff --git a/profile/register/index.html b/profile/register/index.html new file mode 100644 index 000000000..d2ff8f6b6 --- /dev/null +++ b/profile/register/index.html @@ -0,0 +1,109 @@ + + + Sign In | Hello! + + + + + + + + +
+ + +
+
+
+
+

Register user

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+

Already a member?

+ +
+
+
+
+
+ + diff --git a/profile/register/index.js b/profile/register/index.js new file mode 100644 index 000000000..6de680dbd --- /dev/null +++ b/profile/register/index.js @@ -0,0 +1,43 @@ +import { API_SOCIAL_URL } from "../../src/js/api/api.js"; + +const registerUserForm = document.querySelector("#registerUserForm"); +const name = document.querySelector("#name"); +const email = document.querySelector("#email"); +const password = document.querySelector("#password"); + +/** + * API call that registers the user + * @param {string} url + * @param {any} userData + * ``` js + * registerUser(registerUrl, userToRegister); + */ + +async function registerUser(url, userData) { + console.log(url, userData); + try { + const postData = { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(userData), + }; + const response = await fetch(url, postData); + console.log(response); + const json = await response.json(); + console.log(json); + } catch (error) { + console.log(error); + } +} + +const userToRegister = { + name: "my_username", + email: "first.last@stud.noroff.no", + password: "UzI1NiIsInR5cCI", +}; + +const registerUrl = `${API_SOCIAL_URL}/auth/register`; + +registerUser(registerUrl, userToRegister); diff --git a/src/js/api/auth/register.mjs b/src/js/api/auth/register.mjs new file mode 100644 index 000000000..cbc3f0c6f --- /dev/null +++ b/src/js/api/auth/register.mjs @@ -0,0 +1,20 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; + +const action = "/auth/register"; +const method = "post"; + +export async function register(profile) { + const registerURL = API_SOCIAL_URL + action; + console.log(registerURL); + + const response = await fetch(registerURL, { + headers: { + "Content-Type": "application/json", + }, + method, + body: JSON.stringify(profile), + }); + + const result = await response.json(); + console.log(result); +} diff --git a/src/js/api/constants.mjs b/src/js/api/constants.mjs new file mode 100644 index 000000000..dfe3040b7 --- /dev/null +++ b/src/js/api/constants.mjs @@ -0,0 +1,4 @@ +export const API_HOST_URL = "https://api.noroff.dev"; +export const API_BASE = "/api/v1"; +export const API_SOCIAL_BASE = "/social"; +export const API_SOCIAL_URL = `${API_HOST_URL}${API_BASE}${API_SOCIAL_BASE}`; diff --git a/src/js/handlers/register.mjs b/src/js/handlers/register.mjs new file mode 100644 index 000000000..c0a386a79 --- /dev/null +++ b/src/js/handlers/register.mjs @@ -0,0 +1,15 @@ +import { register } from "../api/auth/register.mjs"; + +export function setRegisterFormListener() { + const form = document.querySelector("#registerForm"); + + form.addEventListener("submit", (event) => { + event.preventDefault(); + const form = event.target; + const formData = new FormData(form); + const profile = Object.fromEntries(formData.entries()); + console.log(profile); + + register(profile); + }); +} diff --git a/src/js/index.mjs b/src/js/index.mjs new file mode 100644 index 000000000..64565145d --- /dev/null +++ b/src/js/index.mjs @@ -0,0 +1,3 @@ +import { setRegisterFormListener } from "./handlers/register.mjs"; + +setRegisterFormListener(); From 06bc32bf4fa13aa8c17c360e583055b3861f119d Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Sun, 3 Dec 2023 17:13:42 +0100 Subject: [PATCH 02/29] small tweaks on html and added login functionality --- index.html | 6 +- profile/login/index.html | 116 ++++++++++++++++------------------- profile/register/index.html | 8 +-- profile/register/index.js | 43 ------------- src/js/api/auth/login.mjs | 23 +++++++ src/js/api/auth/register.mjs | 1 + src/js/handlers/login.mjs | 17 +++++ src/js/handlers/register.mjs | 18 +++--- src/js/index.mjs | 9 ++- src/js/storage/index.mjs | 16 +++++ 10 files changed, 135 insertions(+), 122 deletions(-) delete mode 100644 profile/register/index.js create mode 100644 src/js/api/auth/login.mjs create mode 100644 src/js/handlers/login.mjs create mode 100644 src/js/storage/index.mjs diff --git a/index.html b/index.html index 7d5852aed..f406e4597 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous" > - +
@@ -26,7 +26,7 @@

Not a member yet?

+
@@ -21,72 +22,61 @@
-
-
-
-
-
-

Sign in

+
+
+ -
-
-
+
+
+

Register user

@@ -92,7 +92,7 @@

Register user

Already a member?

{ + event.preventDefault(); + const form = event.target; + const formData = new FormData(form); + const profile = Object.fromEntries(formData.entries()); + console.log(profile); + + login(profile); + }); + } +} diff --git a/src/js/handlers/register.mjs b/src/js/handlers/register.mjs index c0a386a79..78dabe615 100644 --- a/src/js/handlers/register.mjs +++ b/src/js/handlers/register.mjs @@ -3,13 +3,15 @@ import { register } from "../api/auth/register.mjs"; export function setRegisterFormListener() { const form = document.querySelector("#registerForm"); - form.addEventListener("submit", (event) => { - event.preventDefault(); - const form = event.target; - const formData = new FormData(form); - const profile = Object.fromEntries(formData.entries()); - console.log(profile); + if (form) { + form.addEventListener("submit", (event) => { + event.preventDefault(); + const form = event.target; + const formData = new FormData(form); + const profile = Object.fromEntries(formData.entries()); + console.log(profile); - register(profile); - }); + register(profile); + }); + } } diff --git a/src/js/index.mjs b/src/js/index.mjs index 64565145d..1071e9556 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,3 +1,10 @@ import { setRegisterFormListener } from "./handlers/register.mjs"; +import { setLoginFormListener } from "./handlers/login.mjs"; -setRegisterFormListener(); +const path = location.pathname; + +if (path === "/profile/login/") { + setLoginFormListener(); +} else if (path === "/profile/register/") { + setRegisterFormListener(); +} diff --git a/src/js/storage/index.mjs b/src/js/storage/index.mjs new file mode 100644 index 000000000..e3df9819a --- /dev/null +++ b/src/js/storage/index.mjs @@ -0,0 +1,16 @@ +export function save(key, value) { + localStorage.setItem(key, JSON.stringify(value)); +} + +export function load(key) { + try { + const value = localStorage.getItem(key); + return JSON.parse(value); + } catch { + return null; + } +} + +export function remove(key) { + localStorage.removeItem(key); +} From 911aedfff9a7b5660ffac8bc09e874cb6b53b224 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:46:24 +0100 Subject: [PATCH 03/29] Added js funcionality for posts - Get post - Get posts - Delete post - Update post - Also removed console.logs --- index.html | 3 +-- src/js/api/auth/login.mjs | 1 - src/js/api/auth/register.mjs | 2 -- src/js/api/authFetch.mjs | 17 +++++++++++++++++ src/js/api/posts/create.mjs | 16 ++++++++++++++++ src/js/api/posts/get.mjs | 24 ++++++++++++++++++++++++ src/js/api/posts/index.mjs | 4 ++++ src/js/api/posts/remove.mjs | 19 +++++++++++++++++++ src/js/api/posts/update.mjs | 20 ++++++++++++++++++++ src/js/handlers/login.mjs | 1 - src/js/handlers/register.mjs | 1 - src/js/index.mjs | 21 +++++++++++++++++++++ 12 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 src/js/api/authFetch.mjs create mode 100644 src/js/api/posts/create.mjs create mode 100644 src/js/api/posts/get.mjs create mode 100644 src/js/api/posts/index.mjs create mode 100644 src/js/api/posts/remove.mjs create mode 100644 src/js/api/posts/update.mjs diff --git a/index.html b/index.html index f406e4597..7da544d06 100644 --- a/index.html +++ b/index.html @@ -7,8 +7,7 @@ diff --git a/src/js/api/auth/login.mjs b/src/js/api/auth/login.mjs index e05df38d2..e6e37b8cd 100644 --- a/src/js/api/auth/login.mjs +++ b/src/js/api/auth/login.mjs @@ -6,7 +6,6 @@ const method = "post"; export async function login(profile) { const loginURL = API_SOCIAL_URL + action; - console.log(loginURL); const response = await fetch(loginURL, { headers: { diff --git a/src/js/api/auth/register.mjs b/src/js/api/auth/register.mjs index 7fb3de9d5..cc0a160b6 100644 --- a/src/js/api/auth/register.mjs +++ b/src/js/api/auth/register.mjs @@ -5,7 +5,6 @@ const method = "post"; export async function register(profile) { const registerURL = API_SOCIAL_URL + action; - console.log(registerURL); const response = await fetch(registerURL, { headers: { @@ -17,5 +16,4 @@ export async function register(profile) { const result = await response.json(); return result; - console.log(result); } diff --git a/src/js/api/authFetch.mjs b/src/js/api/authFetch.mjs new file mode 100644 index 000000000..2811da85b --- /dev/null +++ b/src/js/api/authFetch.mjs @@ -0,0 +1,17 @@ +import { load } from "../storage/index.mjs"; + +export function headers() { + const token = load("token"); + + return { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }; +} + +export async function authFetch(url, options = {}) { + return fetch(url, { + ...options, + headers: headers(), + }); +} diff --git a/src/js/api/posts/create.mjs b/src/js/api/posts/create.mjs new file mode 100644 index 000000000..8fe9446e7 --- /dev/null +++ b/src/js/api/posts/create.mjs @@ -0,0 +1,16 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/posts"; +const method = "post"; + +export async function createPost(postData) { + const createPostURL = API_SOCIAL_URL + action; + + const response = await authFetch(createPostURL, { + method, + body: JSON.stringify(postData), + }); + + return await response.json(); +} diff --git a/src/js/api/posts/get.mjs b/src/js/api/posts/get.mjs new file mode 100644 index 000000000..fa48bd1ab --- /dev/null +++ b/src/js/api/posts/get.mjs @@ -0,0 +1,24 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/posts"; + +export async function getPosts() { + const getPostsURL = `${API_SOCIAL_URL}${action}`; + + const response = await authFetch(getPostsURL); + + return await response.json(); +} + +export async function getPost(id) { + if (!id) { + throw new Error("Get requires a postID"); + } + + const getPostURL = `${API_SOCIAL_URL}${action}/${id}`; + + const response = await authFetch(getPostURL); + + return await response.json(); +} diff --git a/src/js/api/posts/index.mjs b/src/js/api/posts/index.mjs new file mode 100644 index 000000000..db34f8d61 --- /dev/null +++ b/src/js/api/posts/index.mjs @@ -0,0 +1,4 @@ +export * from "./create.mjs"; +export * from "./get.mjs"; +export * from "./update.mjs"; +export * from "./remove.mjs"; diff --git a/src/js/api/posts/remove.mjs b/src/js/api/posts/remove.mjs new file mode 100644 index 000000000..2142e713b --- /dev/null +++ b/src/js/api/posts/remove.mjs @@ -0,0 +1,19 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/posts"; +const method = "delete"; + +export async function removePost(id) { + if (!id) { + throw new Error("Delete requires a postID"); + } + + const removePostURL = `${API_SOCIAL_URL}${action}/${id}`; + + const response = await authFetch(removePostURL, { + method, + }); + + return await response.json(); +} diff --git a/src/js/api/posts/update.mjs b/src/js/api/posts/update.mjs new file mode 100644 index 000000000..c9fa69c20 --- /dev/null +++ b/src/js/api/posts/update.mjs @@ -0,0 +1,20 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/posts"; +const method = "put"; + +export async function updatePost(postData) { + if (!postData.id) { + throw new Error("Update requires a postID"); + } + + const updatePostURL = `${API_SOCIAL_URL}${action}/${postData.id}`; + + const response = await authFetch(updatePostURL, { + method, + body: JSON.stringify(postData), + }); + + return await response.json(); +} diff --git a/src/js/handlers/login.mjs b/src/js/handlers/login.mjs index 590600c20..29df86aa8 100644 --- a/src/js/handlers/login.mjs +++ b/src/js/handlers/login.mjs @@ -9,7 +9,6 @@ export function setLoginFormListener() { const form = event.target; const formData = new FormData(form); const profile = Object.fromEntries(formData.entries()); - console.log(profile); login(profile); }); diff --git a/src/js/handlers/register.mjs b/src/js/handlers/register.mjs index 78dabe615..9fddf7c30 100644 --- a/src/js/handlers/register.mjs +++ b/src/js/handlers/register.mjs @@ -9,7 +9,6 @@ export function setRegisterFormListener() { const form = event.target; const formData = new FormData(form); const profile = Object.fromEntries(formData.entries()); - console.log(profile); register(profile); }); diff --git a/src/js/index.mjs b/src/js/index.mjs index 1071e9556..891d90fee 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,5 +1,6 @@ import { setRegisterFormListener } from "./handlers/register.mjs"; import { setLoginFormListener } from "./handlers/login.mjs"; +import * as post from "./api/posts/index.mjs"; const path = location.pathname; @@ -8,3 +9,23 @@ if (path === "/profile/login/") { } else if (path === "/profile/register/") { setRegisterFormListener(); } + +// post.createPost(); +// post.updatePost(); +// post.removePost(); +// post.getPost(); +// post.getPosts().then(console.log); + +// Examples +// post.createPost({ +// title: "Example Post 4", +// body: "Example text in body 4", +// }); + +// updatePost({ +// id: 8932, +// title: "Example Post updated", +// body: "Example text in body", +// }); + +// removePost(8932); From eb8667d0e7cbe926f17547ed49059624c97fc879 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:44:00 +0100 Subject: [PATCH 04/29] working on ui --- feed/index.html | 184 +------------- post/edit/index.html | 470 ++++++++++++++++++++++++++++++++++++ post/index.html | 221 +++++++++++++++++ profile/register/index.html | 3 +- src/js/index.mjs | 21 +- src/js/templates/index.mjs | 1 + src/js/templates/post.mjs | 48 ++++ 7 files changed, 764 insertions(+), 184 deletions(-) create mode 100644 post/edit/index.html create mode 100644 post/index.html create mode 100644 src/js/templates/index.mjs create mode 100644 src/js/templates/post.mjs diff --git a/feed/index.html b/feed/index.html index 7c84aca35..c25b7da00 100644 --- a/feed/index.html +++ b/feed/index.html @@ -10,9 +10,9 @@ +
@@ -113,185 +113,7 @@

@tigerlily

-
    -
  • -
    -
    -
    - Profile photo for cutedogs. A picture of a golden retriever sitting down and smiling to the camera. -
    -

    cutedogs

    -
    -
    - Corgi walking on railroads smiling happily in the rain. -
    -
    - - -
    -

    - Caught this corgi in action as he was out on a walk today. He - looks so happy and so adorable! - #happy #dogs #cuteness #corgi -

    -

    - 1 hour ago -

    -
    -
  • - -
  • -
    -
    -
    - Profile photo for girlwithapencil. A drawing of a blonde woman with eyes closed. -
    -

    girlwithapencil

    -
    -
    - Drawing of flowers in soft pastel colours and a white background. -
    -
    - - -
    -

    - Just some nighttime doodles.. Summers over and I can't wait for - spring to arrive again. What du you think? - #art #pastels #drawing #inspiration #flowers #spring -

    -

    - 2 days ago -

    -
    -
  • -
  • -
    -
    -
    - Profile photo for cutedogs. A picture of a golden retriever sitting down and smiling to the camera. -
    -

    cutedogs

    -
    -
    - Close up of a puppy lying down looking up with huge brown eyes. -
    -
    - - -
    -

    - How can I resist this cuteness overload? The rain was pouring - down today, but with those big brown eyes looking at me I was - easily pursuaded to go for a walk. - #happy #dogs #cuteness #cockerspaniel -

    -

    - 6 days ago -

    -
    -
  • - -
  • -
    -
    -
    - Profile photo for yogaemilia. A woman sitting down and meditating facing a lake. -
    -

    yogaemeilia

    -
    -
    - A woman standing in the sunset by the ocean reaching her hands out to both sides. -
    -
    - - -
    -

    - Just came back from a wonderful place. I have shot a 10 days - series with videos for you that will be released in a month. So - excited to share this experience with you guys! - #healthy #freedom #spirit #mindfullness -

    -

    - 3 weeks ago -

    -
    -
  • - -
  • -
    -
    -
    - Profile photo for yogaemilia. A woman sitting down and meditating facing a lake. -
    -

    yogaemeilia

    -
    -
    - A woman doing yoga on a mountain next to the ocean. She is standing on the hands. -
    -
    - - -
    -

    - I'm working on something... Will share more about this soon. - #healthy #yoga #spirit #mindfullness -

    -

    - 1 month ago -

    -
    -
  • -
+
    diff --git a/post/edit/index.html b/post/edit/index.html new file mode 100644 index 000000000..18a21a7d9 --- /dev/null +++ b/post/edit/index.html @@ -0,0 +1,470 @@ + + + My profile | Hello! + + + + + + + + + + + +
    + +
    +
    + Profile photo for Tigerlily. A photo of a young woman with long and curly brown hair. +
    +
    +

    @tigerlily

    +

    Iris Doe

    +

    + Just a girl living in the city trying to catch a glimpse of magic + that the earth has to offer. And yeah.. I'm a morning person! +

    +
    + +
    +
    +
    +
    + + + + +
    +
    +
    +
      +
    • +
      +
      +
      + Young woman with long and curly brown hair. +
      +

      tigerlily

      +
      +
      + A meadow of lavendel at sunrise. +
      +
      + + +
      +

      + Went to stay at my parent house for the weekend and I was + up early just get a glimpse of the wonderful morning out + on the fields. + #lavendel #morning #foggy #nature #peaceful #beautiful + +

      +

      + 7 minutes ago +

      +
      +
    • +
    +
    +
    + + + + + + +
    +
    +
    + + diff --git a/post/index.html b/post/index.html new file mode 100644 index 000000000..414c03a3b --- /dev/null +++ b/post/index.html @@ -0,0 +1,221 @@ + + + Feed | Hello! + + + + + + + + +
    + +
    + +
    +
    +
    + Profile photo for Tigerlily. A photo of a young woman with long and curly brown hair. +
    +
    +

    @tigerlily

    +
    +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + + + + diff --git a/profile/register/index.html b/profile/register/index.html index a42f4d2d6..2b001dea0 100644 --- a/profile/register/index.html +++ b/profile/register/index.html @@ -7,8 +7,7 @@ diff --git a/src/js/index.mjs b/src/js/index.mjs index 891d90fee..af3dbcef8 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,6 +1,7 @@ import { setRegisterFormListener } from "./handlers/register.mjs"; import { setLoginFormListener } from "./handlers/login.mjs"; -import * as post from "./api/posts/index.mjs"; +import * as postMethods from "./api/posts/index.mjs"; +import * as templates from "./templates/index.mjs"; const path = location.pathname; @@ -10,6 +11,24 @@ if (path === "/profile/login/") { setRegisterFormListener(); } +// async function testTemplates() { +// const posts = await postMethods.getPosts(); +// const post = posts[45]; +// const container = document.querySelector("#postFeed"); +// templates.renderPostTemplates(posts, container); +// } + +// testTemplates(); + +// async function testTemplate() { +// const posts = await postMethods.getPosts(); +// const post = posts[45]; +// const container = document.querySelector("#post"); +// templates.renderPostTemplate(post, container); +// } + +// testTemplate(); + // post.createPost(); // post.updatePost(); // post.removePost(); diff --git a/src/js/templates/index.mjs b/src/js/templates/index.mjs new file mode 100644 index 000000000..c11a397f6 --- /dev/null +++ b/src/js/templates/index.mjs @@ -0,0 +1 @@ +export * from "./post.mjs"; diff --git a/src/js/templates/post.mjs b/src/js/templates/post.mjs new file mode 100644 index 000000000..aac714afd --- /dev/null +++ b/src/js/templates/post.mjs @@ -0,0 +1,48 @@ +export function postTemplate(postData) { + const post = document.createElement("div"); + post.classList.add("post"); + post.innerHTML += `
  • + +

    ${postData.title}

    +
    +

    + ${postData.body} + ${postData.tags} +

    + +
    +
    + + +
    + +

    + Posted:${postData.created} +

    + +
  • + `; + return post; +} + +export function renderPostTemplate(postData, parent) { + parent.append(postTemplate(postData)); +} + +export function renderPostTemplates(postDataList, parent) { + parent.append(...postDataList.map(postTemplate)); + console.log(postDataList); +} + +export async function testTemplates() { + const posts = await postMethods.getPosts(); + const post = posts[45]; + const container = document.querySelector("#postFeed"); + templates.renderPostTemplates(posts, container); +} + +testTemplates(); From aee404ee5876f96443c4e3eca1787378f33eb532 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:56:12 +0100 Subject: [PATCH 05/29] some html cleanup --- feed/index.html | 6 +++--- post/edit/index.html | 8 ++++---- post/index.html | 8 ++++---- profile/index.html | 8 ++++---- profile/login/index.html | 2 +- profile/register/index.html | 2 +- src/js/index.mjs | 14 +++++++------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/feed/index.html b/feed/index.html index c25b7da00..f32e90f26 100644 --- a/feed/index.html +++ b/feed/index.html @@ -40,19 +40,19 @@

    - - diff --git a/post/create/index.html b/post/create/index.html new file mode 100644 index 000000000..34e28216d --- /dev/null +++ b/post/create/index.html @@ -0,0 +1,101 @@ + + + My profile | Hello! + + + + + + + + + +
    + + +
    + +
    +
    +
    +

    Create post

    +
    + +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    +
    +
    +
    + + diff --git a/post/edit/index.html b/post/edit/index.html index ddb2b5f6e..99f0bfe48 100644 --- a/post/edit/index.html +++ b/post/edit/index.html @@ -5,7 +5,7 @@ - + + + + +
    + + +
    + +
    +
    +
    +

    Create post

    +
    + +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    +
    +
    +
    + + diff --git a/src/js/api/posts/create.mjs b/src/js/api/posts/create.mjs index 5053c96b1..152b2fd33 100644 --- a/src/js/api/posts/create.mjs +++ b/src/js/api/posts/create.mjs @@ -14,5 +14,5 @@ export async function createPost(postData) { const newPost = await response.json(); - return newPost; + return console.log(newPost); } diff --git a/src/js/index.mjs b/src/js/index.mjs index db315e6df..15f7e7aa4 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,5 +1,5 @@ import * as listeners from "./handlers/index.mjs"; -// import { createPost } from "./api/posts/create.mjs"; +import { createPost } from "./api/posts/create.mjs"; // import * as postMethods from "./api/posts/index.mjs"; // import * as templates from "./templates/index.mjs"; @@ -39,10 +39,10 @@ if (path === "/profile/login/") { // post.getPost(); // post.getPosts().then(console.log); -// createPost({ -// title: "Example Post 4", -// body: "Example text in body 4", -// }); +createPost({ + title: "Example Post 4", + body: "Example text in body 4", +}); // updatePost({ // id: 8932, From f41fe16e87b747f5347607f859464d3500b92fb9 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:53:41 +0100 Subject: [PATCH 09/29] redirected user at login and register at success --- index.html | 2 +- profile/register/index.html | 14 +++++++++++--- src/js/api/auth/login.mjs | 29 ++++++++++++++++++----------- src/js/api/auth/register.mjs | 29 +++++++++++++++++++---------- src/js/handlers/login.mjs | 20 ++++++++++++-------- src/js/handlers/register.mjs | 1 + src/js/index.mjs | 14 +++++++------- 7 files changed, 69 insertions(+), 40 deletions(-) diff --git a/index.html b/index.html index 7da544d06..19f9f86c3 100644 --- a/index.html +++ b/index.html @@ -12,7 +12,7 @@ -
    +
    diff --git a/profile/register/index.html b/profile/register/index.html index 4f3fb5504..bb2ebc946 100644 --- a/profile/register/index.html +++ b/profile/register/index.html @@ -74,6 +74,16 @@

    Register user

    +
    + + +
    + +
    + + +
    +
    - +
    diff --git a/src/js/api/auth/login.mjs b/src/js/api/auth/login.mjs index e6e37b8cd..7e11ca988 100644 --- a/src/js/api/auth/login.mjs +++ b/src/js/api/auth/login.mjs @@ -5,18 +5,25 @@ const action = "/auth/login"; const method = "post"; export async function login(profile) { - const loginURL = API_SOCIAL_URL + action; + try { + const loginURL = API_SOCIAL_URL + action; + const body = JSON.stringify(profile); - const response = await fetch(loginURL, { - headers: { - "Content-Type": "application/json", - }, - method, - body: JSON.stringify(profile), - }); + const response = await fetch(loginURL, { + headers: { + "Content-Type": "application/json", + }, + method, + body, + }); - const { accessToken, ...user } = await response.json(); + const { accessToken, ...profileUser } = await response.json(); - storage.save("token", accessToken); - storage.save("profile", user); + storage.save("token", accessToken); + storage.save("profile", profileUser); + window.location.href = "/feed"; + } catch (error) { + console.log(error); + alert("Failed to login. Check your email and password."); + } } diff --git a/src/js/api/auth/register.mjs b/src/js/api/auth/register.mjs index cc0a160b6..908ba4fde 100644 --- a/src/js/api/auth/register.mjs +++ b/src/js/api/auth/register.mjs @@ -4,16 +4,25 @@ const action = "/auth/register"; const method = "post"; export async function register(profile) { - const registerURL = API_SOCIAL_URL + action; + try { + const registerURL = API_SOCIAL_URL + action; + const body = JSON.stringify(profile); - const response = await fetch(registerURL, { - headers: { - "Content-Type": "application/json", - }, - method, - body: JSON.stringify(profile), - }); + const response = await fetch(registerURL, { + headers: { + "Content-Type": "application/json", + }, + method, + body, + }); - const result = await response.json(); - return result; + const registerUser = await response.json(); + window.location.href = "/feed"; + return registerUser; + } catch (error) { + console.log(error); + alert( + "Failed to register user, please check that the requirements are met." + ); + } } diff --git a/src/js/handlers/login.mjs b/src/js/handlers/login.mjs index 29df86aa8..c01baa1ab 100644 --- a/src/js/handlers/login.mjs +++ b/src/js/handlers/login.mjs @@ -3,14 +3,18 @@ import { login } from "../api/auth/login.mjs"; export function setLoginFormListener() { const form = document.querySelector("#loginForm"); - if (form) { - form.addEventListener("submit", (event) => { - event.preventDefault(); - const form = event.target; - const formData = new FormData(form); - const profile = Object.fromEntries(formData.entries()); + try { + if (form) { + form.addEventListener("submit", (event) => { + event.preventDefault(); + const form = event.target; + const formData = new FormData(form); + const profile = Object.fromEntries(formData.entries()); - login(profile); - }); + login(profile); + }); + } + } catch (error) { + console.log(error); } } diff --git a/src/js/handlers/register.mjs b/src/js/handlers/register.mjs index 9fddf7c30..684d72e16 100644 --- a/src/js/handlers/register.mjs +++ b/src/js/handlers/register.mjs @@ -11,6 +11,7 @@ export function setRegisterFormListener() { const profile = Object.fromEntries(formData.entries()); register(profile); + console.log("profile:", profile); }); } } diff --git a/src/js/index.mjs b/src/js/index.mjs index e8999b49e..af3dbcef8 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -11,14 +11,14 @@ if (path === "/profile/login/") { setRegisterFormListener(); } -async function testTemplates() { - const posts = await postMethods.getPosts(); - const post = posts[45]; - const container = document.querySelector("#postFeed"); - templates.renderPostTemplates(posts, container); -} +// async function testTemplates() { +// const posts = await postMethods.getPosts(); +// const post = posts[45]; +// const container = document.querySelector("#postFeed"); +// templates.renderPostTemplates(posts, container); +// } -testTemplates(); +// testTemplates(); // async function testTemplate() { // const posts = await postMethods.getPosts(); From 213289f07d13a8e059d3c996374c28dd67133cf2 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Tue, 5 Dec 2023 16:09:06 +0100 Subject: [PATCH 10/29] done som tweaks for testing --- src/js/api/posts/create.mjs | 6 ++++-- src/js/api/posts/{remove.mjs => delete.mjs} | 0 src/js/api/posts/index.mjs | 2 +- src/js/index.mjs | 13 ++++++------- 4 files changed, 11 insertions(+), 10 deletions(-) rename src/js/api/posts/{remove.mjs => delete.mjs} (100%) diff --git a/src/js/api/posts/create.mjs b/src/js/api/posts/create.mjs index 152b2fd33..006f27936 100644 --- a/src/js/api/posts/create.mjs +++ b/src/js/api/posts/create.mjs @@ -5,7 +5,7 @@ const action = "/posts"; const method = "post"; export async function createPost(postData) { - const createPostURL = `${API_SOCIAL_URL}${action}`; + const createPostURL = API_SOCIAL_URL + action; const response = await authFetch(createPostURL, { method, @@ -14,5 +14,7 @@ export async function createPost(postData) { const newPost = await response.json(); - return console.log(newPost); + console.log(createPostURL); + console.log("newPost:", newPost); + return newPost; } diff --git a/src/js/api/posts/remove.mjs b/src/js/api/posts/delete.mjs similarity index 100% rename from src/js/api/posts/remove.mjs rename to src/js/api/posts/delete.mjs diff --git a/src/js/api/posts/index.mjs b/src/js/api/posts/index.mjs index db34f8d61..49d6a6182 100644 --- a/src/js/api/posts/index.mjs +++ b/src/js/api/posts/index.mjs @@ -1,4 +1,4 @@ export * from "./create.mjs"; export * from "./get.mjs"; export * from "./update.mjs"; -export * from "./remove.mjs"; +export * from "./delete.mjs"; diff --git a/src/js/index.mjs b/src/js/index.mjs index 15f7e7aa4..1289cc74c 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,7 +1,6 @@ import * as listeners from "./handlers/index.mjs"; -import { createPost } from "./api/posts/create.mjs"; -// import * as postMethods from "./api/posts/index.mjs"; -// import * as templates from "./templates/index.mjs"; +import * as postMethods from "./api/posts/index.mjs"; +import * as templates from "./templates/index.mjs"; const path = location.pathname; @@ -39,10 +38,10 @@ if (path === "/profile/login/") { // post.getPost(); // post.getPosts().then(console.log); -createPost({ - title: "Example Post 4", - body: "Example text in body 4", -}); +// postMethods.createPost({ +// title: "Example Post 4", +// body: "Example text in body 4", +// }); // updatePost({ // id: 8932, From 039ea55af062616003f04963625549a35cd8b804 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:36:54 +0100 Subject: [PATCH 11/29] Fixed issue with creating and updating post Was not due to token, but missed a code snippet turning tags back into an array --- post/edit/create/index.html | 101 --------------------------------- src/js/handlers/createPost.mjs | 4 ++ src/js/handlers/updatePost.mjs | 4 ++ 3 files changed, 8 insertions(+), 101 deletions(-) delete mode 100644 post/edit/create/index.html diff --git a/post/edit/create/index.html b/post/edit/create/index.html deleted file mode 100644 index 002dc0a51..000000000 --- a/post/edit/create/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - My profile | Hello! - - - - - - - - - -
    - - -
    - -
    -
    -
    -

    Create post

    -
    - -
    -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - -
    -
    -
    -
    - - diff --git a/src/js/handlers/createPost.mjs b/src/js/handlers/createPost.mjs index aab9093b8..6835773ef 100644 --- a/src/js/handlers/createPost.mjs +++ b/src/js/handlers/createPost.mjs @@ -10,6 +10,10 @@ export function setCreatePostFormListener() { const formData = new FormData(form); const post = Object.fromEntries(formData.entries()); + if (post.tags) { + post.tags = post.tags.split(" , ").map((tag) => tag.trim()); + } + createPost(post); }); } diff --git a/src/js/handlers/updatePost.mjs b/src/js/handlers/updatePost.mjs index 9a8dbdbc7..1c5375b9e 100644 --- a/src/js/handlers/updatePost.mjs +++ b/src/js/handlers/updatePost.mjs @@ -14,6 +14,10 @@ export function setUpdatePostFormListener() { const post = Object.fromEntries(formData.entries()); post.id = id; + if (post.tags) { + post.tags = post.tags.split(" , ").map((tag) => tag.trim()); + } + updatePost(post); }); } From cbc0ee0854468fd7d042a41cdc0cf3b525e292b0 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Thu, 7 Dec 2023 18:15:29 +0100 Subject: [PATCH 12/29] Created and tweaked postTemplates for feed and added some code to update and create --- src/js/api/posts/create.mjs | 1 + src/js/handlers/updatePost.mjs | 16 ++++- src/js/index.mjs | 19 ++---- src/js/templates/post.mjs | 118 +++++++++++++++++++++++++-------- 4 files changed, 112 insertions(+), 42 deletions(-) diff --git a/src/js/api/posts/create.mjs b/src/js/api/posts/create.mjs index 006f27936..53ec813a7 100644 --- a/src/js/api/posts/create.mjs +++ b/src/js/api/posts/create.mjs @@ -16,5 +16,6 @@ export async function createPost(postData) { console.log(createPostURL); console.log("newPost:", newPost); + window.location.href = "/feed"; return newPost; } diff --git a/src/js/handlers/updatePost.mjs b/src/js/handlers/updatePost.mjs index 1c5375b9e..ba0258fed 100644 --- a/src/js/handlers/updatePost.mjs +++ b/src/js/handlers/updatePost.mjs @@ -1,12 +1,24 @@ -import { updatePost } from "../api/posts/index.mjs"; +import { getPost, updatePost } from "../api/posts/index.mjs"; -export function setUpdatePostFormListener() { +export async function setUpdatePostFormListener() { const form = document.querySelector("#updatePost"); const url = new URL(location.href); const id = url.searchParams.get("id"); if (form) { + const button = form.querySelector("button"); + button.disabled = true; + + const post = await getPost(id); + + form.title.value = post.title; + form.body.value = post.body; + form.tags.valu = post.tags; + form.media.value = post.media; + + button.disabled = false; + form.addEventListener("submit", (event) => { event.preventDefault(); const form = event.target; diff --git a/src/js/index.mjs b/src/js/index.mjs index 1289cc74c..402200f0f 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -14,14 +14,13 @@ if (path === "/profile/login/") { listeners.setUpdatePostFormListener(); } -// async function testTemplates() { -// const posts = await postMethods.getPosts(); -// const post = posts[45]; -// const container = document.querySelector("#postFeed"); -// templates.renderPostTemplates(posts, container); -// } +async function testTemplates() { + const posts = await postMethods.getPosts(); + const container = document.querySelector("#postFeed"); + templates.renderPostTemplates(posts, container); +} -// testTemplates(); +testTemplates(); // async function testTemplate() { // const posts = await postMethods.getPosts(); @@ -32,12 +31,6 @@ if (path === "/profile/login/") { // testTemplate(); -// post.createPost(); -// post.updatePost(); -// post.removePost(); -// post.getPost(); -// post.getPosts().then(console.log); - // postMethods.createPost({ // title: "Example Post 4", // body: "Example text in body 4", diff --git a/src/js/templates/post.mjs b/src/js/templates/post.mjs index 49500afbc..62a0369ff 100644 --- a/src/js/templates/post.mjs +++ b/src/js/templates/post.mjs @@ -1,32 +1,96 @@ export function postTemplate(postData) { + console.log(postData); + const listElement = document.createElement("li"); + listElement.classList.add("card", "py-2", "my-3"); + listElement.id = postData.id; + + const postURL = document.createElement("a"); + postURL.classList.add("stretched-link"); + postURL.href = `post/index/id?=${postData.id}`; + listElement.appendChild(postURL); + + // const postHeaderWrapper = document.createElement("div"); + // authorHeader.classList.add("row", "align-items-center", "mb-3", "mx-2"); + // listElement.appendChild(postHeaderWrapper); + + // const authorImgWrapper = document.createElement("div"); + // authorContentWrapper.classList.add("col-3", "col-md-2"); + // postHeaderWrapper.appendChild(authorImgWrapper); + + // const authorImg = document.createElement("img"); + // img.classList.add("rounded-circle", "w-100"); + // img.src = postData.media; + // img.alt = `Profilephoto for ${postData.user}`; + // authorImgWrapper.appendChild(authorImg); + + // const authorUserName = document.createElement("p"); + // authorUserName.classList.add("card-title", "fs-5", "col-5"); + // authorUserName.innerHTML = postData.user; + // postHeaderWrapper.appendChild(authorUserName); + const post = document.createElement("div"); - post.classList.add("post"); - post.innerHTML += `
  • - -

    ${postData.title}

    -
    -

    - ${postData.body} - ${postData.tags} -

    - -
    -
    - - -
    - -

    - Posted:${postData.created} -

    - -
  • - `; - return post; + post.classList.add("mb-3", "mx-2", "py-2", "my-3"); + listElement.appendChild(post); + + if (postData.title) { + const title = document.createElement("p"); + title.classList.add("card-title", "fs-5"); + title.innerHTML = postData.title; + post.appendChild(title); + } + + if (postData.media) { + const img = document.createElement("img"); + img.classList.add("img-fluid"); + img.src = postData.media; + img.alt = `Image from ${postData.title}`; + post.appendChild(img); + } + + if (postData.body) { + const bodyWrapper = document.createElement("div"); + bodyWrapper.classList.add("card-body"); + post.appendChild(bodyWrapper); + + const body = document.createElement("p"); + body.classList.add("card-text"); + body.innerHTML = postData.body; + bodyWrapper.appendChild(body); + } + + if (postData.tags) { + const tags = document.createElement("span"); + tags.classList.add("fw-bold"); + tags.innerHTML = postData.tags; + post.appendChild(tags); + } + + if (postData.created) { + const timeWrapper = document.createElement("p"); + timeWrapper.classList.add("card-text"); + post.appendChild(timeWrapper); + + const time = document.createElement("small"); + time.classList.add("text-muted"); + if (postData.updated) { + time.innerHTML = `Updated: ${postData.updated}`; + } else { + time.innerHTML = `Posted: ${postData.created}`; + } + timeWrapper.appendChild(time); + } + + const reactionsWrapper = document.createElement("div"); + reactionsWrapper.classList.add("d-flex", "align-items-center", "mb-2"); + post.appendChild(reactionsWrapper); + const reactions = document.createElement("i"); + reactions.classList.add("bi", "bi-heart", "fs-4", "me-2"); + const comments = document.createElement("i"); + comments.classList.add("bi", "bi-chat-right", "fs-4", "ms-2"); + reactionsWrapper.appendChild(reactions); + reactionsWrapper.appendChild(comments); + + return listElement; } export function renderPostTemplate(postData, parent) { From 86ea54b4b2f50e8d3aa2bad7131350341b014788 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Sat, 9 Dec 2023 19:33:16 +0100 Subject: [PATCH 13/29] working on view post by id page --- feed/post/index.html | 142 ++++++++++++++++++++++++++++++++++++++ src/js/index.mjs | 13 ++-- src/js/templates/post.mjs | 95 +++++++++++++++++-------- 3 files changed, 212 insertions(+), 38 deletions(-) create mode 100644 feed/post/index.html diff --git a/feed/post/index.html b/feed/post/index.html new file mode 100644 index 000000000..01634f9da --- /dev/null +++ b/feed/post/index.html @@ -0,0 +1,142 @@ + + + ${postData.title} | Hello! + + + + + + + + +
    + +
    + +
    +
    +
    + Profile photo for Tigerlily. A photo of a young woman with long and curly brown hair. +
    +
    +

    @tigerlily

    +
    +
    + +
    +
    +
    +
    + +
    + +
    + + diff --git a/src/js/index.mjs b/src/js/index.mjs index 402200f0f..7abcf8896 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -1,5 +1,4 @@ import * as listeners from "./handlers/index.mjs"; -import * as postMethods from "./api/posts/index.mjs"; import * as templates from "./templates/index.mjs"; const path = location.pathname; @@ -12,16 +11,12 @@ if (path === "/profile/login/") { listeners.setCreatePostFormListener(); } else if (path === "/post/edit/") { listeners.setUpdatePostFormListener(); +} else if (path === "/feed/") { + templates.renderPosts(); +} else if (path === "/feed/post/") { + templates.renderPost(); } -async function testTemplates() { - const posts = await postMethods.getPosts(); - const container = document.querySelector("#postFeed"); - templates.renderPostTemplates(posts, container); -} - -testTemplates(); - // async function testTemplate() { // const posts = await postMethods.getPosts(); // const post = posts[45]; diff --git a/src/js/templates/post.mjs b/src/js/templates/post.mjs index 62a0369ff..69b6abcae 100644 --- a/src/js/templates/post.mjs +++ b/src/js/templates/post.mjs @@ -1,17 +1,46 @@ +import * as postMethods from "../api/posts/index.mjs"; + +function getQueryStringParam(param) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(param); +} + +export function formatDateString(dateString) { + const date = new Date(dateString); + + const options = { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + }; + + const formattedDate = date.toLocaleString("en-US", options); + + return formattedDate; +} + export function postTemplate(postData) { console.log(postData); - const listElement = document.createElement("li"); - listElement.classList.add("card", "py-2", "my-3"); - listElement.id = postData.id; - const postURL = document.createElement("a"); - postURL.classList.add("stretched-link"); - postURL.href = `post/index/id?=${postData.id}`; - listElement.appendChild(postURL); + let postDetails; + if (location.pathname === "/feed/") { + postDetails = document.createElement("li"); + const postURL = document.createElement("a"); + postURL.classList.add("stretched-link"); + postURL.href = `/feed/post/?id=${postData.id}`; + postDetails.appendChild(postURL); + } else { + postDetails = document.createElement("div"); + } + postDetails.classList.add("card", "py-2", "my-3"); + postDetails.id = postData.id; // const postHeaderWrapper = document.createElement("div"); // authorHeader.classList.add("row", "align-items-center", "mb-3", "mx-2"); - // listElement.appendChild(postHeaderWrapper); + // postDetails.appendChild(postHeaderWrapper); // const authorImgWrapper = document.createElement("div"); // authorContentWrapper.classList.add("col-3", "col-md-2"); @@ -30,7 +59,7 @@ export function postTemplate(postData) { const post = document.createElement("div"); post.classList.add("mb-3", "mx-2", "py-2", "my-3"); - listElement.appendChild(post); + postDetails.appendChild(post); if (postData.title) { const title = document.createElement("p"); @@ -65,18 +94,17 @@ export function postTemplate(postData) { post.appendChild(tags); } - if (postData.created) { + if (postData.updated) { + const dateString = postData.updated; + const formattedDate = formatDateString(dateString); + const timeWrapper = document.createElement("p"); timeWrapper.classList.add("card-text"); post.appendChild(timeWrapper); const time = document.createElement("small"); time.classList.add("text-muted"); - if (postData.updated) { - time.innerHTML = `Updated: ${postData.updated}`; - } else { - time.innerHTML = `Posted: ${postData.created}`; - } + time.innerHTML = `Posted: ${formattedDate}`; timeWrapper.appendChild(time); } @@ -90,23 +118,32 @@ export function postTemplate(postData) { reactionsWrapper.appendChild(reactions); reactionsWrapper.appendChild(comments); - return listElement; + return postDetails; } -export function renderPostTemplate(postData, parent) { - parent.append(postTemplate(postData)); -} +export async function renderPosts() { + const posts = await postMethods.getPosts(); + const container = document.querySelector("#postFeed"); + + container.innerHTML = ""; -export function renderPostTemplates(postDataList, parent) { - parent.append(...postDataList.map(postTemplate)); - console.log(postDataList); + container.append(...posts.map(postTemplate)); + console.log(posts); } -// export async function testTemplates() { -// const posts = await postMethods.getPosts(); -// const post = posts[45]; -// const container = document.querySelector("#postFeed"); -// templates.renderPostTemplates(posts, container); -// } +renderPosts(); + +export async function renderPost() { + const postId = getQueryStringParam("id"); + const container = document.querySelector("#postByID"); + const postById = await postMethods.getPost(postId); + + const renderPostTemplate = (postData, id) => { + container.innerHTML = ""; + container.append(postTemplate(postData, id)); + }; + + renderPostTemplate(postById); +} -// testTemplates(); +renderPost(); From 5046a5e55baae587967cddf0fc6e47068abd285f Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:42:11 +0100 Subject: [PATCH 14/29] moved functions into a components-folder --- src/js/templates/components.mjs | 21 ++++++++++++ src/js/templates/index.mjs | 1 + src/js/templates/post.mjs | 57 +++++++++++---------------------- 3 files changed, 40 insertions(+), 39 deletions(-) create mode 100644 src/js/templates/components.mjs diff --git a/src/js/templates/components.mjs b/src/js/templates/components.mjs new file mode 100644 index 000000000..a6b9cdc21 --- /dev/null +++ b/src/js/templates/components.mjs @@ -0,0 +1,21 @@ +export function getQueryStringParam(param) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(param); +} + +export function formatDateString(dateString) { + const date = new Date(dateString); + + const options = { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + }; + + const formattedDate = date.toLocaleString("en-US", options); + + return formattedDate; +} diff --git a/src/js/templates/index.mjs b/src/js/templates/index.mjs index c11a397f6..94b36d3bd 100644 --- a/src/js/templates/index.mjs +++ b/src/js/templates/index.mjs @@ -1 +1,2 @@ export * from "./post.mjs"; +export * from "./components.mjs"; diff --git a/src/js/templates/post.mjs b/src/js/templates/post.mjs index 69b6abcae..55b565ce8 100644 --- a/src/js/templates/post.mjs +++ b/src/js/templates/post.mjs @@ -1,26 +1,5 @@ import * as postMethods from "../api/posts/index.mjs"; - -function getQueryStringParam(param) { - const urlParams = new URLSearchParams(window.location.search); - return urlParams.get(param); -} - -export function formatDateString(dateString) { - const date = new Date(dateString); - - const options = { - year: "numeric", - month: "long", - day: "numeric", - hour: "numeric", - minute: "numeric", - hour12: true, - }; - - const formattedDate = date.toLocaleString("en-US", options); - - return formattedDate; -} +import * as component from "../templates/components.mjs"; export function postTemplate(postData) { console.log(postData); @@ -76,11 +55,11 @@ export function postTemplate(postData) { post.appendChild(img); } - if (postData.body) { - const bodyWrapper = document.createElement("div"); - bodyWrapper.classList.add("card-body"); - post.appendChild(bodyWrapper); + const bodyWrapper = document.createElement("div"); + bodyWrapper.classList.add("card-body"); + post.appendChild(bodyWrapper); + if (postData.body) { const body = document.createElement("p"); body.classList.add("card-text"); body.innerHTML = postData.body; @@ -91,12 +70,22 @@ export function postTemplate(postData) { const tags = document.createElement("span"); tags.classList.add("fw-bold"); tags.innerHTML = postData.tags; - post.appendChild(tags); + bodyWrapper.appendChild(tags); } + const reactionsWrapper = document.createElement("div"); + reactionsWrapper.classList.add("d-flex", "align-items-center", "my-2"); + post.appendChild(reactionsWrapper); + const reactions = document.createElement("i"); + reactions.classList.add("bi", "bi-heart", "fs-4", "me-2"); + const comments = document.createElement("i"); + comments.classList.add("bi", "bi-chat-right", "fs-4", "ms-2"); + reactionsWrapper.appendChild(reactions); + reactionsWrapper.appendChild(comments); + if (postData.updated) { const dateString = postData.updated; - const formattedDate = formatDateString(dateString); + const formattedDate = component.formatDateString(dateString); const timeWrapper = document.createElement("p"); timeWrapper.classList.add("card-text"); @@ -108,16 +97,6 @@ export function postTemplate(postData) { timeWrapper.appendChild(time); } - const reactionsWrapper = document.createElement("div"); - reactionsWrapper.classList.add("d-flex", "align-items-center", "mb-2"); - post.appendChild(reactionsWrapper); - const reactions = document.createElement("i"); - reactions.classList.add("bi", "bi-heart", "fs-4", "me-2"); - const comments = document.createElement("i"); - comments.classList.add("bi", "bi-chat-right", "fs-4", "ms-2"); - reactionsWrapper.appendChild(reactions); - reactionsWrapper.appendChild(comments); - return postDetails; } @@ -134,7 +113,7 @@ export async function renderPosts() { renderPosts(); export async function renderPost() { - const postId = getQueryStringParam("id"); + const postId = component.getQueryStringParam("id"); const container = document.querySelector("#postByID"); const postById = await postMethods.getPost(postId); From 38e74062d25e4e2f2311f0bef3594f9b8d9e98d5 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:48:31 +0100 Subject: [PATCH 15/29] created update profile function --- profile/edit/index.html | 107 ++++++++++++++++++++++++++++++ src/js/api/profiles/get.mjs | 27 ++++++++ src/js/api/profiles/index.mjs | 2 + src/js/api/profiles/update.mjs | 20 ++++++ src/js/handlers/index.mjs | 1 + src/js/handlers/updateProfile.mjs | 35 ++++++++++ src/js/index.mjs | 24 +------ src/scss/_variables.scss | 6 ++ 8 files changed, 200 insertions(+), 22 deletions(-) create mode 100644 profile/edit/index.html create mode 100644 src/js/api/profiles/get.mjs create mode 100644 src/js/api/profiles/index.mjs create mode 100644 src/js/api/profiles/update.mjs create mode 100644 src/js/handlers/updateProfile.mjs diff --git a/profile/edit/index.html b/profile/edit/index.html new file mode 100644 index 000000000..bce50f619 --- /dev/null +++ b/profile/edit/index.html @@ -0,0 +1,107 @@ + + + Edit Profile | Hello! + + + + + + + + + +
    + + +
    + +
    +
    +
    +

    Edit Profile

    + +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    +
    +
    +
    +
    + + diff --git a/src/js/api/profiles/get.mjs b/src/js/api/profiles/get.mjs new file mode 100644 index 000000000..45278c690 --- /dev/null +++ b/src/js/api/profiles/get.mjs @@ -0,0 +1,27 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/profiles"; + +export async function getProfiles() { + const getProfilesURL = `${API_SOCIAL_URL}${action}`; + + const response = await authFetch(getProfilesURL); + + const profiles = await response.json(); + + return profiles; +} + +export async function getProfile(name) { + if (!name) { + throw new Error("Get requires a profile name"); + } + + const getProfileURL = `${API_SOCIAL_URL}${action}/${name}`; + + const response = await authFetch(getProfileURL); + + const profileByName = await response.json(); + return profileByName; +} diff --git a/src/js/api/profiles/index.mjs b/src/js/api/profiles/index.mjs new file mode 100644 index 000000000..2753ec82e --- /dev/null +++ b/src/js/api/profiles/index.mjs @@ -0,0 +1,2 @@ +export * from "./get.mjs"; +export * from "./update.mjs"; diff --git a/src/js/api/profiles/update.mjs b/src/js/api/profiles/update.mjs new file mode 100644 index 000000000..e93e6a100 --- /dev/null +++ b/src/js/api/profiles/update.mjs @@ -0,0 +1,20 @@ +import { API_SOCIAL_URL } from "../constants.mjs"; +import { authFetch } from "../authFetch.mjs"; + +const action = "/profiles"; +const method = "put"; + +export async function updateProfile(profileData) { + if (!profileData.name) { + throw new Error("Update requires a name"); + } + + const updateProfileURL = `${API_SOCIAL_URL}${action}/${profileData.name}/media`; + + const response = await authFetch(updateProfileURL, { + method, + body: JSON.stringify(profileData), + }); + + return await response.json(); +} diff --git a/src/js/handlers/index.mjs b/src/js/handlers/index.mjs index 0e14cd90c..286f80249 100644 --- a/src/js/handlers/index.mjs +++ b/src/js/handlers/index.mjs @@ -2,3 +2,4 @@ export * from "./createPost.mjs"; export * from "./updatePost.mjs"; export * from "./login.mjs"; export * from "./register.mjs"; +export * from "./updateProfile.mjs"; diff --git a/src/js/handlers/updateProfile.mjs b/src/js/handlers/updateProfile.mjs new file mode 100644 index 000000000..627e6b4a7 --- /dev/null +++ b/src/js/handlers/updateProfile.mjs @@ -0,0 +1,35 @@ +import { getProfile, updateProfile } from "../api/profiles/index.mjs"; + +import { load } from "../storage/index.mjs"; + +export async function setUpdateProfileListener() { + const form = document.querySelector("#editProfile"); + + if (form) { + const { name, email } = load("profile"); + form.name.value = name; + form.email.value = email; + + const button = form.querySelector("button"); + button.disabled = true; + + const profile = await getProfile(name); + + form.banner.value = profile.banner; + form.avatar.value = profile.avatar; + + button.disabled = false; + + form.addEventListener("submit", (event) => { + event.preventDefault(); + const form = event.target; + const formData = new FormData(form); + const profile = Object.fromEntries(formData.entries()); + + profile.name = name; + profile.email = email; + + updateProfile(profile); + }); + } +} diff --git a/src/js/index.mjs b/src/js/index.mjs index 7abcf8896..8cfba3a8e 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -11,30 +11,10 @@ if (path === "/profile/login/") { listeners.setCreatePostFormListener(); } else if (path === "/post/edit/") { listeners.setUpdatePostFormListener(); +} else if (path === "/profile/edit/") { + listeners.setUpdateProfileListener(); } else if (path === "/feed/") { templates.renderPosts(); } else if (path === "/feed/post/") { templates.renderPost(); } - -// async function testTemplate() { -// const posts = await postMethods.getPosts(); -// const post = posts[45]; -// const container = document.querySelector("#post"); -// templates.renderPostTemplate(post, container); -// } - -// testTemplate(); - -// postMethods.createPost({ -// title: "Example Post 4", -// body: "Example text in body 4", -// }); - -// updatePost({ -// id: 8932, -// title: "Example Post updated", -// body: "Example text in body", -// }); - -// removePost(8932); diff --git a/src/scss/_variables.scss b/src/scss/_variables.scss index 1a17c78ba..99fe4b36a 100644 --- a/src/scss/_variables.scss +++ b/src/scss/_variables.scss @@ -15,3 +15,9 @@ $card-border-color: $light; $link-color: $primary; $link-hover-color: $secondary; $link-decoration: none; + +//Forms +.form-control:disabled { + opacity: 0.5; + cursor: not-allowed; +} From 4ac52d35434af619b6b3fd7ddbcf242a69f9963a Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:19:13 +0100 Subject: [PATCH 16/29] working on profile-info --- src/js/api/posts/get.mjs | 4 ++-- src/js/templates/post.mjs | 41 ++++++++++++++++++++---------------- src/js/templates/profile.mjs | 32 ++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 src/js/templates/profile.mjs diff --git a/src/js/api/posts/get.mjs b/src/js/api/posts/get.mjs index 6f77a3505..86143092f 100644 --- a/src/js/api/posts/get.mjs +++ b/src/js/api/posts/get.mjs @@ -4,7 +4,7 @@ import { authFetch } from "../authFetch.mjs"; const action = "/posts"; export async function getPosts() { - const getPostsURL = `${API_SOCIAL_URL}${action}`; + const getPostsURL = `${API_SOCIAL_URL}${action}?_author=true`; const response = await authFetch(getPostsURL); @@ -18,7 +18,7 @@ export async function getPost(id) { throw new Error("Get requires a postID"); } - const getPostURL = `${API_SOCIAL_URL}${action}/${id}`; + const getPostURL = `${API_SOCIAL_URL}${action}/${id}?_author=true`; const response = await authFetch(getPostURL); diff --git a/src/js/templates/post.mjs b/src/js/templates/post.mjs index 55b565ce8..52e6d7813 100644 --- a/src/js/templates/post.mjs +++ b/src/js/templates/post.mjs @@ -3,6 +3,7 @@ import * as component from "../templates/components.mjs"; export function postTemplate(postData) { console.log(postData); + console.log(postData.author); let postDetails; if (location.pathname === "/feed/") { @@ -17,24 +18,28 @@ export function postTemplate(postData) { postDetails.classList.add("card", "py-2", "my-3"); postDetails.id = postData.id; - // const postHeaderWrapper = document.createElement("div"); - // authorHeader.classList.add("row", "align-items-center", "mb-3", "mx-2"); - // postDetails.appendChild(postHeaderWrapper); - - // const authorImgWrapper = document.createElement("div"); - // authorContentWrapper.classList.add("col-3", "col-md-2"); - // postHeaderWrapper.appendChild(authorImgWrapper); - - // const authorImg = document.createElement("img"); - // img.classList.add("rounded-circle", "w-100"); - // img.src = postData.media; - // img.alt = `Profilephoto for ${postData.user}`; - // authorImgWrapper.appendChild(authorImg); - - // const authorUserName = document.createElement("p"); - // authorUserName.classList.add("card-title", "fs-5", "col-5"); - // authorUserName.innerHTML = postData.user; - // postHeaderWrapper.appendChild(authorUserName); + const postHeader = document.createElement("div"); + postHeader.classList.add("align-items-center", "mb-3", "mx-2"); + postDetails.appendChild(postHeader); + + // if (postData.author.avatar) { + // const authorImgWrapper = document.createElement("div"); + // authorImgWrapper.classList.add("col-3", "col-md-2"); + // postHeader.appendChild(authorImgWrapper); + + // const authorImg = document.createElement("img"); + // authorImg.classList.add("rounded-circle", "w-100"); + // authorImg.src = postData.author.avatar; + // authorImg.alt = `Image from ${postData.author.avatar}`; + // authorImgWrapper.appendChild(authorImg); + // } else { + // authorImg.src = ""; + // } + + const authorUserName = document.createElement("p"); + authorUserName.classList.add("card-title", "fs-5"); + authorUserName.innerHTML = `@ ${postData.author.name}`; + postHeader.appendChild(authorUserName); const post = document.createElement("div"); post.classList.add("mb-3", "mx-2", "py-2", "my-3"); diff --git a/src/js/templates/profile.mjs b/src/js/templates/profile.mjs new file mode 100644 index 000000000..4fb307039 --- /dev/null +++ b/src/js/templates/profile.mjs @@ -0,0 +1,32 @@ +// import * as postMethods from "../api/posts/index.mjs"; + +// export function profileTemplate(profile) { +// return profileDetails; +// } + +// export async function renderPosts() { +// const posts = await postMethods.getPosts(); +// const container = document.querySelector("#postFeed"); + +// container.innerHTML = ""; + +// container.append(...posts.map(postTemplate)); +// console.log(posts); +// } + +// renderPosts(); + +// export async function renderPost() { +// const postId = component.getQueryStringParam("id"); +// const container = document.querySelector("#postByID"); +// const postById = await postMethods.getPost(postId); + +// const renderPostTemplate = (postData, id) => { +// container.innerHTML = ""; +// container.append(postTemplate(postData, id)); +// }; + +// renderPostTemplate(postById); +// } + +// renderPost(); From 05c0b1d4fc5ca9e9977ec11e28a4573ffab671aa Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:42:38 +0100 Subject: [PATCH 17/29] Added profile to post and cleaned up some code relating to profile and post templates --- feed/index.html | 13 +---- feed/post/index.html | 15 +----- src/assets/images/profile-placeholder.png | Bin 0 -> 47965 bytes src/js/index.mjs | 2 + src/js/templates/index.mjs | 3 +- src/js/templates/{ => posts}/post.mjs | 51 +++++++++++------- .../templates/profiles/profile-thumbnail.mjs | 45 ++++++++++++++++ src/js/templates/{ => profiles}/profile.mjs | 0 8 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 src/assets/images/profile-placeholder.png rename src/js/templates/{ => posts}/post.mjs (72%) create mode 100644 src/js/templates/profiles/profile-thumbnail.mjs rename src/js/templates/{ => profiles}/profile.mjs (100%) diff --git a/feed/index.html b/feed/index.html index 27f293d91..31fb0e96c 100644 --- a/feed/index.html +++ b/feed/index.html @@ -64,18 +64,7 @@
    -
    -
    - Profile photo for Tigerlily. A photo of a young woman with long and curly brown hair. -
    -
    -

    @tigerlily

    -
    -
    +
    - +
    +
    + +
    diff --git a/src/js/api/posts/update.mjs b/src/js/api/posts/update.mjs index c9fa69c20..96826fddd 100644 --- a/src/js/api/posts/update.mjs +++ b/src/js/api/posts/update.mjs @@ -16,5 +16,6 @@ export async function updatePost(postData) { body: JSON.stringify(postData), }); + window.location.href = `/feed/post/?id=${postData.id}`; return await response.json(); } diff --git a/src/js/handlers/deletePost.mjs b/src/js/handlers/deletePost.mjs new file mode 100644 index 000000000..704d128c5 --- /dev/null +++ b/src/js/handlers/deletePost.mjs @@ -0,0 +1,33 @@ +import { getPost, removePost } from "../api/posts/index.mjs"; + +export async function setDeletePostListener() { + console.log("testing"); + const deleteButton = document.querySelector("#deleteButton"); + + const url = new URL(location.href); + const id = url.searchParams.get("id"); + + deleteButton.addEventListener("click", async (event) => { + event.preventDefault(); + + try { + const post = await getPost(id); + if (post) { + const confirmDelete = confirm( + "Are you sure you want to delete this post?" + ); + + if (confirmDelete) { + await removePost(id); + + alert("You successfully deleted the post."); + window.location.href = "/feed/"; + } + } else console.log("Post not found"); + } catch (error) { + console.log("Error deleting the post:", error); + } + }); +} + +setDeletePostListener(); diff --git a/src/js/handlers/index.mjs b/src/js/handlers/index.mjs index 286f80249..aabef7d8c 100644 --- a/src/js/handlers/index.mjs +++ b/src/js/handlers/index.mjs @@ -1,5 +1,6 @@ export * from "./createPost.mjs"; export * from "./updatePost.mjs"; +export * from "./deletePost.mjs"; export * from "./login.mjs"; export * from "./register.mjs"; export * from "./updateProfile.mjs"; diff --git a/src/js/handlers/updatePost.mjs b/src/js/handlers/updatePost.mjs index ba0258fed..406ade041 100644 --- a/src/js/handlers/updatePost.mjs +++ b/src/js/handlers/updatePost.mjs @@ -14,7 +14,7 @@ export async function setUpdatePostFormListener() { form.title.value = post.title; form.body.value = post.body; - form.tags.valu = post.tags; + form.tags.value = post.tags; form.media.value = post.media; button.disabled = false; @@ -30,6 +30,7 @@ export async function setUpdatePostFormListener() { post.tags = post.tags.split(" , ").map((tag) => tag.trim()); } + alert("Your post was successfully updated!"); updatePost(post); }); } diff --git a/src/js/index.mjs b/src/js/index.mjs index 2cb47f673..185317571 100644 --- a/src/js/index.mjs +++ b/src/js/index.mjs @@ -13,6 +13,7 @@ if (path === "/profile/login/") { listeners.setUpdatePostFormListener(); } else if (path === "/profile/edit/") { listeners.setUpdateProfileListener(); + listeners.setDeletePostListener(); } else if (path === "/feed/") { templates.renderProfileThumbnail(); templates.renderPosts(); diff --git a/src/js/templates/posts/post.mjs b/src/js/templates/posts/post.mjs index cefce59b5..deda31997 100644 --- a/src/js/templates/posts/post.mjs +++ b/src/js/templates/posts/post.mjs @@ -1,7 +1,10 @@ import * as postMethods from "../../api/posts/index.mjs"; import * as component from "../components.mjs"; +import { load } from "../../storage/index.mjs"; export function postTemplate(postData) { + const profile = load("profile"); + let postDetails; if (location.pathname === "/feed/") { @@ -17,7 +20,7 @@ export function postTemplate(postData) { postDetails.id = postData.id; const postHeader = document.createElement("div"); - postHeader.classList.add("row", "align-items-center", "mx-2"); + postHeader.classList.add("row", "align-items-center", "mx-1"); postDetails.appendChild(postHeader); const authorAvatarWrapper = document.createElement("div"); @@ -42,8 +45,20 @@ export function postTemplate(postData) { authorUserName.innerHTML = `@ ${postData.author.name}`; postHeader.appendChild(authorUserName); + if ( + location.pathname === `/feed/post/` && + postData.author.name === profile.name + ) { + const editButton = document.createElement("a"); + editButton.id = "editPostButton"; + editButton.href = `/post/edit/?id=${postData.id}`; + editButton.classList.add("btn", "button-sm", "btn-secondary", "col-3"); + editButton.innerHTML = `Edit `; + postHeader.appendChild(editButton); + } + const post = document.createElement("div"); - post.classList.add("mb-3", "mx-2", "py-2", "my-3"); + post.classList.add("mb-3", "mx-2", "p-2", "my-3"); postDetails.appendChild(post); if (postData.title) { From 2ab888deaf5f29a076ef9c7e28e9fe33b3a9b123 Mon Sep 17 00:00:00 2001 From: VildeAvloes <94361976+VildeAvloes@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:55:23 +0100 Subject: [PATCH 19/29] created the search bar using the filter method --- feed/index.html | 3 ++- post/create/index.html | 13 ++++++------- post/edit/index.html | 11 +++++------ src/js/handlers/index.mjs | 1 + src/js/handlers/search.mjs | 31 +++++++++++++++++++++++++++++++ src/js/index.mjs | 1 + 6 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 src/js/handlers/search.mjs diff --git a/feed/index.html b/feed/index.html index 31fb0e96c..6f3a6aaba 100644 --- a/feed/index.html +++ b/feed/index.html @@ -65,8 +65,9 @@
    -