soiz1's picture
Upload 1525 files
f2bee8a verified
import alertsData, {AlertTypes, AlertLevels} from '../lib/alerts/index.jsx';
import extensionData from '../lib/libraries/extensions/index.jsx';
const SHOW_ALERT = 'scratch-gui/alerts/SHOW_ALERT';
const SHOW_EXTENSION_ALERT = 'scratch-gui/alerts/SHOW_EXTENSION_ALERT';
const CLOSE_ALERT = 'scratch-gui/alerts/CLOSE_ALERT';
const CLOSE_ALERTS_WITH_ID = 'scratch-gui/alerts/CLOSE_ALERTS_WITH_ID';
const CLOSE_ALERT_WITH_ID = 'scratch-gui/alerts/CLOSE_ALERT_WITH_ID';
/**
* Initial state of alerts reducer
*
* {bool} visible - whether the alerts are visible
* {array} alertsList - list of alerts, each with properties:
* * alertType (required): one of AlertTypes
* * closeButton (optional): bool indicating that we should show close button
* * content (optional): react element (a <FormattedMessage />)
* * extentionId (optional): id string that identifies the extension
* * iconURL (optional): string
* * level (required): string, one of AlertLevels
* * message (optional): string
* * showReconnect (optional): bool
*/
const initialState = {
visible: true,
alertsList: []
};
const filterPopupAlerts = alertsList => (
alertsList.filter(curAlert => (
curAlert.alertType === AlertTypes.STANDARD ||
curAlert.alertType === AlertTypes.EXTENSION
))
);
const filterInlineAlerts = alertsList => (
alertsList.filter(curAlert => (
curAlert.alertType === AlertTypes.INLINE
))
);
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case SHOW_ALERT: { // intended to show standard and inline alerts, but not extensions
const alertId = action.alertId;
if (alertId) {
const newAlert = {
alertId: alertId,
level: AlertLevels.WARN // default level
};
const alertData = alertsData.find(thisAlertData => thisAlertData.alertId === alertId);
if (alertData) {
const newList = state.alertsList.filter(curAlert => (
!alertData.clearList || alertData.clearList.indexOf(curAlert.alertId) === -1
));
if (action.data && action.data.message) {
newAlert.message = action.data.message;
}
newAlert.alertType = alertData.alertType || AlertTypes.STANDARD;
newAlert.closeButton = alertData.closeButton;
newAlert.content = alertData.content;
newAlert.iconURL = alertData.iconURL;
newAlert.iconSpinner = alertData.iconSpinner;
newAlert.level = alertData.level;
newAlert.showDownload = alertData.showDownload;
newAlert.showSaveNow = alertData.showSaveNow;
newList.push(newAlert);
return Object.assign({}, state, {
alertsList: newList
});
}
}
return state; // if alert not found, show nothing
}
case SHOW_EXTENSION_ALERT: {
const extensionId = action.data.extensionId;
if (extensionId) {
const extension = extensionData.find(ext => ext.extensionId === extensionId);
if (extension) {
const newList = state.alertsList.slice();
const newAlert = {
alertType: AlertTypes.EXTENSION,
closeButton: true,
extensionId: extensionId,
extensionName: extension.name,
iconURL: extension.connectionSmallIconURL,
level: AlertLevels.WARN,
showReconnect: true
};
newList.push(newAlert);
return Object.assign({}, state, {
alertsList: newList
});
}
}
return state; // if alert not found, show nothing
}
case CLOSE_ALERT_WITH_ID:
case CLOSE_ALERT: {
if (action.alertId) {
action.index = state.alertsList.findIndex(a => a.alertId === action.alertId);
if (action.index === -1) return state;
}
const newList = state.alertsList.slice();
newList.splice(action.index, 1);
return Object.assign({}, state, {
alertsList: newList
});
}
case CLOSE_ALERTS_WITH_ID: {
return Object.assign({}, state, {
alertsList: state.alertsList.filter(curAlert => (
curAlert.alertId !== action.alertId
))
});
}
default:
return state;
}
};
/**
* Action creator to close an alert with the given index.
*
* @param {object} index - the index of the alert to close.
* @return {object} - an object to be passed to the reducer.
*/
const closeAlert = function (index) {
return {
type: CLOSE_ALERT,
index
};
};
/**
* Action creator to close all alerts with a given ID.
*
* @param {string} alertId - id string of the alert to close
* @return {object} - an object to be passed to the reducer.
*/
const closeAlertsWithId = function (alertId) {
return {
type: CLOSE_ALERTS_WITH_ID,
alertId
};
};
/**
* Action creator to close a single alert with a given ID.
*
* @param {string} alertId - id string of the alert to close
* @return {object} - an object to be passed to the reducer.
*/
const closeAlertWithId = function (alertId) {
return {
type: CLOSE_ALERT_WITH_ID,
alertId
};
};
/**
* Action creator to show an alert with the given alertId.
*
* @param {string} alertId - id string of the alert to show
* @return {object} - an object to be passed to the reducer.
*/
const showStandardAlert = function (alertId) {
return {
type: SHOW_ALERT,
alertId
};
};
/**
* Action creator to show an alert with the given input data.
*
* @param {object} data - data for the alert
* @param {string} data.message - message for the alert
* @param {string} data.extensionId - extension ID for the alert
* @return {object} - an object to be passed to the reducer.
*/
const showExtensionAlert = function (data) {
return {
type: SHOW_EXTENSION_ALERT,
data
};
};
/**
* Function to dispatch showing an alert, with optional
* timeout to make it close/go away.
*
* @param {object} dispatch - dispatch function
* @param {string} alertId - the ID of the alert
*/
const showAlertWithTimeout = function (dispatch, alertId) {
const alertData = alertsData.find(thisAlertData => thisAlertData.alertId === alertId);
if (alertData) {
dispatch(showStandardAlert(alertId));
if (alertData.maxDisplaySecs) {
setTimeout(() => {
dispatch(closeAlertsWithId(alertId));
}, alertData.maxDisplaySecs * 1000);
}
}
};
export {
reducer as default,
initialState as alertsInitialState,
closeAlert,
closeAlertWithId,
filterInlineAlerts,
filterPopupAlerts,
showAlertWithTimeout,
showExtensionAlert,
showStandardAlert
};