Last active
December 3, 2020 13:18
-
-
Save paulmiller3000/d3cc3be7632e14c6c2f26d0b9592802e to your computer and use it in GitHub Desktop.
bsd-strong-post-index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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