From 562570e0bd40e77094e2ac1f323041b8fffba69a Mon Sep 17 00:00:00 2001 From: johnpercivalhackworth Date: Mon, 19 Jun 2017 12:45:04 +0200 Subject: [PATCH] Extensions: Build extensions for wp-admin plugins --- .gitignore | 2 + assets/stylesheets/_wpadmin-normalize.scss | 6 + assets/stylesheets/jetpack.scss | 64 +++ assets/stylesheets/shared/_normalize.scss | 447 ++++++++++++++++++ bin/copy-files.sh | 10 + client/boot/app.js | 4 + client/boot/project/jetpack.js | 109 +++++ client/extensions/test/controller.js | 31 ++ .../extensions/test/data/queryData/index.jsx | 27 ++ client/extensions/test/discussion/index.jsx | 25 + client/extensions/test/index.js | 15 + client/extensions/test/package.json | 15 + client/extensions/test/state/action-types.js | 3 + client/extensions/test/state/actions.js | 42 ++ client/extensions/test/state/reducer.js | 32 ++ client/extensions/test/state/selector.js | 8 + client/extensions/test/writing/index.jsx | 57 +++ client/jetpack.js | 13 + client/layout/logged-out.jsx | 6 +- config/jetpack.json | 103 ++++ package.json | 14 +- server/bundler/assets-jetpack.json | 16 + 22 files changed, 1042 insertions(+), 7 deletions(-) create mode 100644 assets/stylesheets/_wpadmin-normalize.scss create mode 100644 assets/stylesheets/jetpack.scss create mode 100644 assets/stylesheets/shared/_normalize.scss create mode 100755 bin/copy-files.sh create mode 100644 client/boot/project/jetpack.js create mode 100644 client/extensions/test/controller.js create mode 100644 client/extensions/test/data/queryData/index.jsx create mode 100644 client/extensions/test/discussion/index.jsx create mode 100644 client/extensions/test/index.js create mode 100644 client/extensions/test/package.json create mode 100644 client/extensions/test/state/action-types.js create mode 100644 client/extensions/test/state/actions.js create mode 100644 client/extensions/test/state/reducer.js create mode 100644 client/extensions/test/state/selector.js create mode 100644 client/extensions/test/writing/index.jsx create mode 100644 client/jetpack.js create mode 100644 config/jetpack.json create mode 100644 server/bundler/assets-jetpack.json diff --git a/.gitignore b/.gitignore index 04a32c2e9f169..143a33a7712e8 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,8 @@ env-config.sh /public/style*.css.map /public/editor*.css /public/directly*.css +/public/jetpack*.css +/public/jetpack*.css.map /public/images/flags/*.svg /public/images/flags/*.png /server/devdocs/search-index.js diff --git a/assets/stylesheets/_wpadmin-normalize.scss b/assets/stylesheets/_wpadmin-normalize.scss new file mode 100644 index 0000000000000..3a93d498407fe --- /dev/null +++ b/assets/stylesheets/_wpadmin-normalize.scss @@ -0,0 +1,6 @@ +.layout__content { + padding: 0; +} +.button { + height: auto; +} diff --git a/assets/stylesheets/jetpack.scss b/assets/stylesheets/jetpack.scss new file mode 100644 index 0000000000000..2a9b117f5e632 --- /dev/null +++ b/assets/stylesheets/jetpack.scss @@ -0,0 +1,64 @@ +// namespaceing breaks nested & selectors +// For example, in #wpcom wrapper: +// .foldable-card__content { +// display: none; +// .foldable-card.is-expanded & { +// display: block; +// } +// } +// +// produces +// +// #wpcom .foldable-card__content { +// display: none; +// } +// |------this is a problem +// vvvvvv +// .foldable-card.is-expanded #wpcom .foldable-card__content { +// display: block; +// } +// +// #wpcom { + @import 'shared/normalize'; + + // External Dependencies + @import 'vendor'; + + // Shared + @import 'shared/reset'; // css reset before the rest of the styles are defined + @import 'shared/functions'; // functions that we've used from Compass, ported over + @import 'shared/functions/functions'; // sass functions for z-index, etc. + @import 'shared/colors'; // import all of our wpcom colors + @import 'shared/utilities'; // Helper classes + @import 'shared/typography'; // all the typographic rules, variables, etc. + @import 'shared/mixins/mixins'; // sass mixins for gradients, bordius radii, etc. + @import 'shared/extends'; // sass extends for commonly used styles + @import 'shared/animation'; // all UI animation + @import 'shared/forms'; // form styling + @import 'shared/dropdowns'; // dropdown styling + @import 'shared/livechat'; // styles for the popup livechat box + @import 'shared/welcome'; // welcome messages + @import 'shared/infinite-scroll-end'; // Last page marker once infinite scroll has reached end + + // Main + @import 'main'; // global layout and responsive styles + + // Sections + @import 'sections/updated-confirmation'; // confirmation boxes for posts/pages + @import 'sections/notifications'; // notifications styles + @import 'sections/domain-search'; // Domain Search styles + + // Components + @import 'components'; + + // Extensions + @import 'extensions/woocommerce/style'; + @import 'extensions/wp-super-cache/style'; + + // Devdocs + @import 'devdocs/design/style'; + @import 'devdocs/design/syntax'; + + // WP Admin Environment + @import 'wpadmin-normalize'; +// } diff --git a/assets/stylesheets/shared/_normalize.scss b/assets/stylesheets/shared/_normalize.scss new file mode 100644 index 0000000000000..fa4e73dd418b8 --- /dev/null +++ b/assets/stylesheets/shared/_normalize.scss @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} diff --git a/bin/copy-files.sh b/bin/copy-files.sh new file mode 100755 index 0000000000000..83f3aaef68f5c --- /dev/null +++ b/bin/copy-files.sh @@ -0,0 +1,10 @@ +JETPACK_DIR="/home/javi/work/jetpackSandbox/wp-content/plugins/jetpack-ui" + +find ./public -iregex ".*manifest.*\.js" ! -iregex ".*\.m\.js" -exec mv {} $JETPACK_DIR/public/manifest.js \; +find ./public -iregex ".*build.*\.js" ! -iregex ".*\.m\.js" -exec mv {} $JETPACK_DIR/public/build.js \; +find ./public -iregex ".*vendor.*\.js" ! -iregex ".*\.m\.js" -exec mv {} $JETPACK_DIR/public/vendor.js \; +cp ./public/jetpack.css $JETPACK_DIR/public/ +cp ./public/jetpack-debug.css $JETPACK_DIR/public/ +cp ./public/jetpack-debug.css.map $JETPACK_DIR/public/ + +# npm run -s build-server && NODE_PATH=$NODE_PATH:server:client:. CALYPSO_ENV=jetpack node server/bundler/bin/bundler.js && ./bin/copy-files.sh diff --git a/client/boot/app.js b/client/boot/app.js index 79351545b37dc..19c22bd63babc 100644 --- a/client/boot/app.js +++ b/client/boot/app.js @@ -53,4 +53,8 @@ window.AppBoot = () => { } else { user.once( 'change', () => boot( user ) ); } + // @todo Can we get a wp-defined user...? + if ( 'jetpack' === PROJECT_NAME ) { + boot( user ); + } }; diff --git a/client/boot/project/jetpack.js b/client/boot/project/jetpack.js new file mode 100644 index 0000000000000..9b97ff577365b --- /dev/null +++ b/client/boot/project/jetpack.js @@ -0,0 +1,109 @@ +/** + * External dependencies + */ +const React = require( 'react' ), + ReactDom = require( 'react-dom' ), + store = require( 'store' ), + debug = require( 'debug' )( 'calypso' ), + page = require( 'page' ), + includes = require( 'lodash/includes' ); + +/** + * Internal dependencies + */ +const config = require( 'config' ), + normalize = require( 'lib/route/normalize' ), + { isLegacyRoute } = require( 'lib/route/legacy-routes' ); + +import { getSectionName } from 'state/ui/selectors'; + +function renderLayout( reduxStore ) { + const Layout = require( 'controller' ).ReduxWrappedLayout; + + const layoutElement = React.createElement( Layout, { + store: reduxStore + } ); + + ReactDom.render( + layoutElement, + document.getElementById( 'wpcom' ) + ); + + debug( 'Main layout rendered.' ); +} + +export function utils() { + debug( 'Executing Jetpack utils.' ); +} + +export const configureReduxStore = ( currentUser, reduxStore ) => { + debug( 'Executing Jetpack configure Redux store.' ); +}; + +export function setupMiddlewares( currentUser, reduxStore ) { + debug( 'Executing Jetpack setup middlewares.' ); + + // Render Layout only for non-isomorphic sections. + // Isomorphic sections will take care of rendering their Layout last themselves. + if ( ! document.getElementById( 'primary' ) ) { + renderLayout( reduxStore ); + } + + page( '*', function( context, next ) { + // Don't normalize legacy routes - let them fall through and be unhandled + // so that page redirects away from Calypso + if ( isLegacyRoute( context.pathname ) ) { + return next(); + } + + return normalize( context, next ); + } ); + + page( '*', function( context, next ) { + const path = context.pathname; + + // Bypass this global handler for legacy routes + // to avoid bumping stats and changing focus to the content + if ( isLegacyRoute( path ) ) { + return next(); + } + + next(); + } ); + + require( 'my-sites' )(); + + /* + * Layouts with differing React mount-points will not reconcile correctly, + * so remove an existing single-tree layout by re-rendering if necessary. + * + * TODO (@seear): Converting all of Calypso to single-tree layout will + * make this unnecessary. + */ + page( '*', function( context, next ) { + const previousLayoutIsSingleTree = !! ( + document.getElementsByClassName( 'wp-singletree-layout' ).length + ); + + const singleTreeSections = [ 'account-recovery', 'login', 'posts-custom', 'theme', 'themes', 'preview' ]; + const sectionName = getSectionName( context.store.getState() ); + const isMultiTreeLayout = ! includes( singleTreeSections, sectionName ); + + if ( isMultiTreeLayout && previousLayoutIsSingleTree ) { + debug( 'Re-rendering multi-tree layout' ); + ReactDom.unmountComponentAtNode( document.getElementById( 'wpcom' ) ); + renderLayout( context.store ); + } else if ( ! isMultiTreeLayout && ! previousLayoutIsSingleTree ) { + debug( 'Unmounting multi-tree layout' ); + ReactDom.unmountComponentAtNode( document.getElementById( 'primary' ) ); + ReactDom.unmountComponentAtNode( document.getElementById( 'secondary' ) ); + } + next(); + } ); + + page.start( { + hashbang: true, + decodeURLComponents: false, + } ); + page.base( window.pageBase ); +} diff --git a/client/extensions/test/controller.js b/client/extensions/test/controller.js new file mode 100644 index 0000000000000..d64d70bc11d23 --- /dev/null +++ b/client/extensions/test/controller.js @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import React from 'react'; +import page from 'page'; + +/** + * Internal dependencies + */ +import WritingSettings from './writing'; +import DiscussionSettings from './discussion'; +import { renderPage } from 'lib/react-helpers'; + +const loadPage = ( path ) => { + return () => page( path ); +}; + +const jetpackUi = { + + // Writing Settings + writingSettings( context ) { + renderPage( context, React.createElement( WritingSettings, { loadPage } ) ); + }, + + // Discussion Settings + discussionSettings( context ) { + renderPage( context, React.createElement( DiscussionSettings, { loadPage } ) ); + }, +}; + +module.exports = jetpackUi; diff --git a/client/extensions/test/data/queryData/index.jsx b/client/extensions/test/data/queryData/index.jsx new file mode 100644 index 0000000000000..f0cc2d0d97766 --- /dev/null +++ b/client/extensions/test/data/queryData/index.jsx @@ -0,0 +1,27 @@ +/** + * External dependencies + */ +import { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; + +/** + * Internal dependencies + */ +import { requestData } from '../../state/actions'; + +class QueryData extends Component { + componentWillMount() { + this.props.requestData( this.props.siteId ); + } + + render() { + return null; + } +} + +export default connect( + ( state, { siteId } ) => { + return {}; + }, + { requestData } +)( QueryData ); diff --git a/client/extensions/test/discussion/index.jsx b/client/extensions/test/discussion/index.jsx new file mode 100644 index 0000000000000..5b9439e66705f --- /dev/null +++ b/client/extensions/test/discussion/index.jsx @@ -0,0 +1,25 @@ +/** + * External dependencies + */ +import React, { PureComponent } from 'react'; + +/** + * Internal dependencies + */ +import Main from 'components/main'; +import Button from 'components/button'; +import Card from 'components/card'; + +export default class JetpackDiscussion extends PureComponent { + render() { + return ( +
+ +

Discussion

+

Settings, or something, would go here.

+ +
+
+ ); + } +} diff --git a/client/extensions/test/index.js b/client/extensions/test/index.js new file mode 100644 index 0000000000000..f8a526802386a --- /dev/null +++ b/client/extensions/test/index.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import page from 'page'; + +/** + * Internal dependencies + */ +import controller from './controller'; + +export default function() { + page( '/test/writing', controller.writingSettings ); + page( '/test/discussion', controller.discussionSettings ); + page( '/test/', controller.writingSettings ); +} diff --git a/client/extensions/test/package.json b/client/extensions/test/package.json new file mode 100644 index 0000000000000..cfe6fdace9248 --- /dev/null +++ b/client/extensions/test/package.json @@ -0,0 +1,15 @@ +{ + "name": "test", + "author": "Automattic", + "description": "Test", + "version": "0.0.1", + "env_id": [ "development", "wpcalypso", "jetpack" ], + "section": { + "name": "test", + "paths": [ "/test" ], + "module": "test", + "group": "jetpack", + "enableLoggedOut": true, + "secondary": false + } +} diff --git a/client/extensions/test/state/action-types.js b/client/extensions/test/state/action-types.js new file mode 100644 index 0000000000000..1845de13fa282 --- /dev/null +++ b/client/extensions/test/state/action-types.js @@ -0,0 +1,3 @@ +export const TEST_EXTENSION_FETCH = 'TEST_EXTENSION_FETCH'; +export const TEST_EXTENSION_FETCH_FAILURE = 'TEST_EXTENSION_FETCH_FAILURE'; +export const TEST_EXTENSION_FETCH_SUCCESS = 'TEST_EXTENSION_FETCH_SUCCESS'; diff --git a/client/extensions/test/state/actions.js b/client/extensions/test/state/actions.js new file mode 100644 index 0000000000000..6c929f28234be --- /dev/null +++ b/client/extensions/test/state/actions.js @@ -0,0 +1,42 @@ +/** + * External dependencies + */ +import request from 'superagent'; + +/** + * Internal dependencies + */ +import wp from 'lib/wp'; +import { + TEST_EXTENSION_FETCH, + TEST_EXTENSION_FETCH_FAILURE, + TEST_EXTENSION_FETCH_SUCCESS +} from './action-types'; +import config from 'config'; + +const weAreNotInCalypsoAnymore = config( 'env' ) === 'jetpack'; + +export const requestData = ( siteId ) => { + return ( dispatch ) => { + dispatch( { + type: TEST_EXTENSION_FETCH, + siteId, + } ); + if ( weAreNotInCalypsoAnymore ) { + const url = '/wp-json/jetpack/v4/settings/'; + + return request + .get( url ) + .set( 'X-WP-Nonce', window.WP_API_nonce ) + .end( ( error, res ) => { + if ( error ) { + return dispatch( { type: TEST_EXTENSION_FETCH_FAILURE } ); + } + return dispatch( { type: TEST_EXTENSION_FETCH_SUCCESS, siteId, data: res.body } ); + } ); + } + return wp.req.get( { path: '/jetpack-blogs/' + siteId + '/rest-api/' }, { path: '/jetpack/v4/settings/' } ) + .then( ( { data } ) => dispatch( { type: TEST_EXTENSION_FETCH_SUCCESS, siteId, data } ) ) + .catch( () => dispatch( { type: TEST_EXTENSION_FETCH_FAILURE } ) ); + }; +}; diff --git a/client/extensions/test/state/reducer.js b/client/extensions/test/state/reducer.js new file mode 100644 index 0000000000000..4ea07ec85a9fc --- /dev/null +++ b/client/extensions/test/state/reducer.js @@ -0,0 +1,32 @@ +/** + * Internal dependencies + */ +import { combineReducers, createReducer } from 'state/utils'; + +import { + TEST_EXTENSION_FETCH, + TEST_EXTENSION_FETCH_SUCCESS +} from './action-types'; + +const testExtension = createReducer( {}, { + [ TEST_EXTENSION_FETCH ]: ( state, { siteId } ) => ( { + ...state, + [ siteId ]: { + fetching: true, + status: 'pending', + } + } ), + [ TEST_EXTENSION_FETCH_SUCCESS ]: ( state, { siteId, data } ) => ( { + ...state, + [ siteId ]: { + fetching: false, + status: 'loaded', + data + } + } ), + +} ); + +export default combineReducers( { + testExtension, +} ); diff --git a/client/extensions/test/state/selector.js b/client/extensions/test/state/selector.js new file mode 100644 index 0000000000000..78877aba2de61 --- /dev/null +++ b/client/extensions/test/state/selector.js @@ -0,0 +1,8 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; + +export function getData( state, siteId ) { + return get( state, [ 'extensions', 'test', 'testExtension', siteId, 'data' ], {} ); +} diff --git a/client/extensions/test/writing/index.jsx b/client/extensions/test/writing/index.jsx new file mode 100644 index 0000000000000..9919f58bad3b7 --- /dev/null +++ b/client/extensions/test/writing/index.jsx @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; + +/** + * Internal dependencies + */ +import Main from 'components/main'; +import Button from 'components/button'; +import Card from 'components/card'; +import Banner from 'components/banner'; +import FoldableCard from 'components/foldable-card'; +import QueryData from '../data/queryData'; +import { getData } from '../state/selector'; +import FormToggle from 'components/forms/form-toggle'; + +class JetpackWriting extends Component { + render() { + return ( +
+ + Bias Language + + + Passive voice + + + Phrases to Avoid + + +