From 02a92ffc4a6d210d7f91397b6b3e22b372951a94 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 15:00:35 +0800 Subject: [PATCH 01/10] Add jsonfig for easier DX --- jsconfig.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 jsconfig.json diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000..ff0b7e68 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "baseUrl": "./src" + }, + "exclude": ["node_modules"] +} \ No newline at end of file From a8c2f978814f5bbfe6799b861d2e95eac02f14ec Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 15:06:31 +0800 Subject: [PATCH 02/10] Use graphql alias to mitigate API change --- ducks/articleDetail.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index ea221e4e..ec44e664 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -31,13 +31,13 @@ const fragments = { } } `, - replyConnectionAndUserFields: ` + articleReplyAndUserFields: ` fragment userFields on User { id name avatarUrl } - fragment replyConnectionFields on ReplyConnection { + fragment articleReplyFields on ArticleReply { id canUpdateStatus status @@ -74,14 +74,14 @@ export const load = id => dispatch => { GetArticle(id: $id) { ...articleFields user { ...userFields } - replyConnections { ...replyConnectionFields } + replyConnections: articleReplies { ...articleReplyFields } relatedArticles(filter: {replyCount: {GT: 0}}) { edges { node { ...articleFields user { ...userFields } replyCount - replyConnections { ...replyConnectionFields } + replyConnections: articleReplies { ...articleReplyFields } } score } @@ -89,7 +89,7 @@ export const load = id => dispatch => { } } ${fragments.articleFields} - ${fragments.replyConnectionAndUserFields} + ${fragments.articleReplyAndUserFields} `({ id }).then(resp => { dispatch(loadData(resp.getIn(['data', 'GetArticle']))); dispatch(setState({ key: 'isLoading', value: false })); @@ -103,7 +103,7 @@ export const loadAuth = id => dispatch => { gql` query($id: String!) { GetArticle(id: $id) { - replyConnections { + replyConnections: articleReplies { id canUpdateStatus } @@ -124,11 +124,11 @@ const reloadReply = articleId => dispatch => query($id: String!) { GetArticle(id: $id) { replyConnections { - ...replyConnectionFields + ...articleReplyFields } } } - ${fragments.replyConnectionAndUserFields} + ${fragments.articleReplyAndUserFields} `({ id: articleId }).then(resp => { dispatch(loadData(resp.getIn(['data', 'GetArticle']))); dispatch(setState({ key: 'isReplyLoading', value: false })); @@ -236,7 +236,7 @@ export const searchReplies = ({ q }) => dispatch => { type createdAt } - replyConnections { + replyConnections: articleReplies { article { id text From d82929a1c7a1a3f726e9b72cfd69254d2cc14b0c Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 17:19:06 +0800 Subject: [PATCH 03/10] Fix jsconfig --- jsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsconfig.json b/jsconfig.json index ff0b7e68..67fc4dda 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "baseUrl": "./src" + "baseUrl": "./" }, "exclude": ["node_modules"] } \ No newline at end of file From 31c0e3236ed89f57ff133870f87ce182d269f83d Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 17:42:34 +0800 Subject: [PATCH 04/10] Fix UpdateArticleReplyStatus calls --- components/CurrentReplies.js | 4 ++-- components/ReplyConnection.js | 2 +- ducks/articleDetail.js | 27 +++++++++++++++++---------- ducks/replyDetail.js | 25 +++++++++++++++++-------- pages/article.js | 10 +++++----- pages/reply.js | 10 +++++----- 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/components/CurrentReplies.js b/components/CurrentReplies.js index 8e8b5624..f6667709 100644 --- a/components/CurrentReplies.js +++ b/components/CurrentReplies.js @@ -43,7 +43,7 @@ class DeletedItems extends React.Component {
    {items.map(conn => ( ( { const { replyConnection, onAction } = this.props; - return onAction(replyConnection.get('id')); + return onAction(replyConnection); }; renderHint = () => { diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index ec44e664..0c481f93 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -38,9 +38,10 @@ const fragments = { avatarUrl } fragment articleReplyFields on ArticleReply { - id canUpdateStatus status + articleId + replyId reply { id versions(limit: 1) { @@ -104,7 +105,8 @@ export const loadAuth = id => dispatch => { query($id: String!) { GetArticle(id: $id) { replyConnections: articleReplies { - id + articleId + replyId canUpdateStatus } } @@ -149,23 +151,28 @@ export const connectReply = (articleId, replyId) => dispatch => { }); }; -export const updateReplyConnectionStatus = ( +export const updateArticleReplyStatus = ( articleId, - replyConnectionId, + replyId, status ) => dispatch => { dispatch(setState({ key: 'isReplyLoading', value: true })); NProgress.start(); return gql` - mutation($replyConnectionId: String!, $status: ReplyConnectionStatusEnum!) { - UpdateReplyConnectionStatus( - replyConnectionId: $replyConnectionId + mutation( + $articleId: String! + $replyId: String! + $status: ArticleReplyStatusEnum! + ) { + UpdateArticleReplyStatus( + articleId: $articleId + replyId: $replyId status: $status ) { id } } - `({ replyConnectionId, status }).then(() => { + `({ articleId, replyId, status }).then(() => { dispatch(reloadReply(articleId)); NProgress.done(); }); @@ -402,11 +409,11 @@ export default createReducer( [LOAD_AUTH]: (state, { payload }) => { const idAuthMap = payload.get('replyConnections').reduce((agg, conn) => { - agg[conn.get('id')] = conn; + agg[conn.get('replyId')] = conn; return agg; }, {}); return state.updateIn(['data', 'replyConnections'], replyConnections => - replyConnections.map(conn => conn.merge(idAuthMap[conn.get('id')])) + replyConnections.map(conn => conn.merge(idAuthMap[conn.get('replyId')])) ); }, diff --git a/ducks/replyDetail.js b/ducks/replyDetail.js index b6bddc75..3b5e957a 100644 --- a/ducks/replyDetail.js +++ b/ducks/replyDetail.js @@ -31,13 +31,15 @@ export const load = id => dispatch => { reference createdAt } - replyConnections { + replyConnections: articleReplies { id + articleId article { id text replyCount } + replyId user { name } @@ -63,8 +65,10 @@ export const loadAuth = id => dispatch => { gql` query($id: String!) { GetReply(id: $id) { - replyConnections { + replyConnections: articleReplies { id + articleId + replyId canUpdateStatus } } @@ -77,23 +81,28 @@ export const loadAuth = id => dispatch => { }); }; -export const updateReplyConnectionStatus = ( +export const updateArticleReplyStatus = ( + articleId, replyId, - replyConnectionId, status ) => dispatch => { dispatch(setState({ key: 'isReplyLoading', value: true })); NProgress.start(); return gql` - mutation($replyConnectionId: String!, $status: ReplyConnectionStatusEnum!) { - UpdateReplyConnectionStatus( - replyConnectionId: $replyConnectionId + mutation( + $articleId: String! + $replyId: String! + $status: ArticleReplyStatusEnum! + ) { + UpdateArticleReplyStatus( + articleId: $articleId + replyId: $replyId status: $status ) { id } } - `({ replyConnectionId, status }).then(() => { + `({ articleId, replyId, status }).then(() => { // FIXME: // Immediate load(replyId) will not get updated reply connection status. // Super wierd. diff --git a/pages/article.js b/pages/article.js index e8cb42bc..a93d7e3a 100644 --- a/pages/article.js +++ b/pages/article.js @@ -20,7 +20,7 @@ import { connectReply, searchReplies, searchRepiedArticle, - updateReplyConnectionStatus, + updateArticleReplyStatus, voteReply, reset, } from 'ducks/articleDetail'; @@ -71,17 +71,17 @@ class ArticlePage extends React.Component { ); }; - handleReplyConnectionDelete = replyConnectionId => { + handleReplyConnectionDelete = conn => { const { dispatch, query: { id } } = this.props; return dispatch( - updateReplyConnectionStatus(id, replyConnectionId, 'DELETED') + updateArticleReplyStatus(id, conn.get('replyId'), 'DELETED') ); }; - handleReplyConnectionRestore = replyConnectionId => { + handleReplyConnectionRestore = conn => { const { dispatch, query: { id } } = this.props; return dispatch( - updateReplyConnectionStatus(id, replyConnectionId, 'NORMAL') + updateArticleReplyStatus(id, conn.get('replyId'), 'NORMAL') ).then(this.scrollToReplySection); }; diff --git a/pages/reply.js b/pages/reply.js index b237a95c..42986210 100644 --- a/pages/reply.js +++ b/pages/reply.js @@ -6,7 +6,7 @@ import { compose } from 'redux'; import { load, loadAuth, - updateReplyConnectionStatus, + updateArticleReplyStatus, voteReply, } from '../ducks/replyDetail'; import Head from 'next/head'; @@ -49,9 +49,9 @@ class ReplyPage extends React.Component { handleReplyConnectionDelete = () => { const { dispatch, originalReplyConnection, query: { id } } = this.props; return dispatch( - updateReplyConnectionStatus( + updateArticleReplyStatus( + originalReplyConnection.get('articleId'), id, - originalReplyConnection.get('id'), 'DELETED' ) ); @@ -60,9 +60,9 @@ class ReplyPage extends React.Component { handleReplyConnectionRestore = () => { const { dispatch, originalReplyConnection, query: { id } } = this.props; return dispatch( - updateReplyConnectionStatus( + updateArticleReplyStatus( + originalReplyConnection.get('articleId'), id, - originalReplyConnection.get('id'), 'NORMAL' ) ); From 704cfc5996ddec6faa37759fbd1059823b4976b8 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 18:23:43 +0800 Subject: [PATCH 05/10] Update CreateArticleReply API call --- ducks/articleDetail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index 0c481f93..b18a2104 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -141,7 +141,7 @@ export const connectReply = (articleId, replyId) => dispatch => { NProgress.start(); return gql` mutation($articleId: String!, $replyId: String!) { - CreateReplyConnection(articleId: $articleId, replyId: $replyId) { + CreateArticleReply(articleId: $articleId, replyId: $replyId) { id } } From 824132853bd546ff1d96ebffc5aa8110047c0068 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 18:26:39 +0800 Subject: [PATCH 06/10] Avoid using deprecated "replyConnections" field --- ducks/articleDetail.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index b18a2104..2651e255 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -125,7 +125,7 @@ const reloadReply = articleId => dispatch => gql` query($id: String!) { GetArticle(id: $id) { - replyConnections { + replyConnections: articleReplies { ...articleReplyFields } } @@ -292,7 +292,7 @@ export const searchRepiedArticle = ({ q }) => dispatch => { text replyCount createdAt - replyConnections { + replyConnections: articleReplies { reply { id versions { From 10deebc24175466760f36e4d0161157e09a2e9bc Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 20:26:00 +0800 Subject: [PATCH 07/10] Fix article & reply page voting mechanism --- components/ReplyFeedback.js | 4 ++-- ducks/articleDetail.js | 11 ++++++----- ducks/replyDetail.js | 11 ++++++----- pages/article.js | 4 ++-- pages/reply.js | 4 ++-- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/components/ReplyFeedback.js b/components/ReplyFeedback.js index 28f69688..cf94ee3c 100644 --- a/components/ReplyFeedback.js +++ b/components/ReplyFeedback.js @@ -25,12 +25,12 @@ export default class ReplyFeedback extends PureComponent { handleUpVote = () => { const { replyConnection, onVote } = this.props; - return onVote(replyConnection.get('id'), 'UPVOTE'); + return onVote(replyConnection, 'UPVOTE'); }; handleDownVote = () => { const { replyConnection, onVote } = this.props; - return onVote(replyConnection.get('id'), 'DOWNVOTE'); + return onVote(replyConnection, 'DOWNVOTE'); }; getFeedbackScore = () => { diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index 2651e255..0eacd776 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -203,19 +203,20 @@ export const submitReply = params => dispatch => { }); }; -export const voteReply = (articleId, replyConnectionId, vote) => dispatch => { +export const voteReply = (articleId, replyId, vote) => dispatch => { dispatch(setState({ key: 'isReplyLoading', value: true })); NProgress.start(); return gql` - mutation($replyConnectionId: String!, $vote: FeedbackVote!) { - CreateOrUpdateReplyConnectionFeedback( - replyConnectionId: $replyConnectionId + mutation($articleId: String!, $replyId: String!, $vote: FeedbackVote!) { + CreateOrUpdateArticleReplyFeedback( + articleId: $articleId + replyId: $replyId vote: $vote ) { feedbackCount } } - `({ replyConnectionId, vote }).then(() => { + `({ articleId, replyId, vote }).then(() => { dispatch(reloadReply(articleId)); NProgress.done(); }); diff --git a/ducks/replyDetail.js b/ducks/replyDetail.js index 3b5e957a..2afcfd0d 100644 --- a/ducks/replyDetail.js +++ b/ducks/replyDetail.js @@ -116,19 +116,20 @@ export const updateArticleReplyStatus = ( }); }; -export const voteReply = (replyId, replyConnectionId, vote) => dispatch => { +export const voteReply = (articleId, replyId, vote) => dispatch => { dispatch(setState({ key: 'isReplyLoading', value: true })); NProgress.start(); return gql` - mutation($replyConnectionId: String!, $vote: FeedbackVote!) { - CreateOrUpdateReplyConnectionFeedback( - replyConnectionId: $replyConnectionId + mutation($articleId: String!, $replyId: String!, $vote: FeedbackVote!) { + CreateOrUpdateArticleReplyFeedback( + articleId: $articleId + replyId: $replyId vote: $vote ) { feedbackCount } } - `({ replyConnectionId, vote }).then(() => { + `({ articleId, replyId, vote }).then(() => { dispatch(load(replyId)).then(() => { dispatch(setState({ key: 'isReplyLoading', value: false })); }); diff --git a/pages/article.js b/pages/article.js index a93d7e3a..23f4923c 100644 --- a/pages/article.js +++ b/pages/article.js @@ -85,9 +85,9 @@ class ArticlePage extends React.Component { ).then(this.scrollToReplySection); }; - handleReplyConnectionVote = (replyConnectionId, vote) => { + handleReplyConnectionVote = (conn, vote) => { const { dispatch, query: { id } } = this.props; - return dispatch(voteReply(id, replyConnectionId, vote)); + return dispatch(voteReply(id, conn.get('replyId'), vote)); }; handleTabChange = tab => () => { diff --git a/pages/reply.js b/pages/reply.js index 42986210..84e7be85 100644 --- a/pages/reply.js +++ b/pages/reply.js @@ -84,9 +84,9 @@ class ReplyPage extends React.Component { ); }; - handleReplyConnectionVote = (replyConnectionId, vote) => { + handleReplyConnectionVote = (conn, vote) => { const { dispatch, query: { id } } = this.props; - return dispatch(voteReply(id, replyConnectionId, vote)); + return dispatch(voteReply(conn.get('articleId'), id, vote)); }; renderReply = () => { From 3a2a2d2c47a4426fb521fbf095129768f113ca41 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Sun, 18 Feb 2018 20:32:02 +0800 Subject: [PATCH 08/10] Update articleDetail fixture & test snapshot --- .../__snapshots__/articleDetail.js.snap | 6 ++++-- ducks/fixtures/articleDetail.js | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ducks/__tests__/__snapshots__/articleDetail.js.snap b/ducks/__tests__/__snapshots__/articleDetail.js.snap index af7920b4..995b91ca 100644 --- a/ducks/__tests__/__snapshots__/articleDetail.js.snap +++ b/ducks/__tests__/__snapshots__/articleDetail.js.snap @@ -11,7 +11,8 @@ Immutable.Map { }, "replyConnections": Immutable.List [ Immutable.Map { - "id": "article1-reply1", + "articleId": "article1", + "replyId": "reply1", "canUpdateStatus": true, "status": "NORMAL", "reply": Immutable.Map { @@ -75,7 +76,8 @@ Immutable.Map { exports[`reducer: articleDetail handles LOAD_AUTH 1`] = ` Immutable.List [ Immutable.Map { - "id": "article1-reply1", + "articleId": "article1", + "replyId": "reply1", "canUpdateStatus": true, "status": "NORMAL", "reply": Immutable.Map { diff --git a/ducks/fixtures/articleDetail.js b/ducks/fixtures/articleDetail.js index 27dad387..0361cbf2 100644 --- a/ducks/fixtures/articleDetail.js +++ b/ducks/fixtures/articleDetail.js @@ -18,7 +18,8 @@ export const loadAction = { id: 'article1', replyConnections: [ { - id: 'article1-relatedReply1', + articleId: 'article1', + replyId: 'relatedReply1', canUpdateStatus: false, reply: { id: 'relatedReply1', @@ -31,7 +32,8 @@ export const loadAction = { }, }, { - id: 'article1-relatedReply2', + articleId: 'article1', + replyId: 'relatedReply2', canUpdateStatus: false, reply: { id: 'relatedReply2', @@ -44,7 +46,8 @@ export const loadAction = { }, }, { - id: 'article1-reply1', + articleId: 'article1', + replyId: 'reply1', canUpdateStatus: false, reply: { id: 'reply1', // Already added to article (exists in replyConnections) @@ -67,7 +70,8 @@ export const loadAction = { text: '~~黎建南給退休軍公教人員的一封公開信~~', replyConnections: [ { - id: 'article2-relatedReply1', + articleId: 'article2', + replyId: 'relatedReply1', canUpdateStatus: false, reply: { // This is duplicated with related article 1 @@ -88,7 +92,8 @@ export const loadAction = { replyRequestCount: 1, replyConnections: [ { - id: 'article1-reply1', + articleId: 'article1', + replyId: 'reply1', canUpdateStatus: true, status: 'NORMAL', reply: { @@ -188,7 +193,8 @@ export const loadAuthAction = { payload: fromJS({ replyConnections: [ { - id: 'AV9mEFX2yCdS-nWhuiPu__AV9mJJ5qyCdS-nWhuiPz', + articleId: 'AV9mEFX2yCdS-nWhuiPu', + replyId: 'AV9mJJ5qyCdS-nWhuiPz', canUpdateStatus: true, }, ], From c47f113c4ea50a62825f52f756943def0054d799 Mon Sep 17 00:00:00 2001 From: MrOrz Date: Mon, 19 Feb 2018 20:50:58 +0800 Subject: [PATCH 09/10] Avoid using "replyConnections" field and query its ID --- ducks/replyDetail.js | 1 - ducks/replyList.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ducks/replyDetail.js b/ducks/replyDetail.js index 2afcfd0d..a2410e5c 100644 --- a/ducks/replyDetail.js +++ b/ducks/replyDetail.js @@ -32,7 +32,6 @@ export const load = id => dispatch => { createdAt } replyConnections: articleReplies { - id articleId article { id diff --git a/ducks/replyList.js b/ducks/replyList.js index 800525c6..ec8da24b 100644 --- a/ducks/replyList.js +++ b/ducks/replyList.js @@ -69,7 +69,7 @@ export const load = ({ type createdAt } - replyConnections(status: NORMAL) { id } + replyConnections: articleReplies(status: NORMAL) { replyId } } cursor } From ab6d364b428417631f9d10984d6edc12b0d3099c Mon Sep 17 00:00:00 2001 From: MrOrz Date: Tue, 20 Feb 2018 00:37:29 +0800 Subject: [PATCH 10/10] Remove articleReply index to fix reply page auth loading --- ducks/articleDetail.js | 2 +- ducks/replyDetail.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ducks/articleDetail.js b/ducks/articleDetail.js index 0eacd776..a6babdf8 100644 --- a/ducks/articleDetail.js +++ b/ducks/articleDetail.js @@ -169,7 +169,7 @@ export const updateArticleReplyStatus = ( replyId: $replyId status: $status ) { - id + status } } `({ articleId, replyId, status }).then(() => { diff --git a/ducks/replyDetail.js b/ducks/replyDetail.js index a2410e5c..d270c7bf 100644 --- a/ducks/replyDetail.js +++ b/ducks/replyDetail.js @@ -65,7 +65,6 @@ export const loadAuth = id => dispatch => { query($id: String!) { GetReply(id: $id) { replyConnections: articleReplies { - id articleId replyId canUpdateStatus @@ -98,7 +97,7 @@ export const updateArticleReplyStatus = ( replyId: $replyId status: $status ) { - id + status } } `({ articleId, replyId, status }).then(() => {