diff options
Diffstat (limited to 'web/src/js/ducks/flows.js')
-rw-r--r-- | web/src/js/ducks/flows.js | 282 |
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 } +} |