diff --git a/packages/account/src/App.tsx b/packages/account/src/App.tsx index f658afe8facd..23cbccb72a8e 100644 --- a/packages/account/src/App.tsx +++ b/packages/account/src/App.tsx @@ -17,8 +17,11 @@ const App = ({ passthrough }: TAppProps) => { const { root_store, WS } = passthrough; setWebsocket(WS); + const { notification_messages_ui: Notifications } = root_store.ui; + return ( + {Notifications && } diff --git a/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx b/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx index 9632ae82057b..8b45270125a4 100644 --- a/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx +++ b/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx @@ -104,7 +104,7 @@ export const PersonalDetailsForm = observer(({ history }) => { const [is_btn_loading, setIsBtnLoading] = React.useState(false); const [is_submit_success, setIsSubmitSuccess] = useStateCallback(false); - const { client, notifications, ui, common } = useStore(); + const { client, notifications, common } = useStore(); const { authentication_status, @@ -132,7 +132,6 @@ export const PersonalDetailsForm = observer(({ history }) => { showPOAAddressMismatchFailureNotification, } = notifications; - const { Notifications } = ui; const { is_language_changing } = common; const is_mf = landing_company_shortcode === 'maltainvest'; const has_poa_address_mismatch = account_status.status?.includes('poa_address_mismatch'); @@ -561,7 +560,6 @@ export const PersonalDetailsForm = observer(({ history }) => { dirty, }) => ( - {Notifications && } {show_form && (
{ - const { client, ui, common } = useStore(); + const { client, common } = useStore(); const { email_address, getTwoFAStatus, has_enabled_two_fa, is_switching, setTwoFAStatus, setTwoFAChangedStatus } = client; const { is_language_changing } = common; - const { notification_messages_ui: Notifications } = ui; const [is_loading, setLoading] = React.useState(true); const [is_qr_loading, setQrLoading] = React.useState(false); const [error_message, setErrorMessage] = React.useState(''); @@ -198,7 +197,6 @@ const TwoFactorAuthentication = observer(() => { 'two-factor__wrapper-dashboard': is_appstore, })} > - {Notifications && } {has_enabled_two_fa ? TwoFactorEnabled : TwoFactorDisabled} diff --git a/packages/core/src/App/Containers/app-notification-messages.jsx b/packages/core/src/App/Containers/app-notification-messages.jsx index 4c14670d1f1d..6395fe7f6c45 100644 --- a/packages/core/src/App/Containers/app-notification-messages.jsx +++ b/packages/core/src/App/Containers/app-notification-messages.jsx @@ -11,7 +11,11 @@ import Notification, { max_display_notifications_mobile, } from '../Components/Elements/NotificationMessage'; import { useLocation } from 'react-router-dom'; -import { excluded_notifications, priority_toast_messages } from '../../Stores/Helpers/client-notifications'; +import { + excluded_notifications, + priority_toast_messages, + maintenance_notifications, +} from '../../Stores/Helpers/client-notifications'; const Portal = ({ children }) => isMobile() ? ReactDOM.createPortal(children, document.getElementById('deriv_app')) : children; @@ -107,6 +111,7 @@ const AppNotificationMessages = ({ const is_not_marked_notification = !marked_notifications.includes(message.key); const is_non_hidden_notification = isMobile() ? [ + ...maintenance_notifications, 'authenticate', 'deriv_go', 'document_needs_action', @@ -146,7 +151,14 @@ const AppNotificationMessages = ({ const is_only_for_p2p_notification = window.location.pathname !== routes.cashier_p2p || message?.platform === 'P2P'; - return is_not_marked_notification && is_non_hidden_notification && is_only_for_p2p_notification; + + const is_maintenance_notifications = maintenance_notifications.includes(message.key); + + return ( + is_not_marked_notification && + is_non_hidden_notification && + (is_only_for_p2p_notification || is_maintenance_notifications) + ); }); const notifications_limit = isMobile() ? max_display_notifications_mobile : max_display_notifications; @@ -160,7 +172,9 @@ const AppNotificationMessages = ({ const notifications_sublist = window.location.pathname === routes.cashier_deposit - ? filtered_excluded_notifications.filter(message => message.key.includes('switched_to_real')) + ? filtered_excluded_notifications.filter(message => + ['switched_to_real', ...maintenance_notifications].includes(message.key) + ) : filtered_excluded_notifications.slice(0, notifications_limit); if (!should_show_popups) return null; diff --git a/packages/core/src/Stores/Helpers/client-notifications.js b/packages/core/src/Stores/Helpers/client-notifications.js index b6c4bd87fa27..4e0f0049cd37 100644 --- a/packages/core/src/Stores/Helpers/client-notifications.js +++ b/packages/core/src/Stores/Helpers/client-notifications.js @@ -64,10 +64,13 @@ export const getCashierValidations = cashier_arr => { // Notifications keys will not be added to localStorage and will appear again after user logout/login export const excluded_notifications = ['contract_sold', 'switched_to_real', 'has_changed_two_fa']; +export const maintenance_notifications = ['system_maintenance', 'site_maintenance']; + export const priority_toast_messages = [ 'svg', 'need_fa', 'p2p_daily_limit_increase', 'authenticate', 'mt5_notification', + ...maintenance_notifications, ]; diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js index 1df9a795f509..273f5484af48 100644 --- a/packages/core/src/Stores/client-store.js +++ b/packages/core/src/Stores/client-store.js @@ -1771,19 +1771,6 @@ export default class ClientStore extends BaseStore { responseWebsiteStatus(response) { this.website_status = response.website_status; - if (this.website_status.message && this.website_status.message.length) { - this.root_store.notifications.addNotificationMessage({ - key: 'maintenance', - header: localize('Site is being updated'), - message: localize(this.website_status.message), - type: 'warning', - is_persistent: true, - }); - } else { - this.root_store.notifications.removeNotificationMessage({ - key: 'maintenance', - }); - } } responseLandingCompany(response) { @@ -2115,6 +2102,7 @@ export default class ClientStore extends BaseStore { this.landing_companies = {}; localStorage.removeItem('readScamMessage'); localStorage.removeItem('isNewAccount'); + LocalStore.set('marked_notifications', JSON.stringify([])); localStorage.setItem('active_loginid', this.loginid); localStorage.setItem('client.accounts', JSON.stringify(this.accounts)); diff --git a/packages/core/src/Stores/notification-store.js b/packages/core/src/Stores/notification-store.js index 7ee8de9afcd6..23be75cea7f3 100644 --- a/packages/core/src/Stores/notification-store.js +++ b/packages/core/src/Stores/notification-store.js @@ -27,6 +27,7 @@ import { getCashierValidations, getStatusValidations, hasMissingRequiredField, + maintenance_notifications, } from './Helpers/client-notifications'; import { sortNotifications, sortNotificationsMobile } from '../App/Components/Elements/NotificationMessage/constants'; import BaseStore from './base-store'; @@ -89,6 +90,7 @@ export default class NotificationStore extends BaseStore { () => root_store.common.app_routing_history.map(i => i.pathname), () => { this.filterNotificationMessages(); + this.marked_notifications = JSON.parse(LocalStore.get('marked_notifications') || '[]'); } ); reaction( @@ -223,10 +225,10 @@ export default class NotificationStore extends BaseStore { filterNotificationMessages() { if (LocalStore.get('active_loginid') !== 'null') this.resetVirtualBalanceNotification(LocalStore.get('active_loginid')); - if (window.location.pathname === routes.personal_details) { this.notification_messages = this.notification_messages.filter( - notification => notification.platform === 'Account' + notification => + notification.platform === 'Account' || maintenance_notifications.includes(notification.key) ); } else if (!window.location.pathname.includes(routes.cashier_p2p)) { this.notification_messages = this.notification_messages.filter(notification => { @@ -256,7 +258,6 @@ export default class NotificationStore extends BaseStore { const is_p2p_notifications_visible = p2p_settings[loginid] ? p2p_settings[loginid].is_notifications_visible : false; - if (refined_list.length) { refined_list.map(refined => { if (refined.includes('p2p')) { @@ -315,6 +316,12 @@ export default class NotificationStore extends BaseStore { let has_missing_required_field; + if (website_status?.message?.length) { + this.addNotificationMessage(this.client_notifications.site_maintenance); + } else { + this.removeNotificationByKey({ key: this.client_notifications.site_maintenance }); + } + if (is_logged_in) { if (isEmptyObject(account_status)) return; const { @@ -622,7 +629,10 @@ export default class NotificationStore extends BaseStore { } markNotificationMessage({ key }) { - this.marked_notifications.push(key); + if (!this.marked_notifications.includes(key)) { + this.marked_notifications.push(key); + LocalStore.set('marked_notifications', JSON.stringify(this.marked_notifications)); + } } refreshNotifications() { @@ -1227,6 +1237,14 @@ export default class NotificationStore extends BaseStore { type: 'danger', }; }, + site_maintenance: { + key: 'site_maintenance', + header: localize('We’re updating our site'), + message: localize('Some services may be temporarily unavailable.'), + type: 'warning', + should_show_again: true, + closeOnClick: notification_obj => this.markNotificationMessage({ key: notification_obj.key }), + }, system_maintenance: (withdrawal_locked, deposit_locked) => { let message, header; if (isCryptocurrency(client_data.currency)) { @@ -1247,9 +1265,9 @@ export default class NotificationStore extends BaseStore { ); } } else { - header = localize('Scheduled cashier system maintenance'); + header = localize('Scheduled cashier maintenance'); message = localize( - 'Our cashier is temporarily down due to system maintenance. You can access the cashier in a few minutes when the maintenance is complete.' + 'The cashier is temporarily down due to maintenance. It will be available as soon as the maintenance is complete.' ); } return { @@ -1257,6 +1275,8 @@ export default class NotificationStore extends BaseStore { header, message, type: 'warning', + should_show_again: true, + closeOnClick: notification_obj => this.markNotificationMessage({ key: notification_obj.key }), }; }, tax: { diff --git a/packages/core/src/sass/app/_common/components/app-notification-message.scss b/packages/core/src/sass/app/_common/components/app-notification-message.scss index 83254c5c4318..ceca615a6630 100644 --- a/packages/core/src/sass/app/_common/components/app-notification-message.scss +++ b/packages/core/src/sass/app/_common/components/app-notification-message.scss @@ -4,6 +4,7 @@ z-index: 6; position: absolute; right: 0; + margin-top: 1.6rem; > div { display: flex;