Get a Duration from the unit - luxon

Let's say that I know an unit and an amount of this unit. Is there a way to get a Duration object from it?
Something like Duration.fromUnitAmount(unit: DurationUnit, amount: number): Duration or DurationUnit.getDuration(amount: number): Duration, or to build a Duration object from an object such as { unit: myUnit, amount: myAmount }.
Edit
I've made a function for it, but I wanted to know if something was built-in for this. Here is the function:
static getDurationFromAmountOfUnit(unit: DurationUnit, amount: number) {
switch (unit) {
case 'years':
case 'year':
return Duration.fromObject({year: amount});
case 'quarters':
case 'quarter':
return Duration.fromObject({quarter: amount});
case 'months':
case 'month':
return Duration.fromObject({month: amount});
case 'weeks':
case 'week':
return Duration.fromObject({week: amount});
case 'days':
case 'day':
return Duration.fromObject({day: amount});
case 'hours':
case 'hour':
return Duration.fromObject({hour: amount});
case 'minutes':
case 'minute':
return Duration.fromObject({minute: amount});
case 'seconds':
case 'second':
return Duration.fromObject({second: amount});
case 'milliseconds':
case 'millisecond':
return Duration.fromObject({millisecond: amount});
}
}

Does this help:
import { Duration, DurationUnit } from 'luxon';
function getDuration(unit: DurationUnit, amount: number) {
return Duration.fromObject({
[unit]: amount,
});
}

Related

Redux - Adding/removing items from normalised state tree

I've just normalised the state of an app I'm working on (based on this article) and I'm stuck trying to add/remove items from part of my state tree based on quantity.
Part of my state tree cart is solely responsible for housing the quantity of tickets that are in the cart, organised by ID. When the user changes the quantity, an action is dispatched UPDATE_QTY which has the qty and the id.
The state starts off correct as the incoming data has the qty but I can't seem to figure out the syntax to remove the item from the cart reducer if qty is 0, also how to add it back in if the qty is 1 or more.
Could someone offer advice on the correct syntax to achieve this please?
EDIT: I'm wondering if I'm trying to do too much inside the UPDATE_QTY action and that I should have separate actions for deleting and adding items.
byId reducer
export function byId(state = initialState, action) {
switch (action.type) {
case SET_INITIAL_CART_DATA:
return Object.assign({}, state, action.tickets);
case UPDATE_QTY: // Here, I need to check if action.qty is 0 and if it is I need to remove the item but also add it back in if action.qty > 0
return {
...state,
[action.id]: { ...state[action.id], qty: action.qty }, // Updating the qty here works fine
};
default:
return state;
}
}
Simplfied state tree
const state = {
cart: {
byId: {
'40': { // How can I remove these items when qty is 0 or add back in if > 0?
qty: 0,
id: '40'
},
'90': {
qty: 0,
id: '90'
}
},
allIds: [
[
'40',
'90',
]
]
},
}
I also need the IDs to be reflected in my allIds reducer.
allIds reducer
export function allIds(state = [], action) {
switch (action.type) {
case SET_INITIAL_CART_DATA:
return [...state, ...action.allIds];
case UPDATE_QTY:
return [ONLY IDS WITH QTY]
default:
return state;
}
}
For this I'm not sure if the allIds reducer needs to be connected to the byIds reducer and take information from there. I would love to hear what best practice for something like this would be.
Why have separate reducers for byIds and allIds? I would combine these into one cart reducer and maintain the allIds state with byIds:
case SET_INITIAL_CART_DATA:
// just guessing here...
const { tickets } = action;
const allIds = tickets
.reduce((arr, ticket) => arr.concat(ticket.id), []);
return {
byIds: { ...tickets },
allIds
}
case UPDATE_QTY: {
const { byIds, allIds } = state;
const { id, qty } = action;
const idx = allIds.indexOf(id);
const next = { };
if (qty > 0) {
next.byIds = {
...byIds,
[id]: { id, qty }
};
next.allIds = idx === -1 ? allIds.concat(id) : [ ...allIds ];
return next;
}
next.byIds = { ...byIds };
delete next.byIds[id];
next.allIds = idx === -1 ? [ ...allIds ] : [
...allIds.slice(0, idx),
...allIds.slice(idx + 1)
];
return next;
}
However, what state do you want normalized? If this represents a shopping cart of tickets, the tickets are what would be normalized, and the cart would just represent the quantity of tickets to be purchased. Then your state would look something like this:
{
tickets: {
byIds: {
'1': { id, name, price, ... },
'2': { ... },
'3': { ... },
...
}
allIds: [ '1', '2', '3', ... ]
},
cart: [
{ id: 2, qty: 2 },
{ id: 1, qty: 1 }
]
}
The use of an array for the cart state maintains insertion order.
Sometimes (when you only iterate through ids and get by id) it's enough to remove id from allIds and skip all unnecessary computations.
case actionTypes.DELETE_ITEM: {
const filteredIds = state.allIds.filter(id => id !== action.itemId);
return {
...state,
allIds: filteredIds
};
}

