Skip to content

Commit

Permalink
Merge pull request #838 from 10up/enhancement/837
Browse files Browse the repository at this point in the history
Add a Snackbar notice to inform users that settings have been saved successfully.
  • Loading branch information
dkotter authored Jan 13, 2025
2 parents 57e21d3 + 4082203 commit 57d27bd
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 17 deletions.
17 changes: 16 additions & 1 deletion src/js/settings/components/classifai-registration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ export const SaveSettingsButton = ( {
setSettings,
onSaveSuccess = () => {},
} ) => {
const { createErrorNotice, removeNotices } = useDispatch( noticesStore );
const { createErrorNotice, createSuccessNotice, removeNotices } =
useDispatch( noticesStore );
const notices = useSelect( ( select ) =>
select( noticesStore ).getNotices()
);
Expand All @@ -200,11 +201,21 @@ export const SaveSettingsButton = ( {
);
setSettings( res.settings );
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
return;
}

setSettings( res.settings );
onSaveSuccess();
createSuccessNotice(
__( 'Settings saved successfully.', 'classifai' ),
{
type: 'snackbar',
}
);
setIsSaving( false );
} )
.catch( ( error ) => {
Expand All @@ -219,6 +230,10 @@ export const SaveSettingsButton = ( {
}
);
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
} );
};

