mirror of
https://github.com/notherealmarco/WASAPhoto.git
synced 2025-03-14 14:16:15 +01:00
Improve frontend readability, move modal to root component, add interceptors, fix usercard on XS displays
This commit is contained in:
parent
6840c34d7b
commit
4881fecbca
10 changed files with 220 additions and 287 deletions
10
webui/node_modules/.vite/deps/_metadata.json
generated
vendored
10
webui/node_modules/.vite/deps/_metadata.json
generated
vendored
|
@ -1,23 +1,23 @@
|
||||||
{
|
{
|
||||||
"hash": "80447977",
|
"hash": "0c3e4771",
|
||||||
"browserHash": "b98131b5",
|
"browserHash": "01248067",
|
||||||
"optimized": {
|
"optimized": {
|
||||||
"axios": {
|
"axios": {
|
||||||
"src": "../../axios/index.js",
|
"src": "../../axios/index.js",
|
||||||
"file": "axios.js",
|
"file": "axios.js",
|
||||||
"fileHash": "6b5eae63",
|
"fileHash": "d8d02cf0",
|
||||||
"needsInterop": true
|
"needsInterop": true
|
||||||
},
|
},
|
||||||
"vue": {
|
"vue": {
|
||||||
"src": "../../vue/dist/vue.runtime.esm-bundler.js",
|
"src": "../../vue/dist/vue.runtime.esm-bundler.js",
|
||||||
"file": "vue.js",
|
"file": "vue.js",
|
||||||
"fileHash": "de50261f",
|
"fileHash": "f8034b26",
|
||||||
"needsInterop": false
|
"needsInterop": false
|
||||||
},
|
},
|
||||||
"vue-router": {
|
"vue-router": {
|
||||||
"src": "../../vue-router/dist/vue-router.mjs",
|
"src": "../../vue-router/dist/vue-router.mjs",
|
||||||
"file": "vue-router.js",
|
"file": "vue-router.js",
|
||||||
"fileHash": "4cad12d6",
|
"fileHash": "b4ca170f",
|
||||||
"needsInterop": false
|
"needsInterop": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,59 +1,62 @@
|
||||||
<script setup>
|
<script>
|
||||||
import { RouterLink, RouterView } from 'vue-router'
|
export default {
|
||||||
import getCurrentSession from './services/authentication';
|
props: ["user_id", "name", "date", "comments", "likes", "photo_id", "liked"],
|
||||||
import { updateToken } from './services/axios';
|
data: function () {
|
||||||
|
return {
|
||||||
|
modalTitle: "Modal Title",
|
||||||
|
modalMsg: "Modal Message",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showModal(title, message) {
|
||||||
|
this.modalTitle = title;
|
||||||
|
this.modalMsg = message;
|
||||||
|
|
||||||
|
// Simulate a click on the hidden modal button to open it
|
||||||
|
this.$refs.openModal.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
// Configure axios interceptors
|
||||||
|
this.$axios.interceptors.response.use(response => {
|
||||||
|
// Leave response as is
|
||||||
|
return response;
|
||||||
|
}, error => {
|
||||||
|
if (error.response != undefined) {
|
||||||
|
// If the response is 401, redirect to /login
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
this.$router.push({ path: '/login' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the error message from the server in a modal
|
||||||
|
this.showModal("Error " + error.response.status, error.response.data['status'])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Show the error message from axios in a modal
|
||||||
|
this.showModal("Error", error.toString());
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- Invisible button to open the modal -->
|
||||||
<!--<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
|
<button ref="openModal" type="button" class="btn btn-primary" style="display: none" data-bs-toggle="modal" data-bs-target="#modal" />
|
||||||
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="#/">WASAPhoto</a>
|
<!-- Modal to show error messages -->
|
||||||
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
|
<Modal :title="modalTitle" :message="modalMsg" />
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
</header>-->
|
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!--<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
|
||||||
<div class="position-sticky pt-3 sidebar-sticky">
|
|
||||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
|
|
||||||
<span>WASAPhoto</span>
|
|
||||||
</h6>
|
|
||||||
<ul class="nav flex-column">
|
|
||||||
<li class="nav-item">
|
|
||||||
<RouterLink to="/" class="nav-link">
|
|
||||||
<svg class="feather"><use href="/feather-sprite-v4.29.0.svg#home"/></svg>
|
|
||||||
Stream
|
|
||||||
</RouterLink>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<RouterLink to="/link1" class="nav-link">
|
|
||||||
<svg class="feather"><use href="/feather-sprite-v4.29.0.svg#layout"/></svg>
|
|
||||||
Search
|
|
||||||
</RouterLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
|
|
||||||
<span>Account</span>
|
|
||||||
</h6>
|
|
||||||
<ul class="nav flex-column">
|
|
||||||
<li class="nav-item">
|
|
||||||
<RouterLink :to="'/some/' + 'variable_here' + '/path'" class="nav-link">
|
|
||||||
<svg class="feather"><use href="/feather-sprite-v4.29.0.svg#file-text"/></svg>
|
|
||||||
Your profile
|
|
||||||
</RouterLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>-->
|
|
||||||
|
|
||||||
<!---<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">-->
|
|
||||||
<main class="mb-5">
|
<main class="mb-5">
|
||||||
|
<!-- The view is rendered here -->
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- Bottom navigation buttons -->
|
||||||
<nav id="global-nav" class="navbar fixed-bottom navbar-light bg-light row">
|
<nav id="global-nav" class="navbar fixed-bottom navbar-light bg-light row">
|
||||||
<div class="collapse navbar-collapse" id="navbarNav"></div>
|
<div class="collapse navbar-collapse" id="navbarNav"></div>
|
||||||
<RouterLink to="/" class="col-4 text-center">
|
<RouterLink to="/" class="col-4 text-center">
|
||||||
|
@ -71,6 +74,7 @@ import { updateToken } from './services/axios';
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Make the active navigation button a little bit bigger */
|
||||||
#global-nav a.router-link-active {
|
#global-nav a.router-link-active {
|
||||||
font-size: 1.2em
|
font-size: 1.2em
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,3 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!loading"><slot /></div>
|
<div v-if="!loading"><slot /></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import getCurrentSession from '../services/authentication';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["user_id", "name", "date", "comments", "likes", "photo_id", "liked"],
|
props: ["user_id", "name", "date", "comments", "likes", "photo_id", "liked"],
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
imageSrc: "",
|
imageSrc: "",
|
||||||
errorMsg: null,
|
|
||||||
post_liked: this.liked,
|
post_liked: this.liked,
|
||||||
post_like_cnt: this.likes,
|
post_like_cnt: this.likes,
|
||||||
comments_data: [],
|
comments_data: [],
|
||||||
|
@ -19,17 +16,14 @@ export default {
|
||||||
postComment() {
|
postComment() {
|
||||||
this.$axios.post("/users/" + this.user_id + "/photos/" + this.photo_id + "/comments", {
|
this.$axios.post("/users/" + this.user_id + "/photos/" + this.photo_id + "/comments", {
|
||||||
"comment": this.commentMsg,
|
"comment": this.commentMsg,
|
||||||
"user_id": getCurrentSession(),
|
"user_id": this.$currentSession(),
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.commentMsg = "";
|
this.commentMsg = "";
|
||||||
|
|
||||||
this.comments_data = [];
|
this.comments_data = [];
|
||||||
this.comments_start_idx = 0;
|
this.comments_start_idx = 0;
|
||||||
this.getComments();
|
this.getComments();
|
||||||
}).catch(error => {
|
})
|
||||||
console.log(error);
|
|
||||||
this.errorMsg = error.toString();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
getComments() {
|
getComments() {
|
||||||
this.$axios.get("/users/" + this.user_id + "/photos/" + this.photo_id +
|
this.$axios.get("/users/" + this.user_id + "/photos/" + this.photo_id +
|
||||||
|
@ -40,29 +34,19 @@ export default {
|
||||||
|
|
||||||
this.comments_data = this.comments_data.concat(response.data);
|
this.comments_data = this.comments_data.concat(response.data);
|
||||||
this.comments_shown = true;
|
this.comments_shown = true;
|
||||||
//alert(this.comments[0]["comment"]);
|
})
|
||||||
}).catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
this.errorMsg = error.toString();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
like() {
|
like() {
|
||||||
this.$axios.put("/users/" + this.user_id + "/photos/" + this.photo_id + "/likes/" + getCurrentSession()).then(response => {
|
this.$axios.put("/users/" + this.user_id + "/photos/" + this.photo_id + "/likes/" + this.$currentSession()).then(response => {
|
||||||
this.post_liked = true;
|
this.post_liked = true;
|
||||||
this.post_like_cnt++;
|
this.post_like_cnt++;
|
||||||
}).catch(error => {
|
})
|
||||||
console.log(error);
|
|
||||||
this.errorMsg = error.toString();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
unlike() {
|
unlike() {
|
||||||
this.$axios.delete("/users/" + this.user_id + "/photos/" + this.photo_id + "/likes/" + getCurrentSession()).then(response => {
|
this.$axios.delete("/users/" + this.user_id + "/photos/" + this.photo_id + "/likes/" + this.$currentSession()).then(response => {
|
||||||
this.post_liked = false;
|
this.post_liked = false;
|
||||||
this.post_like_cnt--;
|
this.post_like_cnt--;
|
||||||
}).catch(error => {
|
})
|
||||||
console.log(error);
|
|
||||||
this.errorMsg = error.toString();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -81,7 +65,6 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card mb-5">
|
<div class="card mb-5">
|
||||||
<!--<img v-auth-img="imageSrc" class="card-img-top" alt="Chicago Skyscrapers"/>-->
|
|
||||||
<div ref="imageContainer"></div>
|
<div ref="imageContainer"></div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -126,14 +109,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--<ul class="list-group list-group-light list-group-small">
|
|
||||||
<li class="list-group-item px-4">Cras justo odio</li>
|
|
||||||
<li class="list-group-item px-4">Dapibus ac facilisis in</li>
|
|
||||||
<li class="list-group-item px-4">Vestibulum at eros</li>
|
|
||||||
</ul>-->
|
|
||||||
</div>
|
</div>
|
||||||
<ErrorMsg v-if="errormsg" :msg="errormsg"></ErrorMsg>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,36 +1,27 @@
|
||||||
<script>
|
<script>
|
||||||
import getCurrentSession from '../services/authentication';
|
|
||||||
export default {
|
export default {
|
||||||
props: ["user_id", "name", "followed", "banned", "show_new_post"],
|
props: ["user_id", "name", "followed", "banned", "show_new_post"],
|
||||||
watch: {
|
watch: {
|
||||||
banned: function(new_val, old_val) {
|
banned: function (new_val, old_val) {
|
||||||
this.user_banned = new_val;
|
this.user_banned = new_val;
|
||||||
},
|
},
|
||||||
followed: function(new_val, old_val) {
|
followed: function (new_val, old_val) {
|
||||||
this.user_followed = new_val;
|
this.user_followed = new_val;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
errorMsg: "aaa",
|
errorMsg: "aaa",
|
||||||
user_followed: this.followed,
|
user_followed: this.followed,
|
||||||
user_banned: this.banned,
|
user_banned: this.banned,
|
||||||
myself: getCurrentSession() == this.user_id,
|
myself: this.$currentSession() == this.user_id,
|
||||||
show_post_form: false,
|
show_post_form: false,
|
||||||
show_username_form: false,
|
show_username_form: false,
|
||||||
newUsername: "",
|
newUsername: "",
|
||||||
upload_file: null,
|
upload_file: null,
|
||||||
|
|
||||||
modalTitle: "",
|
|
||||||
modalMsg: "",
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
playModal(title, msg) {
|
|
||||||
this.modalTitle = title
|
|
||||||
this.modalMsg = msg
|
|
||||||
this.$refs.openModal.click()
|
|
||||||
},
|
|
||||||
logout() {
|
logout() {
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem("token");
|
||||||
sessionStorage.removeItem("token");
|
sessionStorage.removeItem("token");
|
||||||
|
@ -40,36 +31,32 @@ export default {
|
||||||
this.$router.push({ path: "/profile/" + this.user_id });
|
this.$router.push({ path: "/profile/" + this.user_id });
|
||||||
},
|
},
|
||||||
follow() {
|
follow() {
|
||||||
this.$axios.put("/users/" + this.user_id + "/followers/" + getCurrentSession())
|
this.$axios.put("/users/" + this.user_id + "/followers/" + this.$currentSession())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.user_followed = true
|
this.user_followed = true
|
||||||
this.$emit('updateInfo')
|
this.$emit('updateInfo')
|
||||||
})
|
})
|
||||||
.catch(error => this.playModal("Error", error.toString()));
|
|
||||||
},
|
},
|
||||||
unfollow() {
|
unfollow() {
|
||||||
this.$axios.delete("/users/" + this.user_id + "/followers/" + getCurrentSession())
|
this.$axios.delete("/users/" + this.user_id + "/followers/" + this.$currentSession())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.user_followed = false
|
this.user_followed = false
|
||||||
this.$emit('updateInfo')
|
this.$emit('updateInfo')
|
||||||
})
|
})
|
||||||
.catch(error => this.playModal("Error", error.toString()));
|
|
||||||
},
|
},
|
||||||
ban() {
|
ban() {
|
||||||
this.$axios.put("/users/" + getCurrentSession() + "/bans/" + this.user_id)
|
this.$axios.put("/users/" + this.$currentSession() + "/bans/" + this.user_id)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.user_banned = true
|
this.user_banned = true
|
||||||
this.$emit('updateInfo')
|
this.$emit('updateInfo')
|
||||||
})
|
})
|
||||||
.catch(error => this.playModal("Error", error.toString()));
|
|
||||||
},
|
},
|
||||||
unban() {
|
unban() {
|
||||||
this.$axios.delete("/users/" + getCurrentSession() + "/bans/" + this.user_id)
|
this.$axios.delete("/users/" + this.$currentSession() + "/bans/" + this.user_id)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.user_banned = false
|
this.user_banned = false
|
||||||
this.$emit('updateInfo')
|
this.$emit('updateInfo')
|
||||||
})
|
})
|
||||||
.catch(error => this.playModal("Error", error.toString()));
|
|
||||||
},
|
},
|
||||||
load_file(e) {
|
load_file(e) {
|
||||||
let files = e.target.files || e.dataTransfer.files;
|
let files = e.target.files || e.dataTransfer.files;
|
||||||
|
@ -77,38 +64,19 @@ export default {
|
||||||
this.upload_file = files[0];
|
this.upload_file = files[0];
|
||||||
},
|
},
|
||||||
submit_file() {
|
submit_file() {
|
||||||
this.$axios.post("/users/" + getCurrentSession() + "/photos", this.upload_file)
|
this.$axios.post("/users/" + this.$currentSession() + "/photos", this.upload_file)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.show_post_form = false
|
this.show_post_form = false
|
||||||
this.$emit('updatePosts')
|
this.$emit('updatePosts')
|
||||||
})
|
})
|
||||||
.catch(error => {
|
|
||||||
if (error.response.status != null && error.response.data != null) {
|
|
||||||
this.modalTitle = "Error"
|
|
||||||
this.modalMsg = error.response.data
|
|
||||||
this.$refs.openModal.click()
|
|
||||||
} else {
|
|
||||||
this.playModal("Error", error.toString())
|
|
||||||
}
|
|
||||||
this.playModal("Error", error.toString())
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
updateUsername() {
|
updateUsername() {
|
||||||
this.$axios.put("/users/" + getCurrentSession() + "/username", {name: this.newUsername})
|
this.$axios.put("/users/" + this.$currentSession() + "/username", { name: this.newUsername })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.show_username_form = false
|
this.show_username_form = false
|
||||||
this.$emit('updateInfo')
|
this.$emit('updateInfo')
|
||||||
this.name = this.newUsername
|
this.name = this.newUsername
|
||||||
})
|
})
|
||||||
.catch(error => {
|
|
||||||
if (error.response.status == 409) {
|
|
||||||
this.modalTitle = "Error"
|
|
||||||
this.modalMsg = "The chosen username is already taken."
|
|
||||||
this.$refs.openModal.click()
|
|
||||||
} else {
|
|
||||||
this.playModal("Error", error.toString())
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -117,37 +85,51 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<button ref="openModal" type="button" class="btn btn-primary" style="display: none" data-bs-toggle="modal" data-bs-target="#modal" />
|
|
||||||
<Modal :title="modalTitle" :message="modalMsg" />
|
|
||||||
|
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-10">
|
<div class="col-5">
|
||||||
<div class="card-body h-100 d-flex align-items-center">
|
<div class="card-body h-100 d-flex align-items-center">
|
||||||
<a @click="visit"><h5 class="card-title mb-0">{{ name }}</h5></a>
|
<a @click="visit">
|
||||||
|
<h5 class="card-title mb-0">{{ name }}</h5>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-2">
|
<div class="d-flex flex-column" v-bind:class="{
|
||||||
<div class="card-body d-flex justify-content-end">
|
'col-12': (myself && show_new_post),
|
||||||
|
'col-sm-7': (myself && show_new_post),
|
||||||
|
'col-7': !(myself && show_new_post),
|
||||||
|
'align-items-end': !(myself && show_new_post),
|
||||||
|
'align-items-sm-end': (myself && show_new_post),
|
||||||
|
}">
|
||||||
|
|
||||||
|
<div class="card-body d-flex">
|
||||||
<div v-if="!myself" class="d-flex">
|
<div v-if="!myself" class="d-flex">
|
||||||
<button v-if="!user_banned" @click="ban" type="button" class="btn btn-outline-danger me-2">Ban</button>
|
<button v-if="!user_banned" @click="ban" type="button"
|
||||||
<button v-if="user_banned" @click="unban" type="button" class="btn btn-danger me-2">Banned</button>
|
class="btn btn-outline-danger me-2">Ban</button>
|
||||||
<button v-if="!user_followed" @click="follow" type="button" class="btn btn-primary">Follow</button>
|
<button v-if="user_banned" @click="unban" type="button"
|
||||||
<button v-if="user_followed" @click="unfollow" type="button" class="btn btn-outline-primary">Following</button>
|
class="btn btn-danger me-2">Banned</button>
|
||||||
|
<button v-if="!user_followed" @click="follow" type="button"
|
||||||
|
class="btn btn-primary">Follow</button>
|
||||||
|
<button v-if="user_followed" @click="unfollow" type="button"
|
||||||
|
class="btn btn-outline-primary">Following</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(myself && !show_new_post)">
|
<div v-if="(myself && !show_new_post)">
|
||||||
<button disabled type="button" class="btn btn-secondary">Yourself</button>
|
<button disabled type="button" class="btn btn-secondary">Yourself</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(myself && show_new_post)" class="d-flex">
|
<div v-if="(myself && show_new_post)" class="col">
|
||||||
<button type="button" class="btn btn-outline-danger me-2" @click="logout">Logout</button>
|
<button type="button" class="btn btn-outline-danger me-2" @click="logout">Logout</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(myself && show_new_post)" class="d-flex">
|
<div class="d-flex col justify-content-end flex-row">
|
||||||
<button v-if="!show_username_form" type="button" class="btn btn-outline-secondary me-2" @click="show_username_form = true">Username</button>
|
<div v-if="(myself && show_new_post)" class="">
|
||||||
|
<button v-if="!show_username_form" type="button" class="btn btn-outline-secondary me-2"
|
||||||
|
@click="show_username_form = true">Username</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="(myself && show_new_post)" class="">
|
||||||
|
<button v-if="!show_post_form" type="button" class="btn btn-primary"
|
||||||
|
@click="show_post_form = true">Post</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(myself && show_new_post)" class="d-flex">
|
|
||||||
<button v-if="!show_post_form" type="button" class="btn btn-primary" @click="show_post_form = true">Post</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -168,7 +150,8 @@ export default {
|
||||||
<div class="row" v-if="show_username_form">
|
<div class="row" v-if="show_username_form">
|
||||||
<div class="col-10">
|
<div class="col-10">
|
||||||
<div class="card-body h-100 d-flex align-items-center">
|
<div class="card-body h-100 d-flex align-items-center">
|
||||||
<input v-model="newUsername" class="form-control form-control-lg" id="formUsername" placeholder="Your new fantastic username! 😜" />
|
<input v-model="newUsername" class="form-control form-control-lg" id="formUsername"
|
||||||
|
placeholder="Your new fantastic username! 😜" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {createApp, reactive} from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { axios, updateToken as axiosUpdate } from './services/axios.js';
|
import { axios, updateToken as axiosUpdate } from './services/axios.js';
|
||||||
|
import getCurrentSession from './services/authentication';
|
||||||
import ErrorMsg from './components/ErrorMsg.vue'
|
import ErrorMsg from './components/ErrorMsg.vue'
|
||||||
import LoadingSpinner from './components/LoadingSpinner.vue'
|
import LoadingSpinner from './components/LoadingSpinner.vue'
|
||||||
import PostCard from './components/PostCard.vue'
|
import PostCard from './components/PostCard.vue'
|
||||||
|
@ -12,13 +13,18 @@ import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||||
import './assets/dashboard.css'
|
import './assets/dashboard.css'
|
||||||
import './assets/main.css'
|
import './assets/main.css'
|
||||||
|
|
||||||
|
// Create the Vue SPA
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.config.globalProperties.$axios = axios;
|
app.config.globalProperties.$axios = axios;
|
||||||
app.config.globalProperties.$axiosUpdate = axiosUpdate;
|
app.config.globalProperties.$axiosUpdate = axiosUpdate;
|
||||||
|
app.config.globalProperties.$currentSession = getCurrentSession;
|
||||||
|
|
||||||
|
// Register the components
|
||||||
app.component("ErrorMsg", ErrorMsg);
|
app.component("ErrorMsg", ErrorMsg);
|
||||||
app.component("LoadingSpinner", LoadingSpinner);
|
app.component("LoadingSpinner", LoadingSpinner);
|
||||||
app.component("PostCard", PostCard);
|
app.component("PostCard", PostCard);
|
||||||
app.component("UserCard", UserCard);
|
app.component("UserCard", UserCard);
|
||||||
app.component("Modal", Modal);
|
app.component("Modal", Modal);
|
||||||
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import getCurrentSession from '../services/authentication';
|
|
||||||
export default {
|
export default {
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
|
@ -13,6 +12,9 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh() {
|
||||||
|
// this way we are sure that we fill the first page
|
||||||
|
// 450 is a bit more of the max height of a post
|
||||||
|
// todo: may not work in 4k screens :/
|
||||||
this.limit = Math.round(window.innerHeight / 450);
|
this.limit = Math.round(window.innerHeight / 450);
|
||||||
this.start_idx = 0;
|
this.start_idx = 0;
|
||||||
this.data_ended = false;
|
this.data_ended = false;
|
||||||
|
@ -28,9 +30,7 @@ export default {
|
||||||
else this.stream_data = this.stream_data.concat(response.data);
|
else this.stream_data = this.stream_data.concat(response.data);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.response.status == 401) {
|
// todo: handle better
|
||||||
this.$router.push({ path: "/login" });
|
|
||||||
}
|
|
||||||
this.errormsg = e.toString();
|
this.errormsg = e.toString();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -45,12 +45,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// this way we are sure that we fill the first page
|
|
||||||
// 450 is a bit more of the max height of a post
|
|
||||||
// todo: may not work in 4k screens :/
|
|
||||||
this.limit = Math.round(window.innerHeight / 450);
|
|
||||||
this.scroll();
|
this.scroll();
|
||||||
this.loadContent();
|
this.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -87,9 +83,5 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import LoadingSpinner from '../components/LoadingSpinner.vue';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
|
@ -34,7 +32,8 @@ export default {
|
||||||
// Update the header
|
// Update the header
|
||||||
this.$axiosUpdate();
|
this.$axiosUpdate();
|
||||||
|
|
||||||
this.$router.push({ path: "/" });
|
// Go back to the previous page
|
||||||
|
this.$router.go(-1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.errormsg = response.data["error"];
|
this.errormsg = response.data["error"];
|
||||||
|
@ -45,22 +44,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
async refresh() {
|
|
||||||
//this.loading = true;
|
|
||||||
//this.errormsg = null;
|
|
||||||
//try {
|
|
||||||
// let response = await this.$axios.get("/");
|
|
||||||
// this.some_data = response.data;
|
|
||||||
//} catch (e) {
|
|
||||||
// this.errormsg = e.toString();
|
|
||||||
//}
|
|
||||||
this.loading = false;
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.refresh();
|
|
||||||
},
|
|
||||||
components: { LoadingSpinner }
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import getCurrentSession from "../services/authentication";
|
|
||||||
export default {
|
export default {
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
|
@ -16,6 +15,10 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh() {
|
||||||
this.getMainData();
|
this.getMainData();
|
||||||
|
|
||||||
|
// this way we are sure that we fill the first page todo: check
|
||||||
|
// 450 is a bit more of the max height of a post
|
||||||
|
// todo: may not work in 4k screens :/
|
||||||
this.limit = Math.round(window.innerHeight / 450);
|
this.limit = Math.round(window.innerHeight / 450);
|
||||||
this.start_idx = 0;
|
this.start_idx = 0;
|
||||||
this.data_ended = false;
|
this.data_ended = false;
|
||||||
|
@ -41,9 +44,7 @@ export default {
|
||||||
else this.stream_data = this.stream_data.concat(response.data);
|
else this.stream_data = this.stream_data.concat(response.data);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.response.status == 401) { // todo: move from here
|
// todo: handle better
|
||||||
this.$router.push({ path: "/login" });
|
|
||||||
}
|
|
||||||
this.errormsg = e.toString();
|
this.errormsg = e.toString();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -58,21 +59,15 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
// this way we are sure that we fill the first page
|
|
||||||
// 450 is a bit more of the max height of a post
|
|
||||||
// todo: may not work in 4k screens :/
|
|
||||||
|
|
||||||
if (this.$route.params.user_id == "me") {
|
if (this.$route.params.user_id == "me") {
|
||||||
//this.$router.replace({ path: "/profile/" + });
|
//this.$router.replace({ path: "/profile/" + }); (It's ok to not redirect, it's just a matter of taste)
|
||||||
this.requestedProfile = getCurrentSession();
|
this.requestedProfile = this.$currentSession();
|
||||||
}else {
|
} else {
|
||||||
this.requestedProfile = this.$route.params.user_id;
|
this.requestedProfile = this.$route.params.user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getMainData();
|
|
||||||
this.limit = Math.round(window.innerHeight / 450);
|
|
||||||
this.scroll();
|
this.scroll();
|
||||||
this.loadContent();
|
this.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -90,7 +85,7 @@ export default {
|
||||||
:name = "user_data['name']"
|
:name = "user_data['name']"
|
||||||
:followed = "user_data['followed']"
|
:followed = "user_data['followed']"
|
||||||
:banned = "user_data['banned']"
|
:banned = "user_data['banned']"
|
||||||
:my_id = "getCurrentSession"
|
:my_id = "this.$currentSession"
|
||||||
:show_new_post = "true"
|
:show_new_post = "true"
|
||||||
@updateInfo = "getMainData"
|
@updateInfo = "getMainData"
|
||||||
@updatePosts = "refresh" />
|
@updatePosts = "refresh" />
|
||||||
|
@ -128,9 +123,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,50 +1,47 @@
|
||||||
<script>
|
<script>
|
||||||
import getCurrentSession from '../services/authentication';
|
// import getCurrentSession from '../services/authentication'; todo: can be removed
|
||||||
export default {
|
export default {
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
errormsg: null,
|
errormsg: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
stream_data: [],
|
streamData: [],
|
||||||
data_ended: false,
|
dataEnded: false,
|
||||||
start_idx: 0,
|
startIdx: 0,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
field_username: "",
|
fieldUsername: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh() {
|
||||||
this.limit = Math.round(window.innerHeight / 72);
|
this.limit = Math.round(window.innerHeight / 72);
|
||||||
this.start_idx = 0;
|
this.startIdx = 0;
|
||||||
this.data_ended = false;
|
this.dataEnded = false;
|
||||||
this.stream_data = [];
|
this.streamData = [];
|
||||||
this.loadContent();
|
this.loadContent();
|
||||||
},
|
},
|
||||||
async loadContent() {
|
async loadContent() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.errormsg = null;
|
this.errormsg = null;
|
||||||
if (this.field_username == "") {
|
if (this.fieldUsername == "") {
|
||||||
this.errormsg = "Please enter a username";
|
this.errormsg = "Please enter a username";
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let response = await this.$axios.get("/users?query=" + this.field_username + "&start_index=" + this.start_idx + "&limit=" + this.limit);
|
let response = await this.$axios.get("/users?query=" + this.fieldUsername + "&start_index=" + this.startIdx + "&limit=" + this.limit);
|
||||||
if (response.data.length == 0) this.data_ended = true;
|
if (response.data.length == 0) this.dataEnded = true;
|
||||||
else this.stream_data = this.stream_data.concat(response.data);
|
else this.streamData = this.streamData.concat(response.data);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.errormsg = e.toString();
|
this.errormsg = e.toString(); // todo: handle better
|
||||||
if (e.response.status == 401) {
|
|
||||||
this.$router.push({ path: "/login" });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scroll () {
|
scroll () {
|
||||||
window.onscroll = () => {
|
window.onscroll = () => {
|
||||||
let bottomOfWindow = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop) + window.innerHeight === document.documentElement.offsetHeight
|
let bottomOfWindow = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop) + window.innerHeight === document.documentElement.offsetHeight
|
||||||
if (bottomOfWindow && !this.data_ended) {
|
if (bottomOfWindow && !this.dataEnded) {
|
||||||
this.start_idx += this.limit;
|
this.startIdx += this.limit;
|
||||||
this.loadContent();
|
this.loadContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,11 +68,11 @@ export default {
|
||||||
<ErrorMsg v-if="errormsg" :msg="errormsg"></ErrorMsg>
|
<ErrorMsg v-if="errormsg" :msg="errormsg"></ErrorMsg>
|
||||||
|
|
||||||
<div class="form-floating mb-4">
|
<div class="form-floating mb-4">
|
||||||
<input v-model="field_username" @input="refresh" id="formUsername" class="form-control" placeholder="name@example.com"/>
|
<input v-model="fieldUsername" @input="refresh" id="formUsername" class="form-control" placeholder="name@example.com"/>
|
||||||
<label class="form-label" for="formUsername">Search by username</label>
|
<label class="form-label" for="formUsername">Search by username</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="main-content" v-for="item of stream_data">
|
<div id="main-content" v-for="item of streamData">
|
||||||
<UserCard
|
<UserCard
|
||||||
:user_id="item.user_id"
|
:user_id="item.user_id"
|
||||||
:name="item.name"
|
:name="item.name"
|
||||||
|
|
Loading…
Reference in a new issue