132 lines
2.7 KiB
JavaScript
132 lines
2.7 KiB
JavaScript
|
import shortid from 'shortid';
|
||
|
|
||
|
import check from '../check';
|
||
|
import root from '../root';
|
||
|
|
||
|
export const messageTypes = {
|
||
|
STATUS: 0,
|
||
|
INFO: 1,
|
||
|
WARNING: 2,
|
||
|
ERROR: 3,
|
||
|
QUESTION: 4,
|
||
|
};
|
||
|
|
||
|
export function getTypeName(type) {
|
||
|
const matchingTypeItem = Object.entries(messageTypes)
|
||
|
.find(item => item[1] === type);
|
||
|
if (!matchingTypeItem) {
|
||
|
return undefined;
|
||
|
}
|
||
|
return matchingTypeItem[0];
|
||
|
}
|
||
|
|
||
|
export const initialState = {
|
||
|
messages: [],
|
||
|
};
|
||
|
|
||
|
const myRedux = root.sub('ui').all({
|
||
|
initialState,
|
||
|
|
||
|
actions: {
|
||
|
add: {
|
||
|
params: {
|
||
|
id: v => v === undefined || check.string(v),
|
||
|
text: v => check.string(v),
|
||
|
type: v => v in Object.values(messageTypes),
|
||
|
buttons: v => v === undefined || check.array(v),
|
||
|
},
|
||
|
reducer: (state, {
|
||
|
id,
|
||
|
buttons,
|
||
|
...payload
|
||
|
}) => {
|
||
|
let finalId = id;
|
||
|
|
||
|
// generate new unique id if none given
|
||
|
if (finalId === undefined) {
|
||
|
const hasMatchingId = m => m.id === finalId;
|
||
|
do {
|
||
|
finalId = shortid.generate();
|
||
|
} while (state.messages.find(hasMatchingId));
|
||
|
}
|
||
|
|
||
|
// no buttons => default to "OK" button
|
||
|
let finalButtons = buttons;
|
||
|
if (!finalButtons) {
|
||
|
finalButtons = [
|
||
|
{
|
||
|
text: 'OK', // TODO - localization
|
||
|
close: true,
|
||
|
},
|
||
|
];
|
||
|
}
|
||
|
|
||
|
return ({
|
||
|
...state,
|
||
|
messages: [
|
||
|
...state.messages,
|
||
|
{
|
||
|
...payload,
|
||
|
id: finalId,
|
||
|
buttons: finalButtons,
|
||
|
},
|
||
|
],
|
||
|
});
|
||
|
},
|
||
|
},
|
||
|
|
||
|
update: {
|
||
|
params: {
|
||
|
id: v => check.string(v),
|
||
|
text: v => v === undefined || check.string(v),
|
||
|
progress: v => v === undefined || check.inRange(v, 0, 1),
|
||
|
},
|
||
|
reducer: (state, { id, ...payload }) => ({
|
||
|
...state,
|
||
|
messages: state.messages.map(m =>
|
||
|
(m.id === id
|
||
|
? { ...m, ...payload }
|
||
|
: m),
|
||
|
),
|
||
|
}),
|
||
|
},
|
||
|
|
||
|
closeMessage: {
|
||
|
params: {
|
||
|
id: v => check.string(v),
|
||
|
},
|
||
|
reducer: (state, { id }) => ({
|
||
|
...state,
|
||
|
messages: state.messages.filter(m => m.id !== id),
|
||
|
}),
|
||
|
},
|
||
|
|
||
|
reset: {
|
||
|
reducer: () => initialState,
|
||
|
},
|
||
|
},
|
||
|
|
||
|
selectors: {
|
||
|
generateMessageId: ({ messages }) => {
|
||
|
let id;
|
||
|
const anyMessageWithId = m => m.id === id;
|
||
|
do {
|
||
|
id = shortid.generate();
|
||
|
} while (messages.find(anyMessageWithId));
|
||
|
return id;
|
||
|
},
|
||
|
|
||
|
getMessages: ({ messages }) => ([...messages]),
|
||
|
|
||
|
getMessage: ({ messages }, id) => messages.find(m => m.id === id),
|
||
|
},
|
||
|
});
|
||
|
|
||
|
export const {
|
||
|
actions,
|
||
|
actionTypes,
|
||
|
reducer,
|
||
|
selectors,
|
||
|
} = myRedux;
|
||
|
|