Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

コメント機能を実装しました! #100

Merged
merged 12 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions components/Comment.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div class="box">
<div class="columns">
<div class="column has-text-left">
{{ comment.body }}
</div>
<div class="column has-text-right">
at {{ comment.createdAt.toDate().toLocaleDateString() }}
</div>
</div>
</div>
</template>

<script>
export default {
props: {
comment: { type: Object, default: () => {} },
},
};
</script>

<style></style>
59 changes: 58 additions & 1 deletion pages/_nodeId/_articleId.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,32 @@
<span v-show="isZbzbPushed == true">{{ zbzb_count }} ずぶった!</span>
</button>
<button class="button share-button" @click="goTwitter()">Tweet</button>
<!-- TODO: コメント投稿フォーム -->
<!-- - 各記事詳細画面の下の方に,コメントを各機能を入れる
- コメント書く所,送信ボタンの簡単な設計でいい
- ただのテキストをfirebaseの各記事に登録する
- 各記事のサブコレクションにcommentsを入れる -->
<div class="columns">
<input
v-model="inputComment"
class="input column"
placeholder="コメント"
/>
<button
v-bind:disabled="isNoComment()"
type="button"
class="button column is-one-fifth"
:class="{ 'is-success': !isNoComment() }"
@click="submit"
>
コメントする
</button>
</div>
<ul>
<li v-for="comment in comments" :key="comment.id">
<Comment :comment="comment" />
</li>
</ul>
</div>
</div>
</template>
Expand All @@ -43,7 +69,11 @@
import "mavon-editor/dist/css/index.css";

export default {
data() {
async asyncData({ params, $fetchComments }) {
// コメントを取得
let comments = await $fetchComments(params.articleId);
// 日付の新しい順に並び替える
comments.reverse();
return {
title: "",
tags: [],
Expand All @@ -54,6 +84,12 @@ export default {
currentTagId: null,
authorName: "ほびーさん",
shareUrl: "",
// DBから取得したコメントの配列
comments: comments,
// DBに登録する予定のコメントの文字列
inputComment: "",
// コメント入力欄が空文字列かどうか
noComment: true,
markdownOption: {
bold: true,
italic: true,
Expand Down Expand Up @@ -124,6 +160,27 @@ export default {
goTwitter() {
window.open(this.shareUrl);
},
isNoComment() {
return this.inputComment === "";
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これでも動くけど常に判定し続けるものはcomputedに書くのがセオリーな感じがする!!

async submit() {
// タイプスタンプ取得
let timestamp = await this.$getFirebaseTimestamp();
// コメントのオブジェクト生成
let comment = {
id: null,
body: this.inputComment,
createdAt: timestamp,
updatedAt: timestamp,
};
// コメントをDBに登録
await this.$registerComment(comment, this.articleId);
// 入力フォームを空にする
this.inputComment = "";
// 投稿後強制的にリロードする
// FIXME: ちょっとおそい,どうすれば?? -> コンポーネントだけを再描画したい
this.$router.go({ path: this.$router.currentRoute.path, force: true });
},
},
};
</script>
Expand Down
54 changes: 53 additions & 1 deletion plugins/firebaseUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,59 @@ Vue.prototype.$deleteTag = async function deleteTag(targetNodeId) {
.delete()
.then(() => {
console.debug(`Tag has been successfully deleted!: ${targetNodeId}`);
}).catch((error) => {
})
.catch((error) => {
console.error(`Error delete tag: ${error}`);
});
};

/**
* コメントを取得する
* @param {String} articleId 記事のID
*/
Vue.prototype.$fetchComments = async function fetchComments(articleId) {
return await db
.collection("articles")
.doc(articleId)
.collection("comments")
.get()
.then((querySnapshot) => {
const comments = [];
querySnapshot.forEach((doc) => {
comments.push(doc.data());
});
return comments;
})
.catch((error) => {
console.error(`Error fetch comments: ${error}`);
});
};

/**
* 入力された記事を投稿する
* @param {Object} comment コメントのオブジェクト
* @param {String} articleId コメントされた記事のID
*/
Vue.prototype.$registerComment = async function registerComment(
comment,
articleId
) {
console.debug(`register comment: ${JSON.stringify(comment)}`);
// 記事へのコメントへの参照
let ref = await db
.collection("articles")
.doc(articleId)
.collection("comments");
await ref
.add(comment)
.then((newComment) => {
ref.doc(newComment.id).update({
id: newComment.id,
});
})
.catch((error) => {
console.log(`Error register comment: ${error}`);
});
};

export default (context) => {
Expand All @@ -407,6 +457,8 @@ export default (context) => {
context.$addTagSuggestions = Vue.prototype.$addTagSuggestions;
context.$deleteArticle = Vue.prototype.$deleteArticle;
context.$deleteTag = Vue.prototype.$deleteTag;
context.$fetchComments = Vue.prototype.$fetchComments;
context.$registerComment = Vue.prototype.$registerComment;
};
// 現在時刻を取得する
Vue.prototype.$getFirebaseTimestamp = async function getFirebaseTimestamp() {
Expand Down