The code powering m.abunchtell.com https://m.abunchtell.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

103 lines
3.6 KiB

  1. import {
  2. ANNOUNCEMENTS_FETCH_REQUEST,
  3. ANNOUNCEMENTS_FETCH_SUCCESS,
  4. ANNOUNCEMENTS_FETCH_FAIL,
  5. ANNOUNCEMENTS_UPDATE,
  6. ANNOUNCEMENTS_REACTION_UPDATE,
  7. ANNOUNCEMENTS_REACTION_ADD_REQUEST,
  8. ANNOUNCEMENTS_REACTION_ADD_FAIL,
  9. ANNOUNCEMENTS_REACTION_REMOVE_REQUEST,
  10. ANNOUNCEMENTS_REACTION_REMOVE_FAIL,
  11. ANNOUNCEMENTS_TOGGLE_SHOW,
  12. ANNOUNCEMENTS_DELETE,
  13. ANNOUNCEMENTS_DISMISS_SUCCESS,
  14. } from '../actions/announcements';
  15. import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
  16. const initialState = ImmutableMap({
  17. items: ImmutableList(),
  18. isLoading: false,
  19. show: false,
  20. });
  21. const updateReaction = (state, id, name, updater) => state.update('items', list => list.map(announcement => {
  22. if (announcement.get('id') === id) {
  23. return announcement.update('reactions', reactions => {
  24. const idx = reactions.findIndex(reaction => reaction.get('name') === name);
  25. if (idx > -1) {
  26. return reactions.update(idx, reaction => updater(reaction));
  27. }
  28. return reactions.push(updater(fromJS({ name, count: 0 })));
  29. });
  30. }
  31. return announcement;
  32. }));
  33. const updateReactionCount = (state, reaction) => updateReaction(state, reaction.announcement_id, reaction.name, x => x.set('count', reaction.count));
  34. const addReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', true).update('count', y => y + 1));
  35. const removeReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', false).update('count', y => y - 1));
  36. const sortAnnouncements = list => list.sortBy(x => x.get('starts_at') || x.get('published_at'));
  37. const updateAnnouncement = (state, announcement) => {
  38. const idx = state.get('items').findIndex(x => x.get('id') === announcement.get('id'));
  39. if (idx > -1) {
  40. // Deep merge is used because announcements from the streaming API do not contain
  41. // personalized data about which reactions have been selected by the given user,
  42. // and that is information we want to preserve
  43. return state.update('items', list => sortAnnouncements(list.update(idx, x => x.mergeDeep(announcement))));
  44. }
  45. return state.update('items', list => sortAnnouncements(list.unshift(announcement)));
  46. };
  47. export default function announcementsReducer(state = initialState, action) {
  48. switch(action.type) {
  49. case ANNOUNCEMENTS_TOGGLE_SHOW:
  50. return state.withMutations(map => {
  51. map.set('show', !map.get('show'));
  52. });
  53. case ANNOUNCEMENTS_FETCH_REQUEST:
  54. return state.set('isLoading', true);
  55. case ANNOUNCEMENTS_FETCH_SUCCESS:
  56. return state.withMutations(map => {
  57. const items = fromJS(action.announcements);
  58. map.set('items', items);
  59. map.set('isLoading', false);
  60. });
  61. case ANNOUNCEMENTS_FETCH_FAIL:
  62. return state.set('isLoading', false);
  63. case ANNOUNCEMENTS_UPDATE:
  64. return updateAnnouncement(state, fromJS(action.announcement));
  65. case ANNOUNCEMENTS_REACTION_UPDATE:
  66. return updateReactionCount(state, action.reaction);
  67. case ANNOUNCEMENTS_REACTION_ADD_REQUEST:
  68. case ANNOUNCEMENTS_REACTION_REMOVE_FAIL:
  69. return addReaction(state, action.id, action.name);
  70. case ANNOUNCEMENTS_REACTION_REMOVE_REQUEST:
  71. case ANNOUNCEMENTS_REACTION_ADD_FAIL:
  72. return removeReaction(state, action.id, action.name);
  73. case ANNOUNCEMENTS_DISMISS_SUCCESS:
  74. return updateAnnouncement(state, fromJS({ 'id': action.id, 'read': true }));
  75. case ANNOUNCEMENTS_DELETE:
  76. return state.update('items', list => {
  77. const idx = list.findIndex(x => x.get('id') === action.id);
  78. if (idx > -1) {
  79. return list.delete(idx);
  80. }
  81. return list;
  82. });
  83. default:
  84. return state;
  85. }
  86. };