├── .eslintrc ├── .gitignore ├── build ├── build.css └── build.js ├── index.php ├── package-lock.json ├── package.json ├── readme.md ├── src ├── index.js └── style.scss └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "wordpress", 7 | "parserOptions": { 8 | "ecmaFeatures": { 9 | "jsx": true 10 | }, 11 | "ecmaVersion": 2018, 12 | "sourceType": "module" 13 | }, 14 | "plugins": [ 15 | "react" 16 | ], 17 | "rules": { 18 | "indent": [ 19 | "error", 20 | "tab" 21 | ], 22 | "linebreak-style": [ 23 | "error", 24 | "unix" 25 | ], 26 | "quotes": [ 27 | "error", 28 | "single" 29 | ], 30 | "semi": [ 31 | "error", 32 | "always" 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /build/build.css: -------------------------------------------------------------------------------- 1 | *{box-sizing:inherit}.settings_page_awesome{background:#f6f6f6;font-size:14px;position:relative;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif}#wpcontent{padding-left:0}.auto-fold #wpcontent{padding-left:0}#codeinwp-awesome-plugin .components-placeholder{background:#f6f6f6;margin-top:25vh;margin-bottom:25vh}#codeinwp-awesome-plugin .codeinwp-header{padding:20px 10px;background-color:#ffffff;box-shadow:0 1px 0 rgba(213,213,213,0.5),0 1px 2px #eee}#codeinwp-awesome-plugin .codeinwp-header .codeinwp-container{margin:0 auto;max-width:750px}#codeinwp-awesome-plugin .codeinwp-header .codeinwp-container .codeinwp-logo{display:flex;align-items:center;justify-content:center}#codeinwp-awesome-plugin .codeinwp-main{margin-left:auto;margin-right:auto;max-width:750px}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body{margin:25px 0;background:#fff;border:1px solid #e2e4e7}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__body-toggle{border-bottom:1px solid #d6e2ed}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row{padding:10px;margin:0}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control .components-base-control__field{display:flex;align-items:center;margin-bottom:10px}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field{width:100%}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field{display:block}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field label{font-weight:600;margin-bottom:10px}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field input{border:1px solid #b7c9d9;border-radius:3px;font-size:14px;padding:9px 15px;width:100%;box-shadow:none;height:40px;margin:0 0 10px 0;color:#444}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field input:disabled{background:#f6f6f6;border-color:#eeeeee;color:#bbbbbb}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field input:focus{border-color:#00a0d2;box-shadow:0 0 0 1px #00a0d2;outline:2px solid transparent;outline-offset:-2px}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field .codeinwp-text-field-button-group{display:flex;align-items:center;margin:2px 0 15px}#codeinwp-awesome-plugin .codeinwp-main .components-panel__body .components-panel__row .components-base-control.codeinwp-text-field .components-base-control__field .codeinwp-text-field-button-group .is-primary{padding:2px 20px;height:auto;font-size:14px;margin-right:10px}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info{padding:0 10px 10px}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info h2{font-weight:300;margin-bottom:10px}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info p{margin:0 0 1.5em 0}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info .codeinwp-info-button-group{display:flex}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info .codeinwp-info-button-group .is-default{padding:2px 20px;height:auto;font-size:14px}#codeinwp-awesome-plugin .codeinwp-main .codeinwp-info .codeinwp-info-button-group .is-default:first-child{margin-right:15px} 2 | 3 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);n(1);function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t,n,o,r,a,i){try{var l=e[a](i),c=l.value}catch(e){return void n(e)}l.done?t(c):Promise.resolve(c).then(o,r)}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){for(var n=0;n'; 22 | } 23 | 24 | function codeinwp_add_option_menu() { 25 | $page_hook_suffix = add_options_page( 26 | __( 'Awesome Plugin', 'textdomain' ), 27 | __( 'Awesome Plugin', 'textdomain' ), 28 | 'manage_options', 29 | 'awesome', 30 | 'codeinwp_menu_callback' 31 | ); 32 | 33 | add_action( "admin_print_scripts-{$page_hook_suffix}", 'codeinwp_options_assets' ); 34 | } 35 | 36 | add_action( 'admin_menu', 'codeinwp_add_option_menu' ); 37 | 38 | function codeinwp_register_settings() { 39 | register_setting( 40 | 'codeinwp_settings', 41 | 'codeinwp_analytics_status', 42 | array( 43 | 'type' => 'boolean', 44 | 'show_in_rest' => true, 45 | 'default' => false, 46 | ) 47 | ); 48 | 49 | register_setting( 50 | 'codeinwp_settings', 51 | 'codeinwp_analytics_key', 52 | array( 53 | 'type' => 'string', 54 | 'show_in_rest' => true, 55 | ) 56 | ); 57 | } 58 | 59 | add_action( 'init', 'codeinwp_register_settings' ); 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-awesome-plugin", 3 | "version": "1.0.0", 4 | "description": "I build, therefore I'm awesome.", 5 | "scripts": { 6 | "build": "cross-env BABEL_ENV=default NODE_ENV=production webpack", 7 | "dev": "cross-env BABEL_ENV=default NODE_ENV=development webpack --watch", 8 | "lint": "eslint src/*.js" 9 | }, 10 | "engines": { 11 | "node": ">=8.0.0", 12 | "npm": ">=6.0.0" 13 | }, 14 | "devDependencies": { 15 | "@babel/core": "^7.1.6", 16 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0", 17 | "@babel/plugin-transform-async-to-generator": "^7.1.0", 18 | "@babel/plugin-transform-react-jsx": "^7.1.6", 19 | "@babel/preset-env": "^7.1.6", 20 | "autoprefixer": "^9.7.4", 21 | "babel-loader": "^8.0.4", 22 | "cross-env": "6.0.3", 23 | "css-loader": "^3.4.2", 24 | "eslint": "^5.7.0", 25 | "eslint-config-wordpress": "^2.0.0", 26 | "eslint-loader": "^2.1.1", 27 | "eslint-plugin-react": "^7.11.1", 28 | "mini-css-extract-plugin": "^0.9.0", 29 | "node-sass": "^4.13.1", 30 | "postcss-loader": "^3.0.0", 31 | "sass-loader": "^8.0.2", 32 | "webpack": "^4.25.1", 33 | "webpack-cli": "^3.1.2" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # My Awesome Plugin 2 | 3 | This is an example plugin to create options page in WordPress using components from Gutenberg. -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | /** 3 | * WordPress dependencies 4 | */ 5 | const { __ } = wp.i18n; 6 | 7 | const { 8 | BaseControl, 9 | Button, 10 | ExternalLink, 11 | PanelBody, 12 | PanelRow, 13 | Placeholder, 14 | Spinner, 15 | ToggleControl 16 | } = wp.components; 17 | 18 | const { 19 | render, 20 | Component, 21 | Fragment 22 | } = wp.element; 23 | 24 | /** 25 | * Internal dependencies 26 | */ 27 | import './style.scss'; 28 | 29 | class App extends Component { 30 | constructor() { 31 | super( ...arguments ); 32 | 33 | this.changeOptions = this.changeOptions.bind( this ); 34 | 35 | this.state = { 36 | isAPILoaded: false, 37 | isAPISaving: false, 38 | codeinwp_analytics_status: false, 39 | codeinwp_analytics_key: '' 40 | }; 41 | } 42 | 43 | componentDidMount() { 44 | wp.api.loadPromise.then( () => { 45 | this.settings = new wp.api.models.Settings(); 46 | 47 | if ( false === this.state.isAPILoaded ) { 48 | this.settings.fetch().then( response => { 49 | this.setState({ 50 | codeinwp_analytics_status: Boolean( response.codeinwp_analytics_status ), 51 | codeinwp_analytics_key: response.codeinwp_analytics_key, 52 | isAPILoaded: true 53 | }); 54 | }); 55 | } 56 | }); 57 | } 58 | 59 | changeOptions( option, value ) { 60 | this.setState({ isAPISaving: true }); 61 | 62 | const model = new wp.api.models.Settings({ 63 | // eslint-disable-next-line camelcase 64 | [option]: value 65 | }); 66 | 67 | model.save().then( response => { 68 | this.setState({ 69 | [option]: response[option], 70 | isAPISaving: false 71 | }); 72 | }); 73 | } 74 | 75 | render() { 76 | if ( ! this.state.isAPILoaded ) { 77 | return ( 78 | 79 | 80 | 81 | ); 82 | } 83 | 84 | return ( 85 | 86 |
87 |
88 |
89 |

{ __( 'My Awesome Plugin' ) }

90 |
91 |
92 |
93 | 94 |
95 | 98 | 99 | 105 | this.setState({ codeinwp_analytics_key: e.target.value }) } 112 | /> 113 | 114 |
115 | 123 | 124 | 125 | { __( 'Get API Key' ) } 126 | 127 |
128 |
129 |
130 | 131 | 132 | this.changeOptions( 'codeinwp_analytics_status', ! this.state.codeinwp_analytics_status ) } 137 | /> 138 | 139 |
140 | 141 | 142 |
143 |

{ __( 'Got a question for us?' ) }

144 | 145 |

{ __( 'We would love to help you out if you need any help.' ) }

146 | 147 |
148 | 156 | 157 | 165 |
166 |
167 |
168 |
169 |
170 | ); 171 | } 172 | } 173 | 174 | render( 175 | , 176 | document.getElementById( 'codeinwp-awesome-plugin' ) 177 | ); 178 | -------------------------------------------------------------------------------- /src/style.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: inherit; 3 | } 4 | 5 | .settings_page_awesome { 6 | background: #f6f6f6; 7 | font-size: 14px; 8 | position: relative; 9 | box-sizing: border-box; 10 | font-family: Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif; 11 | } 12 | 13 | #wpcontent { 14 | padding-left: 0; 15 | } 16 | 17 | .auto-fold { 18 | #wpcontent { 19 | padding-left: 0; 20 | } 21 | } 22 | 23 | #codeinwp-awesome-plugin { 24 | .components-placeholder { 25 | background: #f6f6f6; 26 | margin-top: 25vh; 27 | margin-bottom: 25vh; 28 | } 29 | 30 | .codeinwp-header { 31 | padding: 20px 10px; 32 | background-color: #ffffff; 33 | box-shadow: 0 1px 0 rgba(213,213,213,0.5),0 1px 2px #eee; 34 | 35 | .codeinwp-container { 36 | margin: 0 auto; 37 | max-width: 750px; 38 | 39 | .codeinwp-logo { 40 | display: flex; 41 | align-items: center; 42 | justify-content: center; 43 | } 44 | } 45 | } 46 | 47 | .codeinwp-main { 48 | margin-left: auto; 49 | margin-right: auto; 50 | max-width: 750px; 51 | 52 | .components-panel__body { 53 | margin: 25px 0; 54 | background: #fff; 55 | border: 1px solid #e2e4e7; 56 | 57 | .components-panel__body-toggle { 58 | border-bottom: 1px solid #d6e2ed; 59 | } 60 | 61 | .components-panel__row { 62 | padding: 10px; 63 | margin: 0; 64 | 65 | .components-base-control { 66 | .components-base-control__field { 67 | display: flex; 68 | align-items: center; 69 | margin-bottom: 10px; 70 | } 71 | 72 | &.codeinwp-text-field { 73 | width: 100%; 74 | 75 | .components-base-control__field { 76 | display: block; 77 | 78 | label { 79 | font-weight: 600; 80 | margin-bottom: 10px; 81 | } 82 | 83 | input { 84 | border: 1px solid #b7c9d9; 85 | border-radius: 3px; 86 | font-size: 14px; 87 | padding: 9px 15px; 88 | width: 100%; 89 | box-shadow: none; 90 | height: 40px; 91 | margin: 0 0 10px 0; 92 | color: #444; 93 | 94 | &:disabled { 95 | background: #f6f6f6; 96 | border-color: #eeeeee; 97 | color: #bbbbbb; 98 | } 99 | 100 | &:focus { 101 | border-color: #00a0d2; 102 | box-shadow: 0 0 0 1px #00a0d2; 103 | outline: 2px solid transparent; 104 | outline-offset: -2px; 105 | } 106 | } 107 | 108 | .codeinwp-text-field-button-group { 109 | display: flex; 110 | align-items: center; 111 | margin: 2px 0 15px; 112 | 113 | .is-primary { 114 | padding: 2px 20px; 115 | height: auto; 116 | font-size: 14px; 117 | margin-right: 10px; 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | } 125 | 126 | .codeinwp-info { 127 | padding: 0 10px 10px; 128 | 129 | h2 { 130 | font-weight: 300; 131 | margin-bottom: 10px; 132 | } 133 | 134 | p { 135 | margin: 0 0 1.5em 0; 136 | } 137 | 138 | .codeinwp-info-button-group { 139 | display: flex; 140 | 141 | .is-default { 142 | padding: 2px 20px; 143 | height: auto; 144 | font-size: 14px; 145 | 146 | &:first-child { 147 | margin-right: 15px; 148 | } 149 | } 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require( 'webpack' ); 2 | const NODE_ENV = process.env.NODE_ENV || 'development'; 3 | const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' ); 4 | 5 | module.exports = { 6 | mode: NODE_ENV, 7 | entry: './src/index.js', 8 | output: { 9 | path: __dirname, 10 | filename: './build/build.js' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /.js?$/, 16 | use: [ { 17 | loader: 'babel-loader', 18 | options: { 19 | presets: [ '@babel/preset-env' ], 20 | plugins: [ 21 | '@babel/plugin-transform-async-to-generator', 22 | '@babel/plugin-proposal-object-rest-spread', 23 | [ 24 | '@babel/plugin-transform-react-jsx', { 25 | 'pragma': 'wp.element.createElement' 26 | } 27 | ] 28 | ] 29 | } 30 | }, 31 | 'eslint-loader' ], 32 | exclude: /node_modules/ 33 | }, 34 | { 35 | test: /\.(css|scss)$/, 36 | use: [ { 37 | loader: MiniCssExtractPlugin.loader 38 | }, 39 | 'css-loader', 40 | { 41 | loader: 'postcss-loader', 42 | options: { 43 | plugins: [ 44 | require( 'autoprefixer' ) 45 | ] 46 | } 47 | }, 48 | 'sass-loader' ] 49 | } 50 | ] 51 | }, 52 | plugins: [ 53 | new webpack.DefinePlugin({ 54 | 'process.env.NODE_ENV': JSON.stringify( NODE_ENV ) 55 | }), 56 | new MiniCssExtractPlugin({ 57 | filename: './build/build.css' 58 | }) 59 | ] 60 | }; 61 | --------------------------------------------------------------------------------