Skip to content

Instantly share code, notes, and snippets.

@paulmiller3000
Last active December 3, 2020 13:18
Show Gist options
  • Save paulmiller3000/d3cc3be7632e14c6c2f26d0b9592802e to your computer and use it in GitHub Desktop.
Save paulmiller3000/d3cc3be7632e14c6c2f26d0b9592802e to your computer and use it in GitHub Desktop.
bsd-strong-post-index.js
/*
This page demonstrates how to save WordPress settings through the Settings API from React.
It won't function on its own due to dependencies; it is an excerpt from a soon-to-be-published
plugin. It simply serves as an example.
Lines 62-76 demonstrate how to retrieve options.
Lines 133-169, in combination with state, demonstrate how to update options.
Inspired by:
https://www.codeinwp.com/blog/plugin-options-page-gutenberg/
https://gitlab.iseard.media/michael/kudos-donations/-/blob/9e8e6b1c6ff870dcb2637c374ee9763dca4bbc03/src/js/Settings/KudosAdmin.jsx
*/
const { BaseControl, Button, PanelBody, PanelRow, Placeholder, SelectControl, Spinner } = wp.components;
const { render, Component, Fragment } = wp.element;
const { __ } = wp.i18n;
import './admin.scss';
import * as api from '../utils/api';
import { Notice } from './Notice';
import * as ProgramsPhases from '../utils/programs-phases';
class App extends Component {
constructor(props) {
super(...arguments);
this.showNotice = this.showNotice.bind(this);
this.hideNotice = this.hideNotice.bind(this);
this.updateOptions = this.updateOptions.bind( this );
this.state = {
isAPILoaded: false,
isAPISaving: false,
isEdited: false,
isSaving: false,
noticeMessage: '',
phaseList: null,
programList: null,
programsAndPhases: null,
settings: { },
showNotice: false,
};
};
componentDidMount() {
let programsAndPhases;
wp.api.loadPromise.then( () => {
api.getProgramsPhasesTemplates()
.then((data) => {
if (data.status) {
// Set list of programs
this.populateProgramSelect(data);
// Get all programs and phases
programsAndPhases = ProgramsPhases.getAllProgramsAndPhases(data);
this.setState({ programsAndPhases: programsAndPhases });
// Get settings
this.settings = new wp.api.models.Settings();
if (false === this.state.isAPILoaded) {
this.settings.fetch().then(response => {
const defaultProgram = response.bsd_strong_post_default_program ? response.bsd_strong_post_default_program : null;
const defaultPhase = response.bsd_strong_post_default_phase ? response.bsd_strong_post_default_phase : null;
// Update state, which is also used to populate current value of controls
this.setState({
settings: {
bsd_strong_post_default_program: defaultProgram,
bsd_strong_post_default_phase: defaultPhase
},
isAPILoaded: true
});
this.populatePhaseSelect(defaultProgram);
});
}
}
})
});
}
populatePhaseSelect(programId) {
const phaseList = ProgramsPhases.getPhaseSelect(programId, this.state.programsAndPhases);
if (phaseList.length < 2 || !phaseList) {
this.setState({ phaseList: null });
} else {
this.setState({ phaseList: phaseList });
}
}
populateProgramSelect(data) {
const programList = ProgramsPhases.getProgramSelect(data);
this.setState({ programList: programList });
}
showNotice(message) {
this.setState({
showNotice: true,
noticeMessage: message,
});
}
hideNotice() {
this.setState({ showNotice: false });
}
updateProgram(newVal) {
this.setState({
isEdited: true,
settings: {
...this.state.settings,
bsd_strong_post_default_program: Number(newVal),
}
});
// Update phase select options
this.populatePhaseSelect(newVal);
}
updatePhase(newVal) {
this.setState({
isEdited: true,
settings: {
...this.state.settings,
bsd_strong_post_default_phase: Number(newVal),
}
})
}
updateOptions( showNotice = true ) {
this.setState({ isAPISaving: true });
// Delete empty settings keys (prevents 500 error when settings don't change)
for ( const key in this.state.settings ) {
if ( this.state.settings[ key ] === null ) {
delete this.state.settings[ key ];
}
}
// Create WordPress settings model
const model = new wp.api.models.Settings( {
...this.state.settings,
});
// Save to database
model
.save()
.then(response => {
this.setState({
settings: { ...response },
isAPISaving: false,
isEdited: false,
});
if ( showNotice ) {
this.showNotice(
__( 'Setting(s) updated', 'bsd-strong-post' )
);
}
})
.fail( ( response ) => {
if ( showNotice ) {
this.showNotice( response.statusText );
}
});
}
render() {
if (!this.state.isAPILoaded) {
return (
<Placeholder>
<Spinner/>
</Placeholder>
);
}
return (
<Fragment>
<div className="bsd-strong-post-header">
<div className="bsd-strong-post-container">
<div className="bsd-strong-post-logo">
<h1>{ __( 'BSD Strong Post' ) }</h1>
</div>
</div>
</div>
<Notice
showNotice={ this.state.showNotice }
hideNotice={ this.hideNotice }
message={ this.state.noticeMessage }
/>
<div className="bsd-strong-post-main">
<PanelBody title={ __( 'Settings' ) }>
<PanelRow>
<SelectControl
label={ __('Default Program', 'bsd-strong-post') }
help={ __('Set the default program for new training session posts.', 'bsd-strong-post') }
id='bsd-strong-post-options-default-program'
className='bsd-strong-post-select-field'
value={ this.state.settings.bsd_strong_post_default_program }
options={ this.state.programList }
disabled={ this.state.isAPISaving }
onChange={ e => this.updateProgram(e) }
/>
</PanelRow>
<PanelRow>
<SelectControl
label={ __('Default Phase', 'bsd-strong-post') }
help={ __('Set the default phase for new training session posts.', 'bsd-strong-post') }
id='bsd-strong-post-options-default-phase'
className='bsd-strong-post-select-field'
value={ this.state.settings.bsd_strong_post_default_phase }
options={ this.state.phaseList }
disabled={ this.state.isAPISaving } // TO DO: Also disable if selected program does not have a phase
onChange={ e => this.updatePhase(e) }
/>
</PanelRow>
<PanelRow>
<Button
isPrimary
disabled={ this.state.isSaving || !this.state.isEdited }
isBusy={ this.state.isSaving || this.state.checkingApi }
onClick={this.updateOptions}
>
{__('Save', 'bsd-strong-post')}
</Button>
</PanelRow>
</PanelBody>
</div>
</Fragment>
);
}
}
render(
<App/>,
document.getElementById( 'bsd-strong-post-settings' )
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment