import { error, warning } from "../logger"; import * as _ from "lodash"; import { BotState, DeviceAccountSettings, HardwareState } from "./interfaces"; import { generateReducer } from "../generate_reducer"; import { isBotLog } from "./is_bot_log"; import { ReduxAction } from "../interfaces"; import * as i18next from "i18next"; let status = { NOT_READY: i18next.t("never connected to device"), CONNECTING: i18next.t("initiating connection"), AWAITING_API: i18next.t("downloading device credentials"), API_ERROR: i18next.t("Unable to download device credentials"), AWAITING_WEBSOCKET: i18next.t("calling FarmBot with credentials"), WEBSOCKET_ERR: i18next.t("Error establishing socket connection"), CONNECTED: i18next.t("Socket Connection Established"), READY: i18next.t("Bot ready") }; let initialState: BotState = { account: { id: 0, uuid: "loading...", name: "loading..." }, logQueueSize: 10, logQueue: [], status: status.NOT_READY, stepSize: 1000, hardware: {}, axisBuffer: {}, settingsBuffer: {} }; function READ_STATUS_OK(state: BotState, action: ReduxAction) { let hardware = action.payload; delete hardware.method; return _.assign<{}, BotState>({}, state, { hardware: hardware }, { status: status.READY }); }; export let botReducer = generateReducer(initialState) .add("SETTING_TOGGLE_OK", function(state, action) { return READ_STATUS_OK(state, action); }) .add("COMMIT_SETTINGS_OK", function(state, action) { let nextState = _.assign({}, state, { settingsBuffer: {} }); return nextState; }) .add("COMMIT_AXIS_CHANGE_OK", function(oldState, action) { let hardware = _.assign({}, oldState.hardware, action.payload); let state = _.assign({}, oldState); return _.assign({}, state, { axisBuffer: {}, hardware }); }) .add("CHANGE_AXIS_BUFFER", function(state, action) { // let axisBuffer: any = _.assign({}, state.axisBuffer); state.axisBuffer[action.payload.key] = action.payload.val; return _.assign({}, state, { axisBuffer: state.axisBuffer }); }) .add("CHANGE_SETTINGS_BUFFER", function(state, action) { let newVal = Number(action.payload.val); if (newVal) { state.settingsBuffer[action.payload.key] = action.payload.val; } else { delete state.settingsBuffer[action.payload.key]; } return _.assign({}, state, { settingsBuffer: state.settingsBuffer }); }) .add("CHANGE_STEP_SIZE", function(state, action) { return _.assign({}, state, { stepSize: action.payload }); }) .add("READ_STATUS_OK", READ_STATUS_OK) .add("BOT_CHANGE", function(state, action) { let statuses: any = _.assign({}, action.payload); let newState: any = _.assign({}, state); newState.hardware = _.assign({}, state.hardware, statuses); return _.assign({}, newState); }) .add("CONNECT_OK", function(state, action) { return _.assign({}, state, action.payload, { status: status.CONNECTED, connected: true }); }) .add("CONNECT_ERR", function(state, action) { return _.assign({}, state, { status: status.WEBSOCKET_ERR }); }) .add("CHANGE_DEVICE", function(s, a) { _.assign(s.account, a.payload, {dirty: true}); return s; }) .add("FETCH_DEVICE", function(state, action) { return state; }) .add("FETCH_DEVICE_OK", function(state, { payload }) { return _.assign({}, state, payload, { status: status.AWAITING_WEBSOCKET }); }) .add("FETCH_DEVICE_ERR", function(state, action) { // TODO: Toast messages do not belong in a reducer. if (action.payload.status === 404) { warning(i18next.t("You need to add a device to your account."), i18next.t("No device found!")); } else { error(i18next.t("Unable to download device data from server."), i18next.t("Check your internet connection.")); }; return _.assign({}, state, { status: status.API_ERROR }); }) .add("SAVE_DEVICE_ERR", function(state, action) { switch (action.payload.status) { case 422: let errors = _.map(action.payload.responseJSON, v => v) .join(". "); error(errors, i18next.t("Couldn\'t save device.")); break; default: error(i18next.t("Error while saving device.")); break; } return state; }) .add("SAVE_DEVICE_OK", function(state, action) { return _.assign({}, state, action.payload, { dirty: false }); }) .add("BOT_NOTIFICATION", function(state, { payload }) { if (isBotLog(payload)) { state.logQueue.unshift(payload); state.logQueue = _.take(state.logQueue, state.logQueueSize); } else { console.warn(i18next.t("Unexpected log message?")); } return state; }) .add("REPLACE_DEVICE_ACCOUNT_INFO", function(s, a) { s.account = a.payload; return s; }) .add("CHANGE_WEBCAM_URL", function(s, a) { s.account.dirty = true; s.account.webcam_url = a.payload; return s; });