Protractor browser wait for boolean Condition

I'm trying to create a wait condition that will execute a script and based on the return value will will determined if it need to wait or not.
I'm using protractors executeScript functionality and browser wait:
this.activeConnections = function(jsl) {
console.log("Inside Active Connections");
switch (jsl) {
case checkEnum.jQuery:
console.log("Jquery Enum");
return browser.executeScript("return jQuery.active;").then(function(count) {
console.log("The count is "+count);
return count == 0;
});
default:
browser.logger.info("No asynchronous check performed.");
break;
}
};
I was expecting the wait condition to wait until the Executed script would evaluate to true but that is not working
this.waitForActiveConnections = function () {
console.log("Inside Wait for Active Connections");
var condition = until.and(this.activeConnections(checkEnum.jQuery),false);
console.log("Whats this condition "+ condition);
return browser.wait(condition,30000);
};
The main issue is that your custom Expected Condition needs to return an executable - a function that browser.wait() is going to execute continuously. Something like:
this.activeConnections = function(jsl) {
return function () {
switch (jsl) {
case checkEnum.jQuery:
return browser.executeScript("return jQuery.active;").then(function(count) {
return count == 0;
});
default:
browser.logger.info("No asynchronous check performed.");
return true;
break;
}
}
}

Using Disjoint Sets in a Switch Case

I'm trying to figure out why getLabelForType works but getOtherLableForType fails typing:
export const things = {
THING1: 'THING1',
THING2: 'THING2',
}
export type Thing = $Keys<typeof things>
type Empty = 'empty type' & 'nothing there'
export default function unexpectedCase(impossible: Empty): void {
throw new Error(`Unexpected case ${impossible}`)
}
export function getLabelForType(thing: Thing): string {
switch (thing) {
case 'THING1':
return 'Thing 1'
case 'THING2':
return 'Thing 2'
default:
unexpectedCase(thing)
return ''
}
}
export function getOtherLabelForType(thing: Thing): string {
(things.THING1: Thing)
switch (thing) {
case things.THING1:
return 'Thing 1'
case things.THING1:
return 'Thing 2'
default:
unexpectedCase(thing)
return ''
}
}
See the tryflow working example

how to remove object from array in redux

this is my code can un help with it how to write slice function properly
export default function(state={inputs:[ ]}, action) {
console.log(action.index);
switch (action.type) {
case APPEND_INPUT:
return { ...state, inputs: state.inputs.concat({value:"",key:"1",type:'input'})};
case APPEND_TEXTAREA:
return { ...state, inputs: state.inputs.concat({value:"",key:"",type:'textarea'})};
case APPEND_EMAIL:
return { ...state, inputs: state.inputs.concat({value:"",key:"",type:'email'})};
case REMOVE_INPUT:
return {inputs: state.inputs.slice(0)};
default:
return state;
}
}
Or:
{inputs: state.inputs.filter((_, i) => i !== action.index))
Slice the array up to the index, and concat it to the slice from the index + 1 onwards:
{
inputs: state.inputs.slice(0, action.index).concat(state.inputs.slice(action.index + 1))
}
If you use ES6 you can do this instead of concat:
{
inputs: [...state.inputs.slice(0, action.index), ...state.inputs.slice(action.index + 1)]
}

Using bracket notation on redux reducer

I have a form that should update my store for every change done in the store. To not have to make 20-30 different actions for each property/field, i though creating one single action containing property-name and value would be a good approach. So the action looks like this:
export function(property, value){
return{
type: UPDATE_MODEL,
property: property,
value: value
}
}
When passing that into my reducer, i tried using the bracket notation.
case UPDATE_MODEL: {
return Object.assign({}, state, {[action.property]: action.value});
}
When doing this:
dispatch(myAction("Type", {Id: 1}));
My reducer will set the Type property to an array instead of just setting the property Type to the incoming object. Is there a way to rig this properly?
I tried to use _cloneDeep from lodash on the current state object i wanted to change, then used the bracket notation on that, and then returning object.assign with that new object, that actually works, it just feels very wrong though.
How about this?
function updateModel(state, action) {
return Object.assign({}, state, {
[action.property]: action.value
})
}
function updateModelAction(property, value) {
return {
type: 'UPDATE_MODEL',
property,
value
}
}
function reducer(state, action) {
switch (action.type) {
case 'UPDATE_MODEL':
return updateModel(state, action)
default:
return state
}
}
console.log(reducer({}, updateModelAction('foo', { bar: 'baz' })))

Resources