Skip to content

Commit

Permalink
Jetpack Pro Dashboard: implement monitor notification settings modal (A…
Browse files Browse the repository at this point in the history
…utomattic#71373)

* Implement monitor notification settings modal

* Fix table responsiveness for monitor

* Update aria-label for notification schedule

* Use form for notification popup

* Move durations to utils

* Move mobile app link to utils

* Fix typo in file directory

* Allow close modal on clicking outside and change Jetpack mobile link

* Minor code changes

* Tokenize on space for add email
  • Loading branch information
yashwin authored Dec 23, 2022
1 parent c775e29 commit 0fc4e98
Show file tree
Hide file tree
Showing 5 changed files with 440 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { Button } from '@automattic/components';
import { Modal, ToggleControl } from '@wordpress/components';
import { useTranslate } from 'i18n-calypso';
import { useEffect, useState } from 'react';
import clockIcon from 'calypso/assets/images/jetpack/clock-icon.svg';
import SelectDropdown from 'calypso/components/select-dropdown';
import TokenField from 'calypso/components/token-field';
import {
availableNotificationDurations as durations,
mobileAppLink,
} from '../../sites-overview/utils';
import type { MonitorSettings } from '../../sites-overview/types';

import './style.scss';

type Duration = { label: string; time: number };

interface Props {
site: { blog_id: number; url: string };
onClose: () => void;
settings: MonitorSettings | undefined;
}

export default function NotificationSettings( { onClose, site, settings }: Props ) {
const translate = useTranslate();

const [ enableMobileNotification, setEnableMobileNotification ] = useState< boolean >( false );
const [ enableEmailNotification, setEnableEmailNotification ] = useState< boolean >( false );
const [ selectedDuration, setSelectedDuration ] = useState< Duration | undefined >( undefined );
const [ addedEmailAddresses, setAddedEmailAddresses ] = useState< string[] | [] >( [] );

function onSave( event: React.FormEvent< HTMLFormElement > ) {
event.preventDefault();
// handle save here
}

function selectDuration( duration: Duration ) {
setSelectedDuration( duration );
}

useEffect( () => {
if ( settings?.monitor_deferment_time ) {
const foundDuration = durations.find(
( duration ) => duration.time === settings.monitor_deferment_time
);
foundDuration && setSelectedDuration( foundDuration );
}
}, [ settings?.monitor_deferment_time ] );

useEffect( () => {
if ( settings?.monitor_notify_users_emails ) {
setAddedEmailAddresses( settings.monitor_notify_users_emails );
setEnableEmailNotification( true );
}
}, [ settings?.monitor_notify_users_emails ] );

const addEmailsContent = enableEmailNotification && (
<div className="notification-settings__email-container">
<TokenField
tokenizeOnSpace
placeholder={ translate( 'Enter email addresses' ) }
value={ addedEmailAddresses }
onChange={ setAddedEmailAddresses }
/>
<div className="notification-settings__email-condition">
{ translate( 'Separate with commas or the Enter key.' ) }
</div>
</div>
);

return (
<Modal
open={ true }
onRequestClose={ onClose }
title={ translate( 'Set custom notification' ) }
className="notification-settings__modal"
>
<div className="notification-settings__sub-title">{ site.url }</div>
<form onSubmit={ onSave }>
<div className="notification-settings__content">
<div className="notification-settings__content-block">
<div className="notification-settings__content-heading">
{ translate( 'Notify me about downtime:' ) }
</div>
<SelectDropdown
selectedIcon={
<img
className="notification-settings__duration-icon"
src={ clockIcon }
alt={ translate( 'Schedules' ) }
/>
}
selectedText={ selectedDuration?.label }
>
{ durations.map( ( duration ) => (
<SelectDropdown.Item
key={ duration.time }
selected={ duration.time === selectedDuration?.time }
onClick={ () => selectDuration( duration ) }
>
{ duration.label }
</SelectDropdown.Item>
) ) }
</SelectDropdown>
</div>
<div className="notification-settings__toggle-container">
<div className="notification-settings__toggle">
<ToggleControl
onChange={ setEnableMobileNotification }
checked={ enableMobileNotification }
/>
</div>
<div className="notification-settings__toggle-content">
<div className="notification-settings__content-heading">
{ translate( 'Mobile' ) }
</div>
<div className="notification-settings__content-sub-heading">
{ translate( 'Receive notifications via the {{a}}Jetpack App{{/a}}.', {
components: {
a: (
<a
className="notification-settings__link"
target="_blank"
rel="noreferrer"
href={ mobileAppLink }
/>
),
},
} ) }
</div>
</div>
</div>
<div className="notification-settings__toggle-container">
<div className="notification-settings__toggle">
<ToggleControl
onChange={ setEnableEmailNotification }
checked={ enableEmailNotification }
/>
</div>
<div className="notification-settings__toggle-content">
<div className="notification-settings__content-heading">{ translate( 'Email' ) }</div>
<div className="notification-settings__content-sub-heading">
{ translate( 'Receive email notifications with one or more recipients.' ) }
</div>
{
// We are using CSS to hide/show add email content on mobile/large screen view instead of the breakpoint
// hook since the 'useMobileBreakpont' hook returns true only when the width is > 480px, and we have some
// styles applied using the CSS breakpoint where '@include break-mobile' is true for width > 479px
}
<div className="notification-settings__large-screen">{ addEmailsContent }</div>
</div>
</div>
<div className="notification-settings__small-screen">{ addEmailsContent }</div>
</div>
<div className="notification-settings__footer">
<Button
onClick={ onClose }
aria-label={ translate( 'Cancel and close notification settings popup' ) }
>
{ translate( 'Cancel' ) }
</Button>
<Button type="submit" primary aria-label={ translate( 'Save notification settings' ) }>
{ translate( 'Save' ) }
</Button>
</div>
</form>
</Modal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
@import "@wordpress/base-styles/mixins";
@import "@wordpress/base-styles/breakpoints";

@keyframes components-modal__appear-animation {
from {
transform: translateY(32px);
}
to {
transform: translateY(0);
}
}

.notification-settings-title-light {
font-size: 0.75rem;
line-height: 14px;
color: var(--studio-gray-50);
}

.notification-settings__sub-title {
@extend .notification-settings-title-light;
position: absolute;
inset-block-start: 50px;

}

.notification-settings__content {
margin-block-start: -16px;
}

.notification-settings__content-heading {
font-size: 0.875rem;
line-height: 17px;
margin-block-end: 8px;
}

.notification-settings__content-sub-heading {
@extend .notification-settings-title-light;
}

.notification-settings__content-block {
margin-block-start: 24px;
position: relative;
}

.notification-settings__link {
text-decoration: underline;
}

.notification-settings__footer {
margin-block-end: 32px;
width: calc(100% - 64px); // reducing the left and right padding
display: flex;
justify-content: flex-start;
flex-direction: column;
position: absolute;
bottom: 0;

button {
height: 36px;
line-height: 18px;

&:nth-child(2) {
margin-block-start: 16px;
}
}

@include break-mobile {
position: static;
justify-content: right;
flex-direction: initial;
margin-block-start: 32px;
margin-block-end: 0;
width: auto;

button {
&:nth-child(2) {
margin-inline-start: 12px;
margin-block-start: 0;
}
}
}

}

.select-dropdown .select-dropdown__container {
display: block;
}

.notification-settings__duration-icon {
position: relative;
inset-block-start: 5px;
inset-inline-end: 2px;
width: 20px;
}


.notification-settings__toggle {
width: 15%;
display: inline-flex;
justify-content: end;

.components-form-toggle {
margin-right: 0 !important;
}

@include break-mobile {
justify-content: unset;
}
}

.notification-settings__toggle-content {
width: 85%;
display: inline-flex;
flex-direction: column;
}

.notification-settings__modal {
max-height: 100%;
width: 480px;
animation: components-modal__appear-animation 0.1s ease-out;
animation-fill-mode: forwards;

@include break-mobile {
width: 450px;
margin: auto;
}
}

.notification-settings__email-container {
margin-block-start: 8px;
width: 100%;

.token-field__suggestions-list {
display: none;
}

@include break-mobile {
margin-block-start: 4px;
}
}

.notification-settings__email-condition {
margin-block-start: 4px;
@extend .notification-settings-title-light;
}

.notification-settings__toggle-container {
@extend .notification-settings__content-block;
display: inline-flex;
flex-direction: row-reverse;
width: 100%;

@include break-mobile {
display: block;
}
}

.notification-settings__large-screen {
display: none;
@include break-mobile {
display: inherit;
}
}

.notification-settings__small-screen {
@include break-mobile {
display: none;
}
}
Loading

0 comments on commit 0fc4e98

Please sign in to comment.