aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/ducks/flows.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/js/ducks/flows.js')
-rw-r--r--web/src/js/ducks/flows.js282
1 files changed, 209 insertions, 73 deletions
diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js
index b877d3e4..aad82de2 100644
--- a/web/src/js/ducks/flows.js
+++ b/web/src/js/ducks/flows.js
@@ -1,114 +1,250 @@
-import makeList from "./utils/list"
-import Filt from "../filt/filt"
-import {updateViewFilter, updateViewList, updateViewSort} from "./utils/view"
-import {reverseString} from "../utils.js";
-import * as columns from "../components/FlowTable/FlowColumns";
+import { fetchApi as fetch } from '../utils'
+import { CMD_RESET as WS_CMD_RESET } from './websocket'
+import reduceList, * as listActions from './utils/list'
-export const UPDATE_FLOWS = "UPDATE_FLOWS"
-export const SET_FILTER = "SET_FLOW_FILTER"
-export const SET_HIGHLIGHT = "SET_FLOW_HIGHLIGHT"
-export const SET_SORT = "SET_FLOW_SORT"
-export const SELECT_FLOW = "SELECT_FLOW"
-
-const {
- reduceList,
- updateList,
- fetchList,
-} = makeList(UPDATE_FLOWS, "/flows")
+export const WS_MSG_TYPE ='UPDATE_FLOWS'
+export const UPDATE_FILTER = 'FLOWS_UPDATE_FLOW_FILTER'
+export const UPDATE_HIGHLIGHT = 'FLOWS_UPDATE_FLOW_HIGHLIGHT'
+export const UPDATE_SORT = 'FLOWS_UPDATE_FLOW_SORT'
+export const WS_MSG = 'FLOWS_WS_MSG'
+export const SELECT_FLOW = 'FLOWS_SELECT_FLOW'
+export const REQUEST_ACTION = 'FLOWS_REQUEST_ACTION'
+export const REQUEST = 'FLOWS_REQUEST'
+export const RECEIVE = 'FLOWS_RECEIVE'
+export const FETCH_ERROR = 'FLOWS_FETCH_ERROR'
const defaultState = {
- all: reduceList(),
selected: [],
- view: [],
- filter: undefined,
- highlight: undefined,
- sort: {sortColumn: undefined, sortDesc: false},
-}
-
-function makeFilterFn(filter) {
- return filter ? Filt.parse(filter) : () => true;
+ sorter: {},
+ filter: null,
+ highlight: null,
+ list: reduceList(undefined, { type: Symbol('FLOWS_INIT_LIST') }),
}
+export default function reduce(state = defaultState, action) {
+ switch (action.type) {
-function makeSortFn(sort){
- let column = columns[sort.sortColumn];
- if (!column) return;
+ case UPDATE_FILTER:
+ return {
+ ...state,
+ filter: action.filter,
+ list: reduceList(state.list, listActions.updateFilter(makeFilterFun(action.filter))),
+ }
- let sortKeyFun = column.sortKeyFun;
- if (sort.sortDesc) {
- sortKeyFun = sortKeyFun && function (flow) {
- const k = column.sortKeyFun(flow);
- return _.isString(k) ? reverseString("" + k) : -k;
- };
- }
- return sortKeyFun;
-}
+ case UPDATE_HIGHLIGHT:
+ return {
+ ...state,
+ highlight: action.highlight,
+ }
-export default function reducer(state = defaultState, action) {
- switch (action.type) {
- case UPDATE_FLOWS:
- let all = reduceList(state.all, action)
+ case UPDATE_SORTER:
return {
...state,
- all,
- view: updateViewList(state.view, state.all, all, action, makeFilterFn(action.filter), makeSortFn(state.sort))
+ sorter: { column: action.column, desc: action.desc },
+ list: reduceList(state.list, listActions.updateSorter(makeSortFun(action.sortKeyFun, action.desc))),
}
- case SET_FILTER:
+
+ case SELECT_FLOW:
return {
...state,
- filter: action.filter,
- view: updateViewFilter(state.all, makeFilterFn(action.filter), makeSortFn(state.sort))
+ selected: [action.id],
}
- case SET_HIGHLIGHT:
+
+ case WS_MSG:
return {
...state,
- highlight: action.highlight
+ list: reduceList(state.list, listActions.handleWsMsg(action.msg)),
}
- case SET_SORT:
+
+ case REQUEST:
return {
...state,
- sort: action.sort,
- view: updateViewSort(state.view, makeSortFn(action.sort))
+ list: reduceList(state.list, listActions.request())
}
- case SELECT_FLOW:
+
+ case RECEIVE:
return {
...state,
- selected: [action.flowId]
+ list: reduceList(state.list, listActions.receive(action.list))
}
+
default:
return state
}
}
+function makeFilterFun(filter) {
+ return filter ? Filt.parse(filter) : () => true
+}
-export function setFilter(filter) {
- return {
- type: SET_FILTER,
- filter
+function makeSortFun(sortKeyFun, desc) {
+ return (a, b) => {
+ const ka = sortKeyFun(a)
+ const kb = sortKeyFun(b)
+ if (ka > kb) {
+ return desc ? -1 : 1
+ }
+ if (ka < kb) {
+ return desc ? 1 : -1
+ }
+ return 0
}
}
-export function setHighlight(highlight) {
- return {
- type: SET_HIGHLIGHT,
- highlight
+
+/**
+ * @public
+ */
+export function updateFilter(filter) {
+ return { type: UPDATE_FILTER, filter }
+}
+
+/**
+ * @public
+ */
+export function updateHighlight(highlight) {
+ return { type: UPDATE_HIGHLIGHT, highlight }
+}
+
+/**
+ * @public
+ */
+export function updateSorter(column, desc, sortKeyFun) {
+ return { type: UPDATE_SORTER, column, desc, sortKeyFun }
+}
+
+/**
+ * @public
+ */
+export function selectFlow(id) {
+ return (dispatch, getState) => {
+ dispatch({ type: SELECT_FLOW, currentSelection: getState().flows.selected[0], id })
}
}
-export function setSort(sort){
- return {
- type: SET_SORT,
- sort
+
+/**
+ * @public websocket
+ */
+export function handleWsMsg(msg) {
+ if (msg.cmd === WS_CMD_RESET) {
+ return fetchData()
}
+ return { type: WS_MSG, msg }
}
-export function selectFlow(flowId) {
- return (dispatch, getState) => {
- dispatch({
- type: SELECT_FLOW,
- currentSelection: getState().flows.selected[0],
- flowId
- })
+
+/**
+ * @public websocket
+ */
+export function fetchData() {
+ return dispatch => {
+ dispatch(request())
+
+ return fetch('/flows')
+ .then(res => res.json())
+ .then(json => dispatch(receive(json.data)))
+ .catch(error => dispatch(fetchError(error)))
}
}
+/**
+ * @public
+ */
+export function accept(flow) {
+ fetch(`/flows/${flow.id}/accept`, { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function acceptAll() {
+ fetch('/flows/accept', { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
-export {updateList as updateFlows, fetchList as fetchFlows}
+/**
+ * @public
+ */
+export function delete(flow) {
+ fetch(`/flows/${flow.id}`, { method: 'DELETE' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function duplicate(flow) {
+ fetch(`/flows/${flow.id}/duplicate`, { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function replay(flow) {
+ fetch(`/flows/${flow.id}/replay`, { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function revert(flow) {
+ fetch(`/flows/${flow.id}/revert`, { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function update(flow, body) {
+ fetch(`/flows/${flow.id}`, { method: 'PUT', body })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function clear() {
+ fetch('/clear', { method: 'POST' })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function download() {
+ window.location = '/flows/dump'
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @public
+ */
+export function upload(file) {
+ const body = new FormData()
+ body.append('file', file)
+ fetch('/flows/dump', { method: 'post', body })
+ return { type: REQUEST_ACTION }
+}
+
+/**
+ * @private
+ */
+export function request() {
+ return { type: REQUEST }
+}
+
+/**
+ * @private
+ */
+export function receive(list) {
+ return { type: RECEIVE, list }
+}
+
+/**
+ * @private
+ */
+export function fetchError(error) {
+ return { type: FETCH_ERROR, error }
+}