Expand Down
45 changes: 43 additions & 2 deletions src/js/settings/components/classifai-settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import {
/**
* WordPress dependencies
*/
import { useDispatch } from '@wordpress/data';
import { SlotFillProvider } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { SlotFillProvider, SnackbarList } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { useEffect, useState } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { store as noticeStore } from '@wordpress/notices';

/**
* Internal dependencies
Expand All @@ -28,6 +29,7 @@ import { STORE_NAME } from '../../data/store';
import { FeatureContext } from '../feature-settings/context';
import { ClassifAIRegistration } from '../classifai-registration';
import { ClassifAIWelcomeGuide } from './welcome-guide';
import { Notices } from '../feature-settings/notices';

const { services, features } = window.classifAISettings;

Expand Down Expand Up @@ -121,6 +123,43 @@ export const ServiceNavigation = () => {
);
};

/**
* Snackbar component to render the snackbar notifications.
*
* @return {React.ReactElement} The Snackbar component.
*/
export const SnackbarNotifications = () => {
const { removeNotice, removeNotices } = useDispatch( noticeStore );
const location = useLocation();

const { notices } = useSelect( ( select ) => {
const allNotices = select( noticeStore ).getNotices();
return {
notices: allNotices.filter(
( notice ) => notice.type === 'snackbar'
),
};
}, [] );

useEffect( () => {
// Remove existing snackbar notices on location change.
if ( removeNotices ) {
removeNotices( notices.map( ( { id } ) => id ) );
} else if ( removeNotice ) {
notices.forEach( ( { id } ) => removeNotice( id ) );
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ location, removeNotice, removeNotices ] );

return (
<SnackbarList
className="classifai-settings-snackbar-notices"
notices={ notices }
onRemove={ ( notice ) => removeNotice( notice ) }
/>
);
};

/**
* Main ClassifAI Settings Component.
*
Expand Down Expand Up @@ -188,6 +227,7 @@ export const ClassifAISettings = () => {
<Header />
<div className="classifai-settings-wrapper">
<div className="classifai-admin-notices wrap"></div>
<Notices feature={ 'generic-notices' } />
<ServiceNavigation />
<Routes>
<Route
Expand All @@ -211,6 +251,7 @@ export const ClassifAISettings = () => {
/>
</Routes>
</div>
<SnackbarNotifications />
</HashRouter>
</SlotFillProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ export const SaveSettingsButton = ( {
label = __( 'Save Settings', 'classifai' ),
} ) => {
const { featureName } = useFeatureSettings();
const { createErrorNotice, removeNotices, removeNotice } =
useDispatch( noticesStore );
const {
createSuccessNotice,
createErrorNotice,
removeNotices,
removeNotice,
} = useDispatch( noticesStore );
const notices = useSelect( ( select ) =>
select( noticesStore ).getNotices()
);
Expand Down Expand Up @@ -79,9 +83,19 @@ export const SaveSettingsButton = ( {
} );
setSettings( res.settings );
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
return;
}
onSaveSuccess();
createSuccessNotice(
__( 'Settings saved successfully.', 'classifai' ),
{
type: 'snackbar',
}
);
setSettings( res.settings );
setIsSaving( false );
} )
Expand All @@ -97,6 +111,10 @@ export const SaveSettingsButton = ( {
}
);
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
} );
};

Expand Down
77 changes: 65 additions & 12 deletions src/js/settings/components/service-settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {
Notice,
Icon,
} from '@wordpress/components';
import { useEffect, useRef } from '@wordpress/element';
import { useEffect, useRef, useState } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { store as noticesStore } from '@wordpress/notices';

/**
* Internal dependencies
Expand Down Expand Up @@ -54,8 +55,18 @@ const ConfigureProviderNotice = () => (
* @return {Object} The ServiceSettings component.
*/
export const ServiceSettings = () => {
const [ enabled, setEnabled ] = useState( false );
const { setCurrentService, setIsSaving, setSettings } =
useDispatch( STORE_NAME );
const {
createSuccessNotice,
createErrorNotice,
removeNotices,
removeNotice,
} = useDispatch( noticesStore );
const notices = useSelect( ( select ) =>
select( noticesStore ).getNotices()
);

const { service } = useParams();
const isInitialPageLoad = useRef( true );
Expand All @@ -77,6 +88,13 @@ export const ServiceSettings = () => {
const serviceFeatures = features[ service ] || {};

const saveSettings = () => {
// Remove existing notices.
if ( removeNotices ) {
removeNotices( notices.map( ( { id } ) => id ) );
} else if ( removeNotice ) {
notices.forEach( ( { id } ) => removeNotice( id ) );
}

setIsSaving( true );
apiFetch( {
path: '/classifai/v1/settings/',
Expand All @@ -86,15 +104,49 @@ export const ServiceSettings = () => {
is_setup: true,
step: 'enable_features',
},
} ).then( ( res ) => {
if ( res.errors && res.errors.length ) {
setIsSaving( false );
return;
}
} )
.then( ( res ) => {
if ( res.errors && res.errors.length ) {
res.errors.forEach( ( error ) => {
createErrorNotice( error.message, {
id: 'error-generic-notices',
} );
} );
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
return;
}

setSettings( res.settings );
setIsSaving( false );
} );
const message = enabled
? __( 'Feature enabled successfully.', 'classifai' )
: __( 'Feature disabled successfully.', 'classifai' );

createSuccessNotice( message, {
type: 'snackbar',
} );
setSettings( res.settings );
setIsSaving( false );
} )
.catch( ( error ) => {
createErrorNotice(
error.message ||
__(
'An error occurred while saving settings.',
'classifai'
),
{
id: 'error-generic-notices',
}
);
setIsSaving( false );
window.scrollTo( {
top: 0,
behavior: 'smooth',
} );
} );
};

const statuses = Object.keys( settings )
Expand Down Expand Up @@ -126,7 +178,8 @@ export const ServiceSettings = () => {
feature
)
}
onChange={ ( value ) =>
onChange={ ( value ) => {
setEnabled( value );
wp.data
.dispatch( STORE_NAME )
.setFeatureSettings(
Expand All @@ -136,8 +189,8 @@ export const ServiceSettings = () => {
: '0',
},
feature
)
}
);
} }
__nextHasNoMarginBottom
/>
</Flex>
Expand Down
10 changes: 10 additions & 0 deletions src/scss/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,16 @@
.classifai-admin-notices {
margin-right: 0px;
}

.classifai-settings-snackbar-notices {
position: fixed;
left: auto;
bottom: 40px;

@media screen and (max-width: 600px) {
padding: 0px 20px 0px 0px;
}
}
}

.classifai-onboarding {
Expand Down

0 comments on commit 57d27bd

Please sign in to comment.