Merge pull request #148 from lbryio/comment-redux
redux comments DRAFT WIP
This commit is contained in:
commit
1415935006
11 changed files with 419 additions and 10 deletions
186
dist/bundle.es.js
vendored
186
dist/bundle.es.js
vendored
|
@ -102,6 +102,14 @@ const CLAIM_SEARCH_STARTED = 'CLAIM_SEARCH_STARTED';
|
|||
const CLAIM_SEARCH_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
|
||||
const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED';
|
||||
|
||||
// Comments
|
||||
const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
|
||||
const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED';
|
||||
const COMMENT_LIST_FAILED = 'COMMENT_LIST_FAILED';
|
||||
const COMMENT_CREATE_STARTED = 'COMMENT_CREATE_STARTED';
|
||||
const COMMENT_CREATE_COMPLETED = 'COMMENT_CREATE_COMPLETED';
|
||||
const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED';
|
||||
|
||||
// Files
|
||||
const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
||||
const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||
|
@ -318,6 +326,12 @@ var action_types = /*#__PURE__*/Object.freeze({
|
|||
CLAIM_SEARCH_STARTED: CLAIM_SEARCH_STARTED,
|
||||
CLAIM_SEARCH_COMPLETED: CLAIM_SEARCH_COMPLETED,
|
||||
CLAIM_SEARCH_FAILED: CLAIM_SEARCH_FAILED,
|
||||
COMMENT_LIST_STARTED: COMMENT_LIST_STARTED,
|
||||
COMMENT_LIST_COMPLETED: COMMENT_LIST_COMPLETED,
|
||||
COMMENT_LIST_FAILED: COMMENT_LIST_FAILED,
|
||||
COMMENT_CREATE_STARTED: COMMENT_CREATE_STARTED,
|
||||
COMMENT_CREATE_COMPLETED: COMMENT_CREATE_COMPLETED,
|
||||
COMMENT_CREATE_FAILED: COMMENT_CREATE_FAILED,
|
||||
FILE_LIST_STARTED: FILE_LIST_STARTED,
|
||||
FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED,
|
||||
FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED,
|
||||
|
@ -676,6 +690,9 @@ const Lbry = {
|
|||
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
|
||||
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),
|
||||
|
||||
// Comments
|
||||
comment_list: (params = {}) => daemonCallWithResult('comment_list', params),
|
||||
comment_create: (params = {}) => daemonCallWithResult('comment_create', params),
|
||||
// Connect to the sdk
|
||||
connect: () => {
|
||||
if (Lbry.connectPromise === null) {
|
||||
|
@ -2761,6 +2778,72 @@ const doDeleteTag = name => ({
|
|||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
function doCommentList(uri) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const claim = selectClaimsByUri(state)[uri];
|
||||
const claimId = claim ? claim.claim_id : null;
|
||||
|
||||
dispatch({
|
||||
type: COMMENT_LIST_STARTED
|
||||
});
|
||||
lbryProxy.comment_list({
|
||||
claim_id: claimId
|
||||
}).then(results => {
|
||||
dispatch({
|
||||
type: COMMENT_LIST_COMPLETED,
|
||||
data: {
|
||||
comments: results,
|
||||
claimId: claimId,
|
||||
uri: uri
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
dispatch({
|
||||
type: COMMENT_LIST_FAILED,
|
||||
data: error
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function doCommentCreate(comment = '', claim_id = '', channel, parent_id) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
dispatch({
|
||||
type: COMMENT_CREATE_STARTED
|
||||
});
|
||||
const myChannels = selectMyChannelClaims(state);
|
||||
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
|
||||
const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null;
|
||||
return lbryProxy.comment_create({
|
||||
comment,
|
||||
claim_id,
|
||||
channel_id
|
||||
}).then(result => {
|
||||
dispatch({
|
||||
type: COMMENT_CREATE_COMPLETED,
|
||||
data: {
|
||||
comment: result,
|
||||
claimId: claim_id
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
dispatch({
|
||||
type: COMMENT_CREATE_FAILED,
|
||||
data: error
|
||||
});
|
||||
dispatch(doToast({
|
||||
message: 'Oops, someone broke comments.',
|
||||
isError: true
|
||||
}));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
var _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
const reducers = {};
|
||||
|
@ -3726,6 +3809,60 @@ function contentReducer(state = defaultState$6, action) {
|
|||
|
||||
var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
const defaultState$7 = {
|
||||
byId: {},
|
||||
commentsByUri: {},
|
||||
isLoading: false
|
||||
};
|
||||
|
||||
const commentReducer = handleActions({
|
||||
[COMMENT_CREATE_STARTED]: (state, action) => _extends$b({}, state, {
|
||||
isLoading: true
|
||||
}),
|
||||
|
||||
[COMMENT_CREATE_FAILED]: (state, action) => _extends$b({}, state, {
|
||||
isLoading: false
|
||||
}),
|
||||
|
||||
[COMMENT_CREATE_COMPLETED]: (state, action) => {
|
||||
const { comment, claimId } = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const comments = byId[claimId];
|
||||
const newComments = comments.slice();
|
||||
|
||||
newComments.unshift(comment);
|
||||
byId[claimId] = newComments;
|
||||
|
||||
return _extends$b({}, state, {
|
||||
byId
|
||||
});
|
||||
},
|
||||
|
||||
[COMMENT_LIST_STARTED]: state => _extends$b({}, state, { isLoading: true }),
|
||||
|
||||
[COMMENT_LIST_COMPLETED]: (state, action) => {
|
||||
const { comments, claimId, uri } = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const commentsByUri = Object.assign({}, state.commentsByUri);
|
||||
|
||||
if (comments['items']) {
|
||||
byId[claimId] = comments['items'];
|
||||
commentsByUri[uri] = claimId;
|
||||
}
|
||||
return _extends$b({}, state, {
|
||||
byId,
|
||||
commentsByUri,
|
||||
isLoading: false
|
||||
});
|
||||
},
|
||||
|
||||
[COMMENT_LIST_FAILED]: (state, action) => _extends$b({}, state, {
|
||||
isLoading: false
|
||||
})
|
||||
}, defaultState$7);
|
||||
|
||||
var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
const tagsReducerBuilder = defaultState => handleActions({
|
||||
[TOGGLE_TAG_FOLLOW]: (state, action) => {
|
||||
const { followedTags } = state;
|
||||
|
@ -3739,7 +3876,7 @@ const tagsReducerBuilder = defaultState => handleActions({
|
|||
newFollowedTags.push(name);
|
||||
}
|
||||
|
||||
return _extends$b({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
followedTags: newFollowedTags
|
||||
});
|
||||
},
|
||||
|
@ -3748,10 +3885,10 @@ const tagsReducerBuilder = defaultState => handleActions({
|
|||
const { knownTags } = state;
|
||||
const { name } = action.data;
|
||||
|
||||
let newKnownTags = _extends$b({}, knownTags);
|
||||
let newKnownTags = _extends$c({}, knownTags);
|
||||
newKnownTags[name] = { name };
|
||||
|
||||
return _extends$b({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
knownTags: newKnownTags
|
||||
});
|
||||
},
|
||||
|
@ -3760,11 +3897,11 @@ const tagsReducerBuilder = defaultState => handleActions({
|
|||
const { knownTags, followedTags } = state;
|
||||
const { name } = action.data;
|
||||
|
||||
let newKnownTags = _extends$b({}, knownTags);
|
||||
let newKnownTags = _extends$c({}, knownTags);
|
||||
delete newKnownTags[name];
|
||||
const newFollowedTags = followedTags.filter(tag => tag !== name);
|
||||
|
||||
return _extends$b({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
knownTags: newKnownTags,
|
||||
followedTags: newFollowedTags
|
||||
});
|
||||
|
@ -3782,14 +3919,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta
|
|||
return state.positions[id] ? state.positions[id][outpoint] : null;
|
||||
});
|
||||
|
||||
var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
var _extends$d = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
const selectState$6 = state => state.notifications || {};
|
||||
|
||||
const selectToast = reselect.createSelector(selectState$6, state => {
|
||||
if (state.toasts.length) {
|
||||
const { id, params } = state.toasts[0];
|
||||
return _extends$c({
|
||||
return _extends$d({
|
||||
id
|
||||
}, params);
|
||||
}
|
||||
|
@ -3810,11 +3947,36 @@ const selectError = reselect.createSelector(selectState$6, state => {
|
|||
|
||||
//
|
||||
|
||||
const selectState$7 = state => state.tags || {};
|
||||
const selectState$7 = state => state.comments || {};
|
||||
|
||||
const selectKnownTagsByName = reselect.createSelector(selectState$7, state => state.knownTags);
|
||||
const selectCommentsById = reselect.createSelector(selectState$7, state => state.byId || {});
|
||||
|
||||
const selectFollowedTagsList = reselect.createSelector(selectState$7, state => state.followedTags);
|
||||
const selectCommentsByUri = reselect.createSelector(selectState$7, state => {
|
||||
const byUri = state.commentsByUri || {};
|
||||
const comments = {};
|
||||
Object.keys(byUri).forEach(uri => {
|
||||
const claimId = byUri[uri];
|
||||
if (claimId === null) {
|
||||
comments[uri] = null;
|
||||
} else {
|
||||
comments[uri] = claimId;
|
||||
}
|
||||
});
|
||||
return comments;
|
||||
});
|
||||
|
||||
const makeSelectCommentsForUri = uri => reselect.createSelector(selectCommentsById, selectCommentsByUri, (byId, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return byId && byId[claimId];
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
const selectState$8 = state => state.tags || {};
|
||||
|
||||
const selectKnownTagsByName = reselect.createSelector(selectState$8, state => state.knownTags);
|
||||
|
||||
const selectFollowedTagsList = reselect.createSelector(selectState$8, state => state.followedTags);
|
||||
|
||||
const selectFollowedTags = reselect.createSelector(selectFollowedTagsList, followedTags => followedTags.map(tag => ({ name: tag })).sort((a, b) => a.name.localeCompare(b.name)));
|
||||
|
||||
|
@ -3844,6 +4006,7 @@ exports.TRANSACTIONS = transaction_types;
|
|||
exports.batchActions = batchActions;
|
||||
exports.buildURI = buildURI;
|
||||
exports.claimsReducer = claimsReducer;
|
||||
exports.commentReducer = commentReducer;
|
||||
exports.contentReducer = contentReducer;
|
||||
exports.convertToShareLink = convertToShareLink;
|
||||
exports.creditsToString = creditsToString;
|
||||
|
@ -3853,6 +4016,8 @@ exports.doBalanceSubscribe = doBalanceSubscribe;
|
|||
exports.doBlurSearchInput = doBlurSearchInput;
|
||||
exports.doCheckAddressIsMine = doCheckAddressIsMine;
|
||||
exports.doClaimSearch = doClaimSearch;
|
||||
exports.doCommentCreate = doCommentCreate;
|
||||
exports.doCommentList = doCommentList;
|
||||
exports.doCreateChannel = doCreateChannel;
|
||||
exports.doDeletePurchasedUri = doDeletePurchasedUri;
|
||||
exports.doDeleteTag = doDeleteTag;
|
||||
|
@ -3906,6 +4071,7 @@ exports.makeSelectClaimIsNsfw = makeSelectClaimIsNsfw;
|
|||
exports.makeSelectClaimIsPending = makeSelectClaimIsPending;
|
||||
exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState;
|
||||
exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage;
|
||||
exports.makeSelectCommentsForUri = makeSelectCommentsForUri;
|
||||
exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri;
|
||||
exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri;
|
||||
exports.makeSelectCoverForUri = makeSelectCoverForUri;
|
||||
|
|
18
dist/flow-typed/Comment.js
vendored
Normal file
18
dist/flow-typed/Comment.js
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
declare type Comment = {
|
||||
author: string,
|
||||
claim_index?: number,
|
||||
comment_id?: number,
|
||||
downvotes?: number,
|
||||
message: string,
|
||||
omitted?: number,
|
||||
reply_count?: number,
|
||||
time_posted?: number,
|
||||
upvotes?: number,
|
||||
parent_id?: number,
|
||||
};
|
||||
|
||||
declare type CommentsState = {
|
||||
byId: {},
|
||||
isLoading: boolean,
|
||||
commentsByUri: { [string]: string },
|
||||
}
|
6
dist/flow-typed/Lbry.js
vendored
6
dist/flow-typed/Lbry.js
vendored
|
@ -105,6 +105,9 @@ declare type ChannelCreateResponse = GenericTxResponse & {
|
|||
outputs: Array<ChannelClaim>,
|
||||
};
|
||||
|
||||
declare type CommentCreateResponse = Comment;
|
||||
declare type CommentListResponse = Array<Comment>;
|
||||
|
||||
declare type ChannelListResponse = Array<ChannelClaim>;
|
||||
|
||||
declare type FileListResponse = Array<FileListItem>;
|
||||
|
@ -184,6 +187,9 @@ declare type LbryTypes = {
|
|||
blob_delete: (params: {}) => Promise<string>,
|
||||
blob_list: (params: {}) => Promise<BlobListResponse>,
|
||||
|
||||
// Commenting
|
||||
comment_list: (params: {}) => Promise<CommentListResponse>,
|
||||
comment_create: (params: {}) => Promise<CommentCreateResponse>,
|
||||
// Wallet utilities
|
||||
account_balance: (params: {}) => Promise<string>,
|
||||
account_decrypt: (prams: {}) => Promise<boolean>,
|
||||
|
|
18
flow-typed/Comment.js
vendored
Normal file
18
flow-typed/Comment.js
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
declare type Comment = {
|
||||
author: string,
|
||||
claim_index?: number,
|
||||
comment_id?: number,
|
||||
downvotes?: number,
|
||||
message: string,
|
||||
omitted?: number,
|
||||
reply_count?: number,
|
||||
time_posted?: number,
|
||||
upvotes?: number,
|
||||
parent_id?: number,
|
||||
};
|
||||
|
||||
declare type CommentsState = {
|
||||
byId: {},
|
||||
isLoading: boolean,
|
||||
commentsByUri: { [string]: string },
|
||||
}
|
6
flow-typed/Lbry.js
vendored
6
flow-typed/Lbry.js
vendored
|
@ -105,6 +105,9 @@ declare type ChannelCreateResponse = GenericTxResponse & {
|
|||
outputs: Array<ChannelClaim>,
|
||||
};
|
||||
|
||||
declare type CommentCreateResponse = Comment;
|
||||
declare type CommentListResponse = Array<Comment>;
|
||||
|
||||
declare type ChannelListResponse = Array<ChannelClaim>;
|
||||
|
||||
declare type FileListResponse = Array<FileListItem>;
|
||||
|
@ -184,6 +187,9 @@ declare type LbryTypes = {
|
|||
blob_delete: (params: {}) => Promise<string>,
|
||||
blob_list: (params: {}) => Promise<BlobListResponse>,
|
||||
|
||||
// Commenting
|
||||
comment_list: (params: {}) => Promise<CommentListResponse>,
|
||||
comment_create: (params: {}) => Promise<CommentCreateResponse>,
|
||||
// Wallet utilities
|
||||
account_balance: (params: {}) => Promise<string>,
|
||||
account_decrypt: (prams: {}) => Promise<boolean>,
|
||||
|
|
|
@ -92,6 +92,14 @@ export const CLAIM_SEARCH_STARTED = 'CLAIM_SEARCH_STARTED';
|
|||
export const CLAIM_SEARCH_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
|
||||
export const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED';
|
||||
|
||||
// Comments
|
||||
export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
|
||||
export const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED';
|
||||
export const COMMENT_LIST_FAILED = 'COMMENT_LIST_FAILED';
|
||||
export const COMMENT_CREATE_STARTED = 'COMMENT_CREATE_STARTED';
|
||||
export const COMMENT_CREATE_COMPLETED = 'COMMENT_CREATE_COMPLETED';
|
||||
export const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED';
|
||||
|
||||
// Files
|
||||
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
||||
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||
|
|
|
@ -90,6 +90,8 @@ export {
|
|||
|
||||
export { doToggleTagFollow, doAddTag, doDeleteTag } from 'redux/actions/tags';
|
||||
|
||||
export { doCommentList, doCommentCreate } from 'redux/actions/comments';
|
||||
|
||||
// utils
|
||||
export { batchActions } from 'util/batchActions';
|
||||
export { parseQueryParams, toQueryString } from 'util/query_params';
|
||||
|
@ -104,6 +106,7 @@ export { notificationsReducer } from 'redux/reducers/notifications';
|
|||
export { searchReducer } from 'redux/reducers/search';
|
||||
export { walletReducer } from 'redux/reducers/wallet';
|
||||
export { contentReducer } from 'redux/reducers/content';
|
||||
export { commentReducer } from 'redux/reducers/comments';
|
||||
export { tagsReducerBuilder } from 'redux/reducers/tags';
|
||||
|
||||
// selectors
|
||||
|
@ -170,6 +173,8 @@ export {
|
|||
selectLastClaimSearchUris,
|
||||
} from 'redux/selectors/claims';
|
||||
|
||||
export { makeSelectCommentsForUri } from 'redux/selectors/comments';
|
||||
|
||||
export {
|
||||
makeSelectFileInfoForUri,
|
||||
makeSelectDownloadingForUri,
|
||||
|
|
|
@ -100,6 +100,9 @@ const Lbry: LbryTypes = {
|
|||
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
|
||||
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),
|
||||
|
||||
// Comments
|
||||
comment_list: (params = {}) => daemonCallWithResult('comment_list', params),
|
||||
comment_create: (params = {}) => daemonCallWithResult('comment_create', params),
|
||||
// Connect to the sdk
|
||||
connect: () => {
|
||||
if (Lbry.connectPromise === null) {
|
||||
|
|
80
src/redux/actions/comments.js
Normal file
80
src/redux/actions/comments.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
// @flow
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbry from 'lbry';
|
||||
import { selectClaimsByUri, selectMyChannelClaims } from 'redux/selectors/claims';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
|
||||
export function doCommentList(uri: string) {
|
||||
return (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
const claim = selectClaimsByUri(state)[uri];
|
||||
const claimId = claim ? claim.claim_id : null;
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_STARTED,
|
||||
});
|
||||
Lbry.comment_list({
|
||||
claim_id: claimId,
|
||||
})
|
||||
.then((results: CommentListResponse) => {
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
||||
data: {
|
||||
comments: results,
|
||||
claimId: claimId,
|
||||
uri: uri,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_FAILED,
|
||||
data: error,
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doCommentCreate(
|
||||
comment: string = '',
|
||||
claim_id: string = '',
|
||||
channel: ?string,
|
||||
parent_id?: number
|
||||
) {
|
||||
return (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_CREATE_STARTED,
|
||||
});
|
||||
const myChannels = selectMyChannelClaims(state);
|
||||
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
|
||||
const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null;
|
||||
return Lbry.comment_create({
|
||||
comment,
|
||||
claim_id,
|
||||
channel_id,
|
||||
})
|
||||
.then((result: Comment) => {
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_CREATE_COMPLETED,
|
||||
data: {
|
||||
comment: result,
|
||||
claimId: claim_id,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_CREATE_FAILED,
|
||||
data: error,
|
||||
});
|
||||
dispatch(
|
||||
doToast({
|
||||
message: 'Oops, someone broke comments.',
|
||||
isError: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
63
src/redux/reducers/comments.js
Normal file
63
src/redux/reducers/comments.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
// @flow
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import { handleActions } from 'util/redux-utils';
|
||||
|
||||
const defaultState: CommentsState = {
|
||||
byId: {},
|
||||
commentsByUri: {},
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
export const commentReducer = handleActions(
|
||||
{
|
||||
[ACTIONS.COMMENT_CREATE_STARTED]: (state: CommentsState, action: any): CommentsState => ({
|
||||
...state,
|
||||
isLoading: true,
|
||||
}),
|
||||
|
||||
[ACTIONS.COMMENT_CREATE_FAILED]: (state: CommentsState, action: any) => ({
|
||||
...state,
|
||||
isLoading: false,
|
||||
}),
|
||||
|
||||
[ACTIONS.COMMENT_CREATE_COMPLETED]: (state: CommentsState, action: any): CommentsState => {
|
||||
const { comment, claimId }: any = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const comments = byId[claimId];
|
||||
const newComments = comments.slice();
|
||||
|
||||
newComments.unshift(comment);
|
||||
byId[claimId] = newComments;
|
||||
|
||||
return {
|
||||
...state,
|
||||
byId,
|
||||
};
|
||||
},
|
||||
|
||||
[ACTIONS.COMMENT_LIST_STARTED]: state => ({ ...state, isLoading: true }),
|
||||
|
||||
[ACTIONS.COMMENT_LIST_COMPLETED]: (state: CommentsState, action: any) => {
|
||||
const { comments, claimId, uri } = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const commentsByUri = Object.assign({}, state.commentsByUri);
|
||||
|
||||
if (comments['items']) {
|
||||
byId[claimId] = comments['items'];
|
||||
commentsByUri[uri] = claimId;
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
byId,
|
||||
commentsByUri,
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
|
||||
[ACTIONS.COMMENT_LIST_FAILED]: (state: CommentsState, action: any) => ({
|
||||
...state,
|
||||
isLoading: false,
|
||||
}),
|
||||
},
|
||||
defaultState
|
||||
);
|
36
src/redux/selectors/comments.js
Normal file
36
src/redux/selectors/comments.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
// @flow
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const selectState = state => state.comments || {};
|
||||
|
||||
export const selectCommentsById = createSelector(
|
||||
selectState,
|
||||
state => state.byId || {}
|
||||
);
|
||||
|
||||
export const selectCommentsByUri = createSelector(
|
||||
selectState,
|
||||
state => {
|
||||
const byUri = state.commentsByUri || {};
|
||||
const comments = {};
|
||||
Object.keys(byUri).forEach(uri => {
|
||||
const claimId = byUri[uri];
|
||||
if (claimId === null) {
|
||||
comments[uri] = null;
|
||||
} else {
|
||||
comments[uri] = claimId;
|
||||
}
|
||||
});
|
||||
return comments;
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectCommentsForUri = (uri: string) =>
|
||||
createSelector(
|
||||
selectCommentsById,
|
||||
selectCommentsByUri,
|
||||
(byId, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return byId && byId[claimId];
|
||||
}
|
||||
);
|
Loading…
Add table
Reference in a new issue