@aappddeevv/dynamics-client-ui
Version:
## What is it? A library to help you create great dynamics applications.
143 lines • 5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/** Redux action management utilities. */
const effects_1 = require("redux-saga/effects");
/**
* Create an action creator. Returns a function that creates an action message
* with "type" type and argNames as properties on that message corresponding
* to the arguments of the function call. The actual properties are computed
* at runtime and hence, we cannot statically make a perfect return type.
*/
function makeActionCreator(type, ...argNames) {
return (...args) => {
// tslint:disable-next-line:no-object-literal-type-assertion
const action = { type };
argNames.forEach((arg, index) => {
action[arg] = args[index]; // was action[argNames[index]] = args[index]
});
return action;
};
}
exports.makeActionCreator = makeActionCreator;
/** Default set of prefixes and arg names for createMultiSelect() */
const multiPrefixes = [
{ key: "SET_REFDATA", args: ["data"] },
{ key: "SET", args: ["data"] },
{ key: "ADD", args: ["data"] },
{ key: "REMOVE", args: ["data"] },
{ key: "CLEAR", args: [] },
{ key: "SET_ALL", args: [] },
];
// the above in object form, much easier to work with...
const multiPrefixes2 = {
SET_REFDATA: ["data"],
SET: ["data"],
ADD: ["data"],
REMOVE: ["data"],
CLEAR: [],
SET_ALL: [],
};
/**
* Return an object with well-known keys that have action creators as values.
* The returned object has properties from "key" but the
* actual message type is under the property ACTION on the creator function and is
* made up of the id and key together.
*
* TODO: Convert to object syntax for input, not goofy array.
*/
function createActionMap(id, prefixes) {
// tslint:disable-next-line:no-object-literal-type-assertion
const rval = {};
prefixes.forEach(p => {
const key = p.key;
const str = id + "." + key;
// first arg must be "type", the rest are more data properties, if present
const func = makeActionCreator.apply(null, [str].concat(p.args || []));
func.ACTION = str;
rval[key] = func;
});
return rval;
}
exports.createActionMap = createActionMap;
/**
* Create string ids and action creators i.e. Record<string, ActionCreator>
*
* ```
* const choices = createMultiSelect("somechoices") // returns an object
* ```
* Dispatching:
* ```
* dispatch(choices.SET_REFDATA(actionData))
* ```
* Reducing:
* ```
* function reducer(state, action) { ...
* case choices.SET_ALL.ACTION:
* const data = action.data
* ...
* }
* ```
*/
function createMultiSelect(id) {
return createActionMap(id, multiPrefixes);
}
exports.createMultiSelect = createMultiSelect;
const singlePrefixes = [
{ key: "SET_REFDATA", args: ["data"] },
{ key: "SET", args: ["data"] },
{ key: "CLEAR", args: [] },
];
/**
* Create a single select set of actions.
* This is just a subset of those in a multi select, SET_REFDATA, SET and CLEAR.
*/
function createSingleSelect(id) {
return createActionMap(id, singlePrefixes);
}
exports.createSingleSelect = createSingleSelect;
/**
* Create action and type for changing something. Args will be a subaction.
* Name on object will be "change.prefix" by default.
*
* @deprecated Use mkWrapper
*/
exports.mkChange = (prefix, aname = "change") => {
const actionName = `${aname}.${prefix}`;
const func = makeActionCreator.apply(null, [actionName, "subaction"]);
func.ACTION = actionName;
return func;
};
/**
* Create action and type for changing something. Args will be a subaction.
* Name on object will be "wrapper.prefix".
*/
exports.mkWrapper = (prefix) => exports.mkChange(prefix, "wrapper");
/**
* Make a function from a "filterName" to create a saga
* action channel on and a handler to call with the most
* recent state. The subaction is dispatched before calling
* the handler. You this to track the a message which wraps another
* message and that needs to be detected in the saga middleware.
* filterName should be called channelName. You still need to call
* the returned function.
*
* @param {string} filterName Name of channel message type.
* @param {Function} handler (action,state) => generator
* @param {boolean} dispatchSubActon Dispatch subaction before calling the handler.
* @return generator
*/
function mkSubactionSaga(filterName, handler, dispatchSubaction = true) {
return function* () {
const channel = yield effects_1.actionChannel(filterName);
while (true) {
const action = yield effects_1.take(channel);
if (dispatchSubaction && action.subaction)
yield effects_1.put.resolve(action.subaction);
const state = yield effects_1.select();
if (handler)
yield effects_1.call(() => handler(action, state));
}
};
}
exports.mkSubactionSaga = mkSubactionSaga;
//# sourceMappingURL=actionutils.js.map