286 lines
7.9 KiB
Vue
286 lines
7.9 KiB
Vue
<template>
|
|
<div id="forums">
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="columns is-centered">
|
|
<div class="column is-3" v-if="!loadingCategory && categories.length">
|
|
<router-link to="/forums/create">
|
|
<b-button type="is-info">Create Thread</b-button>
|
|
</router-link>
|
|
<br /><br />
|
|
<b-menu>
|
|
<b-menu-list label="Categories">
|
|
<b-menu-item label="All" tag="router-link" to="/forums/all" :active="selectedCategory === 'ALL'"></b-menu-item> <b-menu-item :label="category.name" v-for="(category, $index) in categories" :active="selectedCategory === category.value"
|
|
:key="'category-link-' + $index" tag="router-link" :to="'/forums/' + category.value"></b-menu-item>
|
|
</b-menu-list>
|
|
</b-menu>
|
|
</div>
|
|
<div class="column is-3" v-if="loadingCategory">
|
|
<b-skeleton></b-skeleton>
|
|
<b-skeleton></b-skeleton>
|
|
<b-skeleton></b-skeleton>
|
|
<b-skeleton></b-skeleton>
|
|
</div>
|
|
<div
|
|
class="column is-3"
|
|
v-if="!loadingCategory && !categories.length"
|
|
>
|
|
<NoItems connection="true"></NoItems>
|
|
</div>
|
|
<div class="column is-7" v-if="!threads.length && !loadingThreads">
|
|
<div class="box">
|
|
<NoItems type="forum threads"></NoItems>
|
|
</div>
|
|
</div>
|
|
<div class="column is-7" v-if="threads.length">
|
|
<div class="content">
|
|
<article
|
|
class="thread_display box"
|
|
v-for="thread in threads"
|
|
:key="'thread-' + thread.id"
|
|
@click="goToThread(thread)"
|
|
>
|
|
<div style="width: calc(100% - 3rem)">
|
|
<div class="thread_display__header">
|
|
<span class="thread_display__name">
|
|
{{ thread.name }}
|
|
</span>
|
|
<div class="thread_display__meta_bar">
|
|
<div>
|
|
By
|
|
<span class="thread_display__username" ref="username">
|
|
{{ thread.User.username }}
|
|
</span>
|
|
in
|
|
<span class="thread_display__category" ref="category">
|
|
{{ thread.Category.name }}
|
|
</span>
|
|
·
|
|
<span class="thread_display__date">
|
|
{{ thread.createdAt | formatDate }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="thread_display__replies_bar">
|
|
<div
|
|
class="thread_display__latest_reply"
|
|
v-if="thread.Posts.length === 2"
|
|
>
|
|
<font-awesome-icon :icon="['fa', 'reply']" fixed-width />
|
|
<span class="thread_display__latest_reply__text"
|
|
>Latest reply by </span
|
|
>
|
|
<span class="thread_display__username">{{
|
|
replyUsername
|
|
}}</span>
|
|
·
|
|
<span class="thread_display__date">{{
|
|
thread.Posts[1].createdAt | formatDate
|
|
}}</span>
|
|
</div>
|
|
<span title="Replies to thread" v-if="thread.Posts[0]">
|
|
Replies: {{ thread.postsCount - 1 }}
|
|
</span>
|
|
<span title="Replies to thread" v-else> Replies: 0 </span>
|
|
</div>
|
|
<div class="thread_display__content">
|
|
{{ thread.Posts[0].plainText }}
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import AjaxErrorHandler from ".././assets/js/errorHandler";
|
|
import NoItems from "../components/NoItems";
|
|
export default {
|
|
name: "Forums",
|
|
props: ["username"],
|
|
components: {
|
|
NoItems,
|
|
},
|
|
data() {
|
|
return {
|
|
categories: [],
|
|
loadingCategory: true,
|
|
loadingThreads: true,
|
|
threads: [],
|
|
selectedCategory: "ALL",
|
|
};
|
|
},
|
|
methods: {
|
|
goToThread(thread) {
|
|
this.$router.push("/forums/thread/" + thread.id);
|
|
},
|
|
getThreads(initial) {
|
|
if (this.nextURL === null && !initial) return;
|
|
|
|
this.loadingThreads = true;
|
|
|
|
this.axios
|
|
.get(
|
|
process.env.VUE_APP_APIENDPOINT +
|
|
process.env.VUE_APP_APIVERSION +
|
|
"/" +
|
|
"forums/category/" +
|
|
this.selectedCategory
|
|
)
|
|
.then((res) => {
|
|
this.loadingThreads = false;
|
|
|
|
if (initial) {
|
|
this.threads = res.data.Threads;
|
|
} else {
|
|
this.threads.push(...res.data.Threads);
|
|
}
|
|
|
|
this.nextURL = res.data.meta.nextURL;
|
|
this.nextThreadsCount = res.data.meta.nextThreadsCount;
|
|
})
|
|
.catch((e) => {
|
|
this.loadingThreads = false;
|
|
|
|
AjaxErrorHandler(this.$store)(e);
|
|
});
|
|
},
|
|
},
|
|
watch: {
|
|
selectedCategory(newValue) {
|
|
this.$router.push("/forums/" + newValue.toLowerCase());
|
|
},
|
|
$route() {
|
|
this.selectedCategory = this.$route.path.split("/")[2].toUpperCase();
|
|
this.getThreads(true);
|
|
},
|
|
},
|
|
mounted() {
|
|
this.axios
|
|
.get(
|
|
process.env.VUE_APP_APIENDPOINT +
|
|
process.env.VUE_APP_APIVERSION +
|
|
`/` +
|
|
"forums/category"
|
|
)
|
|
.then((res) => {
|
|
this.categories = res.data;
|
|
this.loadingCategory = false;
|
|
})
|
|
.catch((e) => {
|
|
this.loadingCategory = false;
|
|
let invalidId = e.response.data.errors.find((error) => {
|
|
return error.name === "accountDoesNotExist";
|
|
});
|
|
|
|
if (invalidId) {
|
|
this.$store.commit("set404Page", true);
|
|
} else {
|
|
AjaxErrorHandler(this.$store)(e);
|
|
}
|
|
});
|
|
this.getThreads(true);
|
|
},
|
|
};
|
|
</script>
|
|
<style lang='scss' scoped>
|
|
@import "../assets/scss/variables";
|
|
|
|
.thread_display {
|
|
cursor: pointer;
|
|
display: flex;
|
|
margin-bottom: 1rem;
|
|
padding: 0.75rem;
|
|
position: relative;
|
|
transition: background-color 0.2s, box-shadow 0.2s;
|
|
|
|
&:hover {
|
|
@extend .shadow_border--hover;
|
|
}
|
|
|
|
@at-root #{&}__icon {
|
|
margin-right: 0.5rem;
|
|
}
|
|
|
|
@at-root #{&}__username,
|
|
#{&}__category,
|
|
#{&}__date {
|
|
color: $color--text__primary;
|
|
}
|
|
|
|
@at-root #{&}__header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
@at-root #{&}__name {
|
|
font-weight: 500;
|
|
font-size: 1.25rem;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
line-height: 1.5rem;
|
|
height: 1.5rem;
|
|
}
|
|
@at-root #{&}__meta_bar {
|
|
color: $color--gray__darkest;
|
|
flex-shrink: 0;
|
|
line-height: 1.5rem;
|
|
height: 1.5rem;
|
|
}
|
|
|
|
@at-root #{&}__replies_bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
@at-root #{&}__latest_reply {
|
|
color: $color--text__secondary;
|
|
|
|
.fa {
|
|
color: $color--text__primary;
|
|
font-size: 0.75rem;
|
|
}
|
|
}
|
|
@at-root #{&}__replies {
|
|
width: 4rem;
|
|
text-align: right;
|
|
}
|
|
|
|
@at-root #{&}__content {
|
|
margin-top: 0.5rem;
|
|
word-break: break-all;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 420px) {
|
|
.thread_display {
|
|
@at-root #{&}__header {
|
|
flex-direction: column;
|
|
}
|
|
@at-root #{&}__meta_bar {
|
|
font-size: 0.9rem;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
@at-root #{&}__replies_bar {
|
|
position: relative;
|
|
left: -3.25rem;
|
|
width: calc(100% + 3.25rem);
|
|
}
|
|
|
|
@at-root #{&}__latest_reply {
|
|
.fa {
|
|
margin-right: 0.25rem;
|
|
}
|
|
|
|
@at-root #{&}__text {
|
|
display: none;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|