at the end of the day, it was inevitable

This commit is contained in:
Mo Elzubeir
2022-12-09 08:36:26 -06:00
commit 1218570914
1768 changed files with 887087 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
import React, { Fragment } from 'react';
import ReduxModule from '../abstract/reduxModule';
import { toast } from 'react-toastify';
import i18n from '../../../i18n';
import { fromJS } from 'immutable';
import { isLive } from '../../../common/constants';
const ADD_ALERT = 'Add alert';
const REMOVE_ALERT = 'Remove alert';
const REMOVE_ALL_ALERTS = 'Remove alert';
export class Alerts extends ReduxModule {
getNamespace() {
return '[Alert]';
}
defineActions() {
const addAlert = this.createAction(ADD_ALERT, (options) => options);
const removeAlert = this.createAction(REMOVE_ALERT, (id) => id);
const removeAllAlerts = this.createAction(REMOVE_ALL_ALERTS, () => {});
return {
addAlert,
removeAlert,
removeAllAlerts
};
}
getInitialState() {
return [];
}
defineReducers() {
return {
[ADD_ALERT]: (state, { payload: options }) => {
showAlert(options);
// handling breaking api errors (should be catch by backend)
const newOptions = Array.isArray(options)
? options.map((v) =>
typeof v === 'string' && v.startsWith('Error: ') && isLive
? i18n.t('common:alerts.error.somethingWrong2')
: v
)
: options;
return state.concat(newOptions);
},
[REMOVE_ALERT]: (state, { payload: id }) => {
return state.filter((alert) => alert.id !== id);
},
[REMOVE_ALL_ALERTS]: () => {
return fromJS([]);
}
};
}
}
const alerts = new Alerts();
alerts.init();
const backendErrs = ['Error: ', 'Can\'t exec search'];
const showAlert = (alertMessages) => {
const alertsArr = Array.isArray(alertMessages)
? alertMessages
: [alertMessages];
alertsArr
.map((alert) => {
return typeof alert === 'string'
? {
message:
isLive && backendErrs.some((v) => alert.startsWith(v))
? i18n.t('common:alerts.error.somethingWrong2')
: alert
} // handling breaking api errors (should be catch by backend)
: alert;
})
.map((alert) => {
const interpolateParameters = alert ? alert.parameters : {};
const i18nKey = alert && `alerts.${alert.type}.${alert.transKey}`;
if (alert) {
toast(
<Fragment>
{alert.type ? (
<p className="mb-2 text-uppercase">
{i18n.t(`alerts.type.${oldValueMapping[alert.type]}`, {
defaultValue: oldValueMapping[alert.type]
})}
</p>
) : (
''
)}
{(i18nKey &&
i18n.t(i18nKey, {
...interpolateParameters,
defaultValue: alert.message || 'Unknown error'
})) ||
alert.message ||
'Unknown error'}
</Fragment>,
{
type: oldValueMapping[alert.type || 'warning']
}
);
} else {
toast.warn('Unknown error');
}
});
};
const oldValueMapping = {
notice: 'success',
warning: 'warning',
error: 'error'
};
export const addAlert = alerts.actions.addAlert;
export default alerts;
+172
View File
@@ -0,0 +1,172 @@
import * as api from '../../../api/loginApi';
import $ from 'jquery';
import reduxModule from '../abstract/reduxModule';
import { tokenInject } from '../../utils/common';
import { addAlert } from './alerts';
import Cookies from 'cookies-js';
import axios from 'axios';
// import { TOGGLE_UPGRADE_PLAN } from './base';
const ACTIONS = {
PENDING: 'Login pending',
SAVE_USER_DATA: 'Save user data',
SET_FORM_ERROR: 'Set form error',
SET_RESTRICTIONS: 'Set user restrictions'
};
export const AuthNS = '[Auth]';
export const USER_LOGOUT = 'Logout user';
const REFRESH_TOKEN = 'refreshToken';
class Auth extends reduxModule {
getNamespace() {
return AuthNS;
}
getInitialState() {
return {
form: {
error: ''
},
isAuthPending: true,
token: '',
refreshToken: '',
user: {},
userSubscription: '15d',
userSubscriptionDate: '2017-03-01'
};
}
saveRefreshToken(refreshToken, rememberMe) {
if (rememberMe) {
localStorage.setItem(REFRESH_TOKEN, refreshToken);
} else {
Cookies.set(REFRESH_TOKEN, refreshToken);
}
}
clearRefreshToken() {
localStorage.removeItem(REFRESH_TOKEN);
delete axios.defaults.headers.common['Authorization'];
Cookies.expire(REFRESH_TOKEN);
}
getRefreshToken() {
return Cookies.get(REFRESH_TOKEN) || localStorage.getItem(REFRESH_TOKEN);
}
loginRequest(dispatch, promise, rememberMe) {
dispatch(this.loginPending(true));
return promise
.then((data) => {
const { token, refreshToken, user } = data;
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; // to call api with axios
this.saveRefreshToken(data.refreshToken, rememberMe);
dispatch(this.saveUserData({ token, refreshToken, user }));
dispatch(this.loginPending(false));
dispatch(this.authSetError(''));
// history.replace(location); //rerun auth guards for routes
})
.catch((error) => {
dispatch(this.authSetError(error.msg));
dispatch(this.loginPending(false));
delete axios.defaults.headers.common['Authorization'];
// history.replace(location); //rerun auth guards for routes
});
}
refreshLogin = () => {
return (dispatch) => {
const refreshToken = this.getRefreshToken();
if (refreshToken) {
this.loginRequest(dispatch, api.loginRefresh(refreshToken));
} else {
dispatch(this.loginPending(false));
// history.replace(location); //rerun auth guards for routes
}
};
};
login = (email, password, rememberMe) => {
return (dispatch) => {
const validateEmail = /^(([^<>()[\]\\.,;:\s@]+(\.[^<>()[\]\\.,;:\s@]+)*)|(.+))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const isEmailValid = validateEmail.test(email);
if (isEmailValid) {
this.loginRequest(dispatch, api.login({ email, password }), rememberMe);
} else {
dispatch(this.loginPending(false));
dispatch(this.authSetError('Please enter valid email address'));
}
};
};
logout = () => {
return (dispatch) => {
this.clearRefreshToken();
// dispatch(this.saveUserData({ token: '' }));
dispatch(this.userLogout(true));
dispatch(this.loginPending(false));
// history.push('/auth');
};
};
getRestrictions = () =>
tokenInject((dispatch, getState, token) => {
api
.getRestrictions(token)
.then((data) => {
dispatch(this.setRestrictions(data));
})
.catch((errors) => {
dispatch(addAlert(errors));
});
});
handleErrors = () => (dispatch) => {
$(document).ajaxError((event, jqXHR, settings, thrownError) => {
if (jqXHR.status === 402) {
const response = jqXHR.responseJSON;
const failedRestriction = response.failedRestriction;
const restrictions = response.restrictions;
const limit = restrictions.limits[failedRestriction];
if (limit) {
dispatch(this.setRestrictions(restrictions));
// dispatch({ type: `[Base] ${TOGGLE_UPGRADE_PLAN}`, payload: true }); // uncomment when upgrade page is ready
dispatch(
addAlert({
type: 'error',
transKey: 'restriction',
id: 'restriction'
})
);
}
}
});
};
defineActions() {
this.loginPending = this.set(ACTIONS.PENDING, 'isAuthPending');
this.saveUserData = this.merge(ACTIONS.SAVE_USER_DATA);
this.authSetError = this.setIn(ACTIONS.SET_FORM_ERROR, ['form', 'error']);
this.setRestrictions = this.mergeIn(ACTIONS.SET_RESTRICTIONS, [
'user',
'restrictions'
]);
this.userLogout = this.set(USER_LOGOUT, 'userLogout');
return {
login: this.login,
logout: this.logout,
refreshLogin: this.refreshLogin,
authSetError: this.authSetError,
handleErrors: this.handleErrors,
getRestrictions: this.getRestrictions
};
}
}
const auth = new Auth();
auth.init();
export const getRestrictions = auth.actions.getRestrictions;
export default auth;
+157
View File
@@ -0,0 +1,157 @@
import reduxModule from '../abstract/reduxModule';
import dashboards, { LOAD_DASHBOARDS } from '../appState/dashboards';
import * as api from '../../../api/usersApi';
export const TOGGLE_UPGRADE_PLAN = 'TOGGLE_UPGRADE_PLAN';
export class Base extends reduxModule {
getNamespace() {
return '[Base]';
}
changeUserPassword = (password, oldPassword, { token, dispatch }) => {
dispatch(this.setSettingsPopupError(null));
return api
.changePassword(token, { password, oldPassword })
.then(() => {
dispatch(this.hideUserSettingsPopup());
})
.catch((response) => {
dispatch(this.setSettingsPopupError(response[0].message));
});
};
defineActions() {
// const toggleLangsDrop = this.toggle('TOGGLE_LANGS_DROP', 'isLangsDropVisible')
// const hideLangsDrop = this.reset('HIDE_LANGS_DROP', 'isLangsDropVisible', false)
// const toggleSidebar = this.toggle('TOGGLE_SIDEBAR', 'isSidebarCollapsed')
const setDashboardTabs = this.createAction('SET_DASHBOARD_TABS');
const chooseLanguage = this.createAction('CHOOSE_LANG');
const showUserSettingsPopup = this.reset(
'SHOW_USER_SETTINGS_DROP',
'isSettingsPopupVisible',
true
);
const hideUserSettingsPopup = (this.hideUserSettingsPopup = this.reset(
'HIDE_USER_SETTINGS_DROP',
'isSettingsPopupVisible',
false
));
const changeUserPassword = this.thunkAction(
'CHANGE_USER_PASSWORD',
this.changeUserPassword
);
const setSettingsPopupError = (this.setSettingsPopupError = this.set(
'SET_SETTINGS_POPUP_ERROR',
'settingsPopupError'
));
const toggleResponsiveMenu = this.toggle(
'TOGGLE_RESPONSIVE_MENU',
'responsiveMenuVisible'
);
const toggleUpgradeModal = this.toggle(
TOGGLE_UPGRADE_PLAN,
'isUpgradeVisible'
);
const toggleWebTour = this.toggle('TOGGLE_WEBTOUR', 'isTourOpen');
return {
// toggleLangsDrop,
chooseLanguage,
// hideLangsDrop,
// toggleSidebar,
setDashboardTabs,
showUserSettingsPopup,
hideUserSettingsPopup,
changeUserPassword,
setSettingsPopupError,
toggleResponsiveMenu,
toggleUpgradeModal,
toggleWebTour
};
}
getInitialState() {
return {
tabs: {
/*'dashboard': {
items: []
},*/
search: {
items: [
{ title: 'search', url: 'search' },
{ title: 'sourceIndex', url: 'source-index' },
{ title: 'sourceLists', url: 'source-lists' }
],
icon: 'pe-7s-search'
},
analyze: {
items: [
// {title: 'welcome', url: 'welcome'},
{ title: 'savedAnalysis', url: 'saved' },
{ title: 'createAnalysis', url: 'create' }
],
icon: 'pe-7s-graph1'
},
share: {
items: [
{ title: 'notifications', url: 'notifications' },
{ title: 'manageEmails', url: 'manage-emails', masterOnly: true },
{
title: 'manageRecipients',
url: 'manage-recipients',
masterOnly: true
},
{ title: 'export', url: 'export' }
],
icon: 'pe-7s-share'
}
},
// isSidebarCollapsed: false,
isUserSettingsDropVisible: false,
// isLangsDropVisible: false,
isSettingsPopupVisible: false,
settingsPopupError: '',
isThereSomethingNew: true,
langs: ['en', 'ar', 'fr'],
// langs: ['en', 'ar', 'fr', 'es', 'de', , 'he', 'nl', 'pt'],
activeLang: '',
rtlLang: false,
responsiveMenuVisible: false,
isUpgradeVisible: false
};
}
defineReducers() {
this.addExternalReducer(
dashboards.ns(`${LOAD_DASHBOARDS} fulfilled`),
(state, { payload: dashboards }) => {
const dashboardTabs = dashboards.map((d) => ({
url: d.id,
title: d.name
}));
return state.mergeIn(['tabs', 'dashboard', 'items'], dashboardTabs);
}
);
return {
CHOOSE_LANG: (state, { payload: lang }) => {
const langsAvailable = state.get('langs');
const language = langsAvailable.includes(lang) ? lang : 'en';
const rtlLanguages = ['ar', 'he'];
const rtlLang = rtlLanguages.includes(language);
const dir = rtlLang ? 'rtl' : 'ltr';
document.documentElement.dir = dir; // set page direction
document.documentElement.lang = language;
return state.merge({
activeLang: language,
rtlLang: rtlLang
});
}
};
}
}
const instance = new Base();
instance.init();
export default instance;
@@ -0,0 +1,168 @@
import {createAction, handleActions} from 'redux-actions'
import {fromJS} from 'immutable'
import {thunkAction} from '../../utils/common'
import * as api from '../../../api/registrationApi'
import {push} from 'react-router-redux'
import { addAlert } from './alerts'
import i18n from '../../../i18n'
const NS = '[RESET PASS]'
/* const GET_BILLING_PLANS = `${NS} Get billing plans`
const SELECT_BILLING_PLAN = `${NS} Select billing plan`
const SEND_REGISTER_REQUEST = `${NS} Send register request`
const FINISH_REGISTER = `${NS} Finish register`
const SHOW_REGISTER_ERROR = `${NS} Show register error` */
const REQUEST_PASSWORD_RESET = `${NS} Request password reset`
const CONFIRM_PASSWORD_RESET = `${NS} Confirm password reset`
const CLEAR_MESSAGES = `${NS} Clear messages`
/*
const getBillingPlans = thunkAction(GET_BILLING_PLANS, ({token, fulfilled}) => {
return api
.getBillingPlans(token)
.then((plans) => {
fulfilled(plans)
})
}, true)
const selectBillingPlan = createAction(SELECT_BILLING_PLAN, (billingPlan) => ({billingPlan}))
const showRegisterError = createAction(SHOW_REGISTER_ERROR)
const sendRegisterRequest = thunkAction(SEND_REGISTER_REQUEST, (formValues, {token, fulfilled, getState, dispatch}) => {
const billingPlan = getState().getIn(['common', 'register', 'selectedBillingPlan'])
const privatePerson = Boolean(formValues.privatePerson)
let payload = {}
Object.assign(payload, formValues, {
billingPlanId: billingPlan.id,
privatePerson: privatePerson
})
if (privatePerson) {
delete payload.organizationName
delete payload.organizationAddress
delete payload.organizationEmail
delete payload.organizationPhone
}
return api
.sendRegistrationRequest(token, payload)
.then((response) => {
fulfilled(response)
dispatch(showRegisterError(null))
dispatch(push('/auth/register-finish'))
})
.catch((response) => {
dispatch(showRegisterError(response[0]))
throw response
})
}, true)
const finishRegistration = thunkAction(FINISH_REGISTER, (formValues, {getState, token, fulfilled}) => {
let verificationCode = getState().getIn(['common', 'register', 'registrationCode'])
const payload = Object.assign({}, {
code: verificationCode,
card: {
creditCardNumber: formValues.creditCardNumber,
CVV: formValues.CVV,
expireMonth: formValues.expireMonth,
expireYear: formValues.expireYear,
address: {
country: formValues.country,
city: formValues.city,
street: formValues.street,
postalCode: formValues.postalCode
}
}
})
return api
.finishRegistration(token, payload)
.then((response) => {
fulfilled(response)
})
}, true) */
const requestPasswordReset = thunkAction(REQUEST_PASSWORD_RESET, (email, {fulfilled}) => {
return api
.requestPasswordReset(null, {email})
.then(() => {
fulfilled(
i18n.t('loginApp:messages.forgotPasswordSubmit', { email: email })
);
})
})
const confirmPasswordReset = thunkAction(REQUEST_PASSWORD_RESET, (confirmationToken, password, {dispatch}) => {
return api
.confirmPasswordReset(null, {confirmationToken, password})
.then(() => {
dispatch(push('/auth/login'))
dispatch(addAlert({type: 'notice', message: i18n.t('loginApp:messages.passwordUpdated')}))
})
})
const clearMessages = createAction(CLEAR_MESSAGES)
export const actions = {
/* getBillingPlans,
selectBillingPlan,
sendRegisterRequest,
finishRegistration, */
requestPasswordReset,
confirmPasswordReset,
// showRegisterError,
clearMessages
}
export const initialState = fromJS({
selectedBillingPlan: '',
billingPlans: [],
isLoading: false,
error: null,
registrationCode: null,
successMessage: null
})
/*
const toggleLoading = (state, {payload: {isPending}}) => {
return state.set('isLoading', isPending)
} */
export default handleActions({
/*
[`${GET_BILLING_PLANS} fulfilled`]: (state, {payload: plans}) => state.set('billingPlans', plans),
[SELECT_BILLING_PLAN]: (state, {payload: {billingPlan}}) => {
console.log(billingPlan)
return state.set('selectedBillingPlan', billingPlan)
},
[`${SEND_REGISTER_REQUEST} pending`]: toggleLoading,
[`${SEND_REGISTER_REQUEST} fulfilled`]: (state, {payload: response}) => {
return state.merge({
'registrationCode': response.code,
'successMessage': response.message
})
},
[`${FINISH_REGISTER} pending`]: toggleLoading,
[`${FINISH_REGISTER} fulfilled`]: (state, {payload: response}) => {
return state.set('successMessage', response.message)
}, */
[`${REQUEST_PASSWORD_RESET} fulfilled`]: (state, {payload: message}) => {
return state.set('successMessage', message)
},
[`${CONFIRM_PASSWORD_RESET} fulfilled`]: (state, {payload: message}) => {
return state.set('successMessage', message)
},
[CLEAR_MESSAGES]: (state) => {
return state.set('successMessage', null)
}
/*
[SHOW_REGISTER_ERROR]: (state, {payload: error}) => {
return state.set('error', error)
},
[`${GET_BILLING_PLANS} pending`]: toggleLoading */
}, initialState)