Skip to content

Instantly share code, notes, and snippets.

@harryWonder
Created October 26, 2020 09:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harryWonder/040f2c1a0e45d84949c8fd9643e7e715 to your computer and use it in GitHub Desktop.
Save harryWonder/040f2c1a0e45d84949c8fd9643e7e715 to your computer and use it in GitHub Desktop.
This file is where an authenticated user goes in the ld-fullstack lesson. It contains basic crud features for the forums.
<template id="">
<div>
<header>
<Nav></Nav>
</header>
<section class="app_description">
<div class="container">
<div class="row">
<div class="six columns forums-column">
<template v-if="type !== 'comments'">
<h5><i class="material-icons">sms</i> Topics</h5>
<p>The Most Recent Topics For You To Talk About...</p>
<hr>
</template>
<template v-if="type == 'comments'">
<!-- Add The Post Meta Here!! -->
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>{{ forum.title }}</b></h5>
<h6 class="card-subtitle mb-2 text-muted"><b>Author: {{ forum.user.name }}, Created {{ forum.timestamp }}</b></h6>
<hr>
<p class="card-text" v-html="forum.content"></p>
<div class="card-footer">
<ul>
<li class="activity forums" @click.prevent="like(forum.id)"><a href="#" class="card-link"><i class="material-icons">favorite</i> {{ forum.likes }}</a></li>
<li class="activity forums" @click.prevent="editForum(forum)"><a href="#" class="card-link"><i class="material-icons">edit</i> Edit</a></li>
</ul>
</div>
</div>
</div>
<h3><i class="material-icons medium">sms</i> Comments {{ forum.comments }}</h3>
<hr>
<!-- Add The Comments Here... -->
<div v-if="comments.length > 0">
<div class="card" v-for="postComment in comments" :key="postComment.id">
<div class="card-body">
<p><b>{{ postComment.user.name }} Created {{ postComment.humanTime }}</b></p>
<p v-html="postComment.comment"></p>
</div>
</div>
</div>
</template>
<template v-if="forums.length > 0 && type !== 'comments'">
<div class="forums" v-for="singleForum in forums" :key="singleForum.id">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>{{ singleForum.title }}</b></h5>
<h6 class="card-subtitle mb-2 text-muted"><b>Author: {{ singleForum.user.name }}, Created {{ singleForum.humanTime }}</b></h6>
<hr>
<p class="card-text" v-html="$options.filters.truncate(singleForum.content)"></p>
<div class="card-footer">
<ul>
<li class="activity forums" @click.prevent="like(singleForum.id)"><a href="#" class="card-link"><i class="material-icons">favorite</i> {{ singleForum.likes }}</a></li>
<li v-if="parseInt(singleForum.user.id) == user_id" @click.prevent="fetchAndAddComments(singleForum)" class="activity forums"><a href="#" class="card-link"><i class="material-icons">sms</i> {{ singleForum.comments }}</a></li>
<li class="activity forums" @click.prevent="editForum(singleForum)"><a href="#" class="card-link"><i class="material-icons">edit</i> Edit</a></li>
<li v-if="singleForum.user.id == user_id" class="activity forums" @click.prevent="deleteForum(singleForum.id)"><a href="#" class="card-link"><i class="material-icons">close</i></a></li>
</ul>
</div>
</div>
</div>
</div>
</template>
</div>
<div class="six columns">
<div class="forum-editor">
<h5 v-if="type === 'create'"><i class="material-icons">sms</i> Create A Topic...</h5>
<h5 v-if="type === 'edit'"><i class="material-icons">sms</i> <b>Update {{ forum.title }}</b>...</h5>
<h5 v-if="type === 'comments'"><i class="material-icons">sms</i> <b> Add A Comment.</b></h5>
<hr>
<form v-if="type === 'create'" method="post" @submit.prevent="createForum()">
<div class="form-group">
<label for="forum-title" class="col-md-4 col-form-label text-md-right">Forum Title</label>
<div class="col-md-6">
<input id="forum-title" type="text" class="form-control" name="text" required autofocus v-model="forum.title">
</div>
</div>
<div class="form-group">
<label for="forum-content" class="col-md-4 col-form-label text-md-right">Forum Content</label>
<div class="col-md-6">
<ckeditor v-model="forum.content" required placeholder="Start A Topic..." :config="editorConfig"></ckeditor>
</div>
</div>
<div class="form-group btn-div mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
Create Topic
</button>
</div>
</div>
</form>
<form v-if="type === 'edit'" method="post" @submit.prevent="updateForum()">
<div class="form-group">
<label for="forum-title" class="col-md-4 col-form-label text-md-right">Forum Title</label>
<div class="col-md-6">
<input id="forum-title" type="text" class="form-control" name="text" required autofocus v-model="forum.title">
</div>
</div>
<div class="form-group">
<label for="forum-content" class="col-md-4 col-form-label text-md-right">Forum Content</label>
<div class="col-md-6">
<ckeditor v-model="forum.content" required placeholder="Start A Topic..." :config="editorConfig"></ckeditor>
</div>
</div>
<div class="form-group btn-div mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
Update Topic
</button>
</div>
</div>
</form>
<form v-if="type === 'comments'" @submit.prevent="addComment()" method="post" >
<div class="form-group">
<label for="forum-content" class="col-md-4 col-form-label text-md-right">Your Comment</label>
<div class="col-md-6">
<ckeditor v-model="comment" required placeholder="Enter A Comment..." :config="editorConfig"></ckeditor>
</div>
</div>
<div class="form-group btn-div mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
Comment
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script type="text/javascript">
import axios from 'axios';
import swal from 'sweetalert';
import Nav from '../includes/Nav';
export default {
data() {
return {
editorConfig: {},
forum: {
id: null,
user: {},
title: '',
content: '',
likes: 0,
comments: 0,
timestamp: ''
},
type: 'create',
forums: [],
comment: '',
user_id: '',
comments: [],
accessToken: '',
}
},
components: {
Nav
},
async mounted() {
await this.fetchForums();
this.user_id = parseInt(localStorage.getItem('user-id'));
},
filters: {
truncate(value) {
// Make sure an element and number of items to truncate is provided
if (!value) return;
// Get the inner content of the element
var content = value.trim();
// Convert the content into an array of words
// Remove any words above the limit
if (value.length > 25) {
content = content.split(' ').slice(0, 25);
// Convert the array of words back into a string
content = content.join(' ') + '.....';
return content;
}
return value;
},
},
methods: {
async createForum() {
try {
if (this.forum.content.trim() == '') {
swal('Forum Content', 'Sorry, This Field Cannot Be Empty. Please, Write A Story To Continue.', 'error');
return;
}
// create a simple forum..........
let createdForum = await axios.post(this.$baseUrl + 'forum/create', this.forum, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (createdForum.status == 201) {
swal('Topic Created.', 'Your Topic Has Been Created Successfully', 'success');
this.forums.unshift(createdForum.data.data);
return;
}
} catch (e) {
let errorData = e.response.data;
if (errorData.status == 400) {
for (const error in errorData.errors) {
swal(
`${error} Error: `,
errorData.errors[error][0],
'error'
);
}
return;
}
swal('Operation Failed', errorData.message, 'error');
return;
}
},
async updateForum() {
try {
if (this.forum.content.trim() == '') {
swal('Forum Content', 'Sorry, This Field Cannot Be Empty. Please, Write A Story To Continue.', 'error');
return;
}
// create a simple forum..........
let updatedForum = await axios.post(this.$baseUrl + 'forum/update/' + this.forum.id, this.forum, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (updatedForum.status == 200) {
swal('Topic Updated.', 'Your Topic Has Been Updated Successfully', 'success');
this.forums = this.forums.map((el) => {
if (parseInt(el.id) == parseInt(this.forum.id)) {
el.title = this.forum.title;
el.content = this.forum.content;
}
return el;
});
this.type = 'create';
this.forum.id = null;
this.forum.title = '';
this.forum.content = '';
return;
}
} catch (e) {
let errorData = e.response.data;
if (errorData.status == 400) {
for (const error in errorData.errors) {
swal(
`${error} Error: `,
errorData.errors[error][0],
'error'
);
}
return;
}
swal('Operation Failed', errorData.message, 'error');
return;
}
},
async fetchForums() {
try {
let forums = await axios.get(this.$baseUrl + 'forum', {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (forums.status == 200) {
this.forums = forums.data.data;
return;
}
} catch (e) {
this.forums = [];
return;
}
},
async fetchAndAddComments(forumComment) {
try {
let forumAndComment = await axios.get(this.$baseUrl + 'forum/comments/' + forumComment.id, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (forumAndComment.status == 200) {
this.type = 'comments';
this.forum.id = forumAndComment.data.data.id;
this.forum.title = forumAndComment.data.data.title;
this.forum.content = forumAndComment.data.data.content;
this.forum.likes = forumAndComment.data.data.likes;
this.forum.comments = forumAndComment.data.data.comments;
this.forum.timestamp = forumAndComment.data.timestamp;
this.forum.user = forumAndComment.data.data.user;
await this.fetchComments(forumComment.id);
return;
}
} catch (e) {
this.type = 'create';
this.forum.id = '';
this.forum.title = '';
this.forum.content = '';
this.forum.likes = '';
this.forum.comments = '';
this.forum.timestamp = '';
return;
}
},
async fetchComments(forumId) {
try {
let comments = await axios.get(this.$baseUrl + 'comments/' + forumId, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (comments.status == 200) {
this.comments = comments.data.comments;
return;
}
this.comments = [];
return;
} catch (e) {
console.log(e);
this.comments = [];
return;
}
},
async editForum(forumToUpdate) {
this.type = 'edit';
this.forum.id = forumToUpdate.id;
this.forum.title = forumToUpdate.title;
this.forum.content = forumToUpdate.content;
},
async addComment() {
try {
let comment = await axios.post(this.$baseUrl + 'comment/' + this.forum.id, {
comment: this.comment
}, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (comment.status == 201) {
swal('Success', 'Your Comment Has Been Saved Successfully.', 'success');
this.comments.unshift(comment.data.data);
this.forum.comments += 1;
return;
}
swal('Operation Failed', 'Oops, An Unexpected Error Occurred And Your Comment Could Not Be Saved.', 'error');
return;
} catch (e) {
let errorData = e.response.data;
if (errorData.status == 400) {
for (const error in errorData.errors) {
swal(
`${error} Error: `,
errorData.errors[error][0],
'error'
);
}
return;
}
swal('Operation Failed', errorData.message, 'error');
return;
}
},
async like(forumId) {
try {
let liked = await axios.get(this.$baseUrl + 'forum/like/' + forumId, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (liked.status == 200) {
this.forums = this.forums.map((el) => {
if (parseInt(el.id) == parseInt(forumId)) {
el.likes += 1;
}
return el;
});
swal({
icon: 'success'
});
return;
}
} catch (e) {
this.forums = [];
return;
}
},
async deleteForum(forumId) {
try {
let deletedForum = await axios.delete(this.$baseUrl + 'forum/delete/' + forumId, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accessToken,
'Cache-Control': 'no-cache'
}
});
if (deletedForum.status == 200) {
swal('success', 'The Selected Forum Has Been Deleted Successfully!', 'success');
this.forums = this.forums.filter((el) => {
if (el.id == forumId) return false;
})
return;
}
swal('Operation Failed', 'The Selected Forum Could Not Be Deleted Successfully. Please, Try Again Later!', 'error');
return;
} catch (e) {
let errorData = e.response.data;
if (errorData.status == 400) {
for (const error in errorData.errors) {
swal(
`${error} Error: `,
errorData.errors[error][0],
'error'
);
}
return;
}
swal('Operation Failed', errorData.message, 'error');
return;
}
}
},
async created() {
try {
let userSecret = localStorage.getItem('access-token');
this.accessToken = userSecret;
// check if the user access token is set.....
if (userSecret.trim() !== '') {
let user = await axios.get(this.$baseUrl + 'user', {
headers: {
Accept: 'application/json',
'Authorization': 'Bearer ' + userSecret,
'Cache-Control': 'no-cache'
}
});
// check for a status code other than 200.....
if (user.status != 200) {
swal('Unauthorized Access', 'Sorry, You Do Not Have Enough Priviledge To Access This Page.', 'error');
setTimeout(() => {
this.$router.push({
name: 'Welcome'
});
}, 1000);
return;
}
}
if (userSecret.trim() == '') {
swal('Unauthorized Access', 'Sorry, You Do Not Have Enough Priviledge To Access This Page.', 'error');
setTimeout(() => {
this.$router.push({
name: 'Welcome'
});
}, 1000);
return;
}
} catch (e) {
swal('Unauthorized Access', 'Sorry, You Do Not Have Enough Priviledge To Access This Page.', 'error');
setTimeout(() => {
this.$router.push({
name: 'Welcome'
});
}, 1000);
return;
}
}
}
</script>
<style scoped>
.form-control {
width: 100% !important;
}
.forums-column {
padding-right: 100px;
border-right: 1px solid grey;
}
.forum-editor, .forums {
padding: 10px 10px;
}
.app_description {
margin-left: -1%;
}
.btn-div {
margin-top: 15px;
}
.forums {
border-radius: 4px;
margin: 20px 0;
}
.card {
cursor: pointer;
}
ul {
list-style: none;
display: inline-flex;
}
ul li {
margin: 0 5px !important;
}
.activity {
padding: 5px 5px !important;
}
.material-icons {
vertical-align: middle;
}
a {
text-decoration: none;
}
.activity:nth-of-type(1) a,
.activity:nth-of-type(4) a {
color: red;
font-weight: 600;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment