From b02d66491c210d8be36ed670fc83c1f2032b7297 Mon Sep 17 00:00:00 2001
From: Maximilian Hils <git@maximilianhils.com>
Date: Sat, 4 Jun 2016 00:37:10 -0700
Subject: web: implement update and remove for list and view

---
 web/src/js/ducks/eventLog.js   |  8 ++++--
 web/src/js/ducks/utils/list.js | 62 ++++++++++++++++++++++++++++++++++++------
 web/src/js/ducks/utils/view.js | 45 ++++++++++++++++++++++++------
 3 files changed, 95 insertions(+), 20 deletions(-)

(limited to 'web/src')

diff --git a/web/src/js/ducks/eventLog.js b/web/src/js/ducks/eventLog.js
index 00b25bcf..e3661fe7 100644
--- a/web/src/js/ducks/eventLog.js
+++ b/web/src/js/ducks/eventLog.js
@@ -7,9 +7,9 @@ export const UPDATE_LOG = "UPDATE_EVENTLOG"
 
 const {
     reduceList,
-    addToList,
     updateList,
     fetchList,
+    addItem,
 } = makeList(UPDATE_LOG, "/events")
 
 
@@ -51,7 +51,9 @@ export default function reducer(state = defaultState, action) {
                 events,
                 filteredEvents: updateViewList(
                     state.filteredEvents,
-                    events, action,
+                    state.events,
+                    events,
+                    action,
                     x => state.filter[x.level]
                 )
             }
@@ -69,7 +71,7 @@ export function toggleEventLogVisibility() {
 }
 let id = 0
 export function addLogEntry(message, level = "web") {
-    return addToList({
+    return addItem({
         message,
         level,
         id: `log-${id++}`
diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js
index b750982e..e5ce75ef 100644
--- a/web/src/js/ducks/utils/list.js
+++ b/web/src/js/ducks/utils/list.js
@@ -1,6 +1,8 @@
-import {fetchApi} from "../../utils";
+import {fetchApi} from "../../utils"
 
 export const ADD = "ADD"
+export const UPDATE = "UPDATE"
+export const REMOVE = "REMOVE"
 export const REQUEST_LIST = "REQUEST_LIST"
 export const RECEIVE_LIST = "RECEIVE_LIST"
 
@@ -11,7 +13,7 @@ const defaultState = {
     actionsDuringFetch: [],
     byId: {},
     indexOf: {},
-};
+}
 
 export default function makeList(actionType, fetchURL) {
     function reduceList(state = defaultState, action = {}) {
@@ -45,6 +47,7 @@ export default function makeList(actionType, fetchURL) {
             }
         }
 
+        let list, itemIndex
         switch (action.cmd) {
             case ADD:
                 return {
@@ -53,6 +56,27 @@ export default function makeList(actionType, fetchURL) {
                     indexOf: {...state.indexOf, [action.item.id]: state.list.length},
                 }
 
+            case UPDATE:
+
+                list = [...state.list]
+                itemIndex = state.indexOf[action.item.id]
+                list[itemIndex] = action.item
+                return {
+                    ...defaultState,
+                    list
+                }
+
+            case REMOVE:
+                list = [...state.list]
+                itemIndex = state.indexOf[action.item.id]
+                list.splice(itemIndex, 1)
+                return {
+                    ...defaultState,
+                    list,
+                    byId: {...state.byId, [action.item.id]: undefined},
+                    indexOf: {...state.indexOf, [action.item.id]: undefined},
+                }
+
             case REQUEST_LIST:
                 return {
                     ...defaultState,
@@ -60,12 +84,12 @@ export default function makeList(actionType, fetchURL) {
                 }
 
             default:
-                console.debug("unknown action", action.type)
+                console.debug("unknown action", action)
                 return state
         }
     }
 
-    function addToList(item) {
+    function addItem(item) {
         return {
             type: actionType,
             cmd: ADD,
@@ -73,17 +97,37 @@ export default function makeList(actionType, fetchURL) {
         }
     }
 
+    function updateItem(item) {
+        return {
+            type: actionType,
+            cmd: UPDATE,
+            item
+        }
+    }
+
+    function removeItem(item) {
+        return {
+            type: actionType,
+            cmd: REMOVE,
+            item
+        }
+    }
+
 
-    function updateList(action) {
+    function updateList(event) {
         /* This action creater takes all WebSocket events */
         return dispatch => {
-            switch (action.cmd) {
+            switch (event.cmd) {
                 case "add":
-                    return dispatch(addToList(action.data))
+                    return dispatch(addItem(event.data))
+                case "update":
+                    return dispatch(updateItem(event.data))
+                case "remove":
+                    return dispatch(removeItem(event.data))
                 case "reset":
                     return dispatch(fetchList())
                 default:
-                    console.error("unknown list update", action)
+                    console.error("unknown list update", event)
             }
         }
     }
@@ -117,5 +161,5 @@ export default function makeList(actionType, fetchURL) {
     }
 
 
-    return {reduceList, addToList, updateList, fetchList}
+    return {reduceList, updateList, fetchList, addItem, updateItem, removeItem,}
 }
\ No newline at end of file
diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js
index 4b265f89..55fdf6c7 100644
--- a/web/src/js/ducks/utils/view.js
+++ b/web/src/js/ducks/utils/view.js
@@ -1,4 +1,4 @@
-import {ADD, REQUEST_LIST, RECEIVE_LIST} from "./list"
+import {ADD, UPDATE, REMOVE, REQUEST_LIST, RECEIVE_LIST} from "./list"
 
 const defaultFilterFn = x => true
 const defaultSortFn = false
@@ -6,13 +6,13 @@ const defaultSortFn = false
 const makeCompareFn = sortFn => {
     let compareFn = (a, b) => {
         let akey = sortFn(a),
-            bkey = sortFn(b);
+            bkey = sortFn(b)
         if (akey < bkey) {
-            return -1;
+            return -1
         } else if (akey > bkey) {
-            return 1;
+            return 1
         } else {
-            return 0;
+            return 0
         }
     }
     if (sortFn.reverse)
@@ -33,19 +33,48 @@ const sortedInsert = (list, sortFn, item) => {
     return l
 }
 
+const sortedRemove = (list, sortFn, item) => {
+    let itemId = item.id
+    return list.filter(x => x.id !== itemId)
+}
+
 // for when the list changes
-export function updateViewList(state, nextList, action, filterFn = defaultFilterFn, sortFn = defaultSortFn) {
+export function updateViewList(state, currentList, nextList, action, filterFn = defaultFilterFn, sortFn = defaultSortFn) {
     switch (action.cmd) {
         case REQUEST_LIST:
             return state
         case RECEIVE_LIST:
             return updateViewFilter(nextList.list, filterFn, sortFn)
         case ADD:
-            if (filterFn(action.item))
+            if (filterFn(action.item)) {
+                return sortedInsert(state, sortFn, action.item)
+            }
+            return state
+        case UPDATE:
+            // let's determine if it's in the view currently and if it should be in the view.
+            let currentItemState = currentList.byId[action.item.id],
+                nextItemState = action.item,
+                isInView = filterFn(currentItemState),
+                shouldBeInView = filterFn(nextItemState)
+
+            if (!isInView && shouldBeInView)
                 return sortedInsert(state, sortFn, action.item)
+            if (isInView && !shouldBeInView)
+                return sortedRemove(state, sortFn, action.item)
+            if (isInView && shouldBeInView && sortFn(currentItemState) !== sortFn(nextItemState)) {
+                let s = [...state]
+                s.sort(sortFn)
+                return s
+            }
+            return state
+        case REMOVE:
+            let isInView_ = filterFn(currentList.byId[action.item.id])
+            if (isInView_) {
+                return sortedRemove(state, sortFn, action.item)
+            }
             return state
         default:
-            console.error("Unknown list action: ", action);
+            console.error("Unknown list action: ", action)
             return state
     }
 }
-- 
cgit v1.2.3