Changeset 5024
- Timestamp:
- 03/01/2017 06:08:54 PM (8 years ago)
- Location:
- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins
- Files:
-
- 39 added
- 17 deleted
- 63 edited
- 8 copied
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/.babelrc
r4223 r5024 1 1 { 2 "presets": ["es2015", "react"] 2 "plugins": [ 3 [ "transform-imports", { 4 "lodash": { 5 "transform": "lodash/${member}", 6 "preventFullImport": true 7 }, 8 "state/selectors": { 9 "transform": "state/selectors/${member}", 10 "kebabCase": true 11 } 12 }] 13 ], 14 "presets": ["es2015", "react", "stage-2"] 3 15 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/Gruntfile.js
r4465 r5024 58 58 } 59 59 }, 60 jshint: {60 eslint: { 61 61 files: [ 62 'Gruntfile.js',63 'js/**/*.js',64 62 'client/**/*.js', 65 '!js/theme.js' 66 ], 67 options: grunt.file.readJSON('.jshintrc') 63 'client/**/*.jsx', 64 65 // External library. For now. 66 '!client/**/**/image-gallery/index.jsx' 67 ] 68 68 }, 69 69 sass: { … … 85 85 }, 86 86 options: { signature: false } 87 }, 88 shell: { 89 build: { 90 command: './node_modules/wpapi/lib/data/update-default-routes-json.js --endpoint=https://wordpress.org/plugins-wp/wp-json --output=./client' 91 } 87 92 }, 88 93 rtlcss: { … … 148 153 }, 149 154 watch: { 150 jshint: {151 files: ['<%= jshint.files %>'],152 tasks: [' jshint']155 eslint: { 156 files: ['<%= eslint.files %>'], 157 tasks: ['eslint'] 153 158 }, 154 159 css: { … … 162 167 grunt.loadNpmTasks('grunt-rtlcss'); 163 168 grunt.loadNpmTasks('grunt-webpack'); 164 grunt.loadNpmTasks('grunt- contrib-jshint');169 grunt.loadNpmTasks('grunt-eslint'); 165 170 grunt.loadNpmTasks('grunt-contrib-watch'); 166 171 grunt.loadNpmTasks('grunt-sass-globbing'); 172 grunt.loadNpmTasks('grunt-shell'); 167 173 168 grunt.registerTask('default', [' jshint', 'sass_globbing', 'sass', 'rtlcss:dynamic']);174 grunt.registerTask('default', ['eslint', 'sass_globbing', 'sass', 'rtlcss:dynamic']); 169 175 grunt.registerTask('css', ['sass_globbing', 'sass', 'postcss', 'rtlcss:dynamic']); 170 grunt.registerTask('build', ['webpack:build', 'css' ]);176 grunt.registerTask('build', ['webpack:build', 'css', 'shell:build']); 171 177 }; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/404/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { identity } from 'lodash'; 2 6 import { IndexLink } from 'react-router'; 7 import { localize } from 'i18n-calypso'; 3 8 4 export default React.createClass( { 5 displayName: 'NotFound', 9 export class NotFound extends Component { 10 static propTypes = { 11 translate: PropTypes.func, 12 }; 13 14 static defaultProps = { 15 translate: identity, 16 }; 6 17 7 18 componentDidMount() { 8 setTimeout( function() { 9 jQuery( '.hinge' ).hide(); 10 }, 1800 ); 11 }, 19 setTimeout( () => jQuery( '.hinge' ).hide(), 1800 ); 20 } 12 21 13 22 render() { … … 15 24 <section className="error-404 not-found"> 16 25 <header className="page-header"> 17 <h1 className="page-title"> Oops! That page can’t be found.</h1>26 <h1 className="page-title">{ this.props.translate( 'Oops! That page can’t be found.' ) }</h1> 18 27 </header> 19 28 <div className="page-content"> 20 <p>Try searching from the field above, or go to the <IndexLink to="/">home page</IndexLink>.</p> 29 <p> 30 { this.props.translate( 31 'Try searching from the field above, or go to the {{link}}home page{{/link}}.', { 32 component: { link: <IndexLink to="/" /> }, 33 } 34 ) } 35 </p> 21 36 22 37 <div className="logo-swing"> … … 26 41 </div> 27 42 </section> 28 ) 43 ); 29 44 } 30 } );45 } 31 46 32 47 export default localize( NotFound ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/archive/browse/browse.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 9 /** 10 * Internal dependencies. 11 */ 3 12 import ContentNone from 'components/content-none'; 13 import { getSection, getSectionPlugins } from 'state/selectors'; 14 import Pagination from 'components/pagination'; 4 15 import PluginCard from 'components/plugin-card'; 5 16 6 export default React.createClass( { 7 displayName: 'ArchiveBrowse', 17 export const ArchiveBrowse = ( { plugins, section, translate } ) => { 18 if ( plugins && plugins.length ) { 19 return ( 20 <div> 21 <header className="page-header"> 22 <h1 className="page-title"> 23 { translate( 'Browse: {{strong}}%(name)s{{/strong}}', { 24 args: { name: section.name }, 25 components: { strong: <strong /> }, 26 } ) } 27 </h1> 28 { section.description && 29 <div className="taxonomy-description">{ section.description }</div> 30 } 31 </header> 32 { plugins.map( ( plugin ) => <PluginCard key={ plugin.id } plugin={ plugin } /> ) } 33 <Pagination current={ 12 } total={ 30 } /> 34 </div> 35 ); 36 } 8 37 9 render() { 10 if ( this.props.plugins && this.props.plugins.length ) { 11 return ( 12 <div> 13 <header className="page-header"> 14 <h1 className="page-title">Browse: <strong>{ this.props.params.type }</strong></h1> 15 <div className="taxonomy-description"></div> 16 </header> 17 { this.props.plugins.map( slug => 18 <PluginCard key={ slug } slug={ slug } /> 19 ) } 20 </div> 21 ) 22 } 38 return <ContentNone />; 39 }; 23 40 24 return <ContentNone { ...this.props } />; 25 } 26 } ); 41 ArchiveBrowse.propTypes = { 42 plugins: PropTypes.arrayOf( PropTypes.object ), 43 section: PropTypes.object, 44 translate: PropTypes.func, 45 type: PropTypes.string.isRequired, 46 }; 47 48 ArchiveBrowse.defaultProps = { 49 plugins: [], 50 section: {}, 51 translate: identity, 52 }; 53 54 export default connect( 55 ( state, { type } ) => ( { 56 plugins: getSectionPlugins( state, type ), 57 section: getSection( state, type ), 58 } ), 59 )( localize( ArchiveBrowse ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/archive/browse/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 6 4 import { getBrowse } from 'actions'; 7 /** 8 * Internal dependencies. 9 */ 10 import { fetchSection, fetchSections } from 'state/sections/actions'; 11 import { getSection } from 'state/selectors'; 5 12 import Browse from './browse'; 6 13 7 const BrowseContainer = React.createClass( { 14 export class BrowseContainer extends Component { 15 static propTypes = { 16 fetchSection: PropTypes.func, 17 params: PropTypes.object, 18 }; 19 20 static defaultProps = { 21 fetchSection: () => {}, 22 params: {}, 23 }; 24 8 25 componentDidMount() { 9 this. getBrowse();10 } ,26 this.fetchSection(); 27 } 11 28 12 componentDidUpdate( previousProps) {13 if ( this.props.params.type !== p reviousProps.params.type ) {14 this. getBrowse();29 componentDidUpdate( { params } ) { 30 if ( this.props.params.type !== params.type ) { 31 this.fetchSection(); 15 32 } 16 } ,33 } 17 34 18 getBrowse() { 19 this.props.dispatch( getBrowse( this.props.params.type ) ); 20 }, 35 fetchSection() { 36 if ( ! this.props.section ) { 37 this.props.fetchSections(); 38 } 39 this.props.fetchSection( this.props.params.type ); 40 } 21 41 22 42 render() { 23 return <Browse { ...this.props} />;43 return <Browse type={ this.props.params.type } />; 24 44 } 25 } );45 } 26 46 27 const mapStateToProps = ( state, ownProps ) => ( { 28 plugins: state.browse[ ownProps.params.type ] 29 } ); 30 31 export default connect( mapStateToProps )( BrowseContainer ); 32 33 47 export default connect( 48 ( state, { params } ) => ( { 49 section: getSection( state, params.type ), 50 } ), 51 { 52 fetchSection, 53 fetchSections, 54 }, 55 )( BrowseContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/content-none/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 3 9 /** 4 10 * Internal dependencies. 5 11 */ 12 import { getParams, getPath } from 'state/selectors'; 6 13 import SearchForm from 'components/search-form'; 7 14 8 export default React.createClass({9 displayName: 'ContentNone',15 export const ContentNone = ( { params, path, translate } ) => { 16 let helpText, userHelp; 10 17 11 render() { 12 let helpText, userHelp; 18 if ( -1 !== path.indexOf( 'search' ) ) { 19 helpText = ( 20 <div className="page-content"> 21 <p>{ translate( 'Sorry, but nothing matched your search terms.' ) }</p> 22 <p>{ translate( 'Please try again with some different keywords.' ) }</p> 23 <SearchForm /> 24 </div> 25 ); 26 } else if ( -1 !== path.indexOf( 'browse/favorites' ) ) { 27 if ( pluginDirectory.userId > 0 ) { 28 helpText = <p>{ translate( 'No favorites have been added, yet.' ) }</p>; 13 29 14 if ( -1 !== this.props.location.pathname.indexOf( 'search' ) ) { 15 helpText = ( 16 <div className="page-content"> 17 <p>Sorry, but nothing matched your search terms.</p> 18 <p>Please try again with some different keywords.</p> 19 <SearchForm searchTerm={ this.props.params.searchTerm } /> 20 </div> 21 ); 22 23 } else if ( -1 !== this.props.location.pathname.indexOf( 'browse/favorites' ) ) { 24 if ( true /*user_logged_in*/ ) { 25 helpText = <p>No favorites have been added, yet.</p>; 26 27 if ( -1 !== this.props.location.pathname.indexOf( 'browse/favorites/' + this.props.params.username ) ) { 28 userHelp = ( 29 <div> 30 <p>Find a plugin and mark it as a favorite to see it here.</p> 31 <p>Your favorite plugins are also shared on <a href={ 'https://profile.wordpress.org/' + this.props.params.username }>your profile</a></p> 32 </div> 33 ); 34 } 35 36 helpText = <div className="page-content">{ helpText }{ userHelp }</div>; 37 } else { 38 helpText = ( 39 <div className="page-content"> 40 <p><a href="https://login.wordpress.org/">Loginto WordPress.org</a> to mark plugins as favorites.</p> 30 if ( -1 !== path.indexOf( 'browse/favorites/' + params.username ) ) { 31 userHelp = ( 32 <div> 33 <p>{ translate( 'Find a plugin and mark it as a favorite to see it here.' ) }</p> 34 <p> 35 { translate( 'Your favorite plugins are also shared on {{a}}your profile{{/a}}', { 36 components: { a: <a href={ 'https://profile.wordpress.org/' + params.username } /> }, 37 } ) } 38 </p> 41 39 </div> 42 40 ); 43 41 } 42 43 helpText = <div className="page-content">{ helpText }{ userHelp }</div>; 44 44 } else { 45 45 helpText = ( 46 46 <div className="page-content"> 47 <p>It seems we can’t find what you’re looking for. Perhaps searching can help.</p> 47 <p> 48 { translate( '{{a}}Log into WordPress.org{{/a}} to mark plugins as favorites.', { 49 components: { a: <a href="https://login.wordpress.org/" /> }, 50 } ) } 51 </p> 48 52 </div> 49 53 ); 54 } 55 } else { 56 helpText = ( 57 <div className="page-content"> 58 <div className="page-content"> 59 <p> 60 { translate( 61 'It seems we can’t find what you’re looking for. Perhaps searching can help.' 62 ) } 63 </p> 64 </div> 65 <SearchForm /> 66 </div> 67 ); 68 } 50 69 51 helpText = ( 52 <div className="page-content"> 53 { helpText } 54 <SearchForm searchTerm={ this.props.params.searchTerm } /> 55 </div> 56 ); 70 return ( 71 <section className="no-results not-found"> 72 <header className="page-header"> 73 <h1 className="page-title">{ translate( 'Nothing Found' ) }</h1> 74 </header> 75 { helpText } 76 </section> 77 ); 78 }; 57 79 58 } 80 ContentNone.propTypes = { 81 params: PropTypes.object, 82 path: PropTypes.string, 83 translate: PropTypes.func, 84 }; 59 85 60 return ( 61 <section className="no-results not-found"> 62 <header className="page-header"> 63 <h1 className="page-title">Nothing Found</h1> 64 </header> 65 { helpText } 66 </section> 67 ) 68 } 69 } ); 86 ContentNone.defaultProps = { 87 params: {}, 88 path: '', 89 translate: identity, 90 }; 91 92 export default connect( 93 ( state ) => ( { 94 params: getParams( state ), 95 path: getPath( state ), 96 } ), 97 )( localize( ContentNone ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/front-page/index.js
r4223 r5024 1 import { connect } from 'react-redux'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 8 /** 4 9 * Internal dependencies. 5 10 */ 6 import FrontPage from './front-page';11 import PluginSection from './plugin-section'; 7 12 8 const mapStateToProps = () => ( { 9 sections: [ 10 { 11 path: 'browse/featured/', 12 title: 'Featured Plugins', 13 type: 'featured' 14 }, 15 { 16 path: 'browse/popular/', 17 title: 'Popular Plugins', 18 type: 'popular' 19 }, 20 { 21 path: 'browse/beta/', 22 title: 'Beta Plugins', 23 type: 'beta' 24 } 25 ] 26 } ); 13 const FrontPage = ( { sections } ) => ( 14 <div> 15 { sections.map( ( type ) => <PluginSection key={ type } type={ type } /> ) } 16 </div> 17 ); 27 18 28 export default connect( mapStateToProps )( FrontPage ); 19 FrontPage.propTypes = { 20 sections: PropTypes.arrayOf( PropTypes.string ), 21 translate: PropTypes.func, 22 }; 23 24 FrontPage.defaultProps = { 25 sections: [ 'featured', 'popular', 'beta' ], 26 translate: identity, 27 }; 28 29 export default localize( FrontPage ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/front-page/plugin-section/index.jsx
r4223 r5024 1 import React, { Component } from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 6 … … 5 8 * Internal dependencies. 6 9 */ 7 import { getBrowse } from 'actions';10 import { fetchSection, fetchSections } from 'state/sections/actions'; 8 11 import PluginSection from './plugin-section'; 9 12 10 13 class PluginSectionContainer extends Component { 14 static propTypes = { 15 fetchSection: PropTypes.func, 16 type: PropTypes.string.isRequired, 17 }; 18 19 static defaultProps = { 20 fetchBrowse: () => {}, 21 }; 22 11 23 componentDidMount() { 12 this.getBrowse(); 24 this.props.fetchSections(); 25 this.fetchSection(); 13 26 } 14 27 15 componentDidUpdate( previousProps) {16 if ( this.props. section.type !== previousProps.section.type ) {17 this. getBrowse();28 componentDidUpdate( { type } ) { 29 if ( this.props.type !== type ) { 30 this.fetchSection(); 18 31 } 19 32 } 20 33 21 getBrowse() {22 this.props. dispatch( getBrowse( this.props.section.type ));34 fetchSection() { 35 this.props.fetchSection( this.props.type ); 23 36 } 24 37 25 38 render() { 26 return <PluginSection { ...this.props} />;39 return <PluginSection type={ this.props.type } />; 27 40 } 28 41 } 29 42 30 const mapStateToProps = ( state, ownProps ) => ( { 31 plugins: state.browse[ ownProps.section.type ].slice( 0, 4 ) 32 } ); 33 34 export default connect( mapStateToProps )( PluginSectionContainer ); 43 export default connect( 44 null, 45 { 46 fetchSection, 47 fetchSections, 48 }, 49 )( PluginSectionContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/front-page/plugin-section/plugin-section.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 2 7 import { Link } from 'react-router'; 8 import { localize } from 'i18n-calypso'; 3 9 4 10 /** 5 11 * Internal dependencies. 6 12 */ 13 import { getSection, getSectionPlugins } from 'state/selectors'; 7 14 import PluginCard from 'components/plugin-card'; 8 15 9 export default React.createClass( { 10 displayName: 'PluginSection', 11 12 render() { 13 if ( ! this.props.plugins ) { 14 return <div />; 15 } 16 16 /** 17 * 18 * @param {Array} plugins Plugins 19 * @param {Object} section Section 20 * @param {Function} translate Translation function 21 * @return {(XML|null)} Component or null. 22 * @constructor 23 */ 24 export const PluginSection = ( { plugins, section, translate } ) => { 25 if ( plugins ) { 17 26 return ( 18 27 <section className="plugin-section"> 19 28 <header className="section-header"> 20 <h2 className="section-title">{ this.props.section.title }</h2>21 <Link className="section-link" to={ this.props.section.path }>See all</Link>29 <h2 className="section-title">{ section.name }</h2> 30 <Link className="section-link" to={ `/browse/${ section.slug }/` }>{ translate( 'See all' ) }</Link> 22 31 </header> 23 { this.props.plugins.map( slug => 24 <PluginCard key={ slug } slug={ slug } /> 25 ) } 32 { plugins.map( ( plugin ) => <PluginCard key={ plugin.id } plugin={ plugin } /> ) } 26 33 </section> 27 ) 34 ); 28 35 } 29 } ); 36 37 return null; 38 }; 39 40 PluginSection.propTypes = { 41 plugins: PropTypes.array, 42 section: PropTypes.object, 43 translate: PropTypes.func, 44 }; 45 46 PluginSection.defaultProps = { 47 plugins: [], 48 section: {}, 49 translate: identity, 50 }; 51 52 export default connect( 53 ( state, { type } ) => ( { 54 plugins: getSectionPlugins( state, type ).slice( 0, 4 ), 55 section: getSection( state, type ), 56 } ), 57 )( localize( PluginSection ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/index.js
r4223 r5024 1 /** 2 * External dependencies. 3 */ 1 4 import { connect } from 'react-redux'; 2 5 import { withRouter } from 'react-router'; 6 import { localize } from 'i18n-calypso'; 3 7 8 /** 9 * Internal dependencies. 10 */ 4 11 import PluginDirectory from './plugin-directory'; 5 12 6 const mapStateToProps = () => ( { 7 widgets: [ 8 { 9 title: 'Add Your Plugin', 10 text: 'The WordPress Plugin Directory is the largest directory of free and open source WordPress plugins. Find out how to host your plugin on WordPress.org.' 11 }, 12 { 13 title: 'Create a Plugin', 14 text: 'Building a plugin has never been easier. Read through the Plugin Developer Handbook to learn all about WordPress plugin development.' 15 }, 16 { 17 title: 'Stay Up-to-Date', 18 text: 'Plugin development is constantly changing with each new WordPress release. Keep up with the latest changes by following the Plugin Review Team’s blog.' 19 }, 20 ] 21 } ); 22 23 export default withRouter( connect( mapStateToProps )( PluginDirectory ) ); 13 export default withRouter( localize( connect( 14 ( state, { translate } ) => ( { 15 widgets: [ 16 /* eslint-disable max-len */ 17 { 18 title: translate( 'Add Your Plugin' ), 19 text: translate( 'The WordPress Plugin Directory is the largest directory of free and open source WordPress plugins. Find out how to host your plugin on WordPress.org.' ), 20 }, 21 { 22 title: translate( 'Create a Plugin' ), 23 text: translate( 'Building a plugin has never been easier. Read through the Plugin Developer Handbook to learn all about WordPress plugin development.' ), 24 }, 25 { 26 title: translate( 'Stay Up-to-Date' ), 27 text: translate( 'Plugin development is constantly changing with each new WordPress release. Keep up with the latest changes by following the Plugin Review Team’s blog.' ), 28 }, 29 /* eslint-enable max-len */ 30 ], 31 } ), 32 )( PluginDirectory ) ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/page/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 import find from 'lodash/find';4 6 5 7 /** … … 7 9 */ 8 10 import Page from './page'; 9 import { getPage } from 'actions';11 import { fetchPage } from 'state/pages/actions'; 10 12 11 const PageContainer = React.createClass( { 13 class PageContainer extends Component { 14 static propTypes = { 15 fetchPage: PropTypes.func, 16 route: PropTypes.object.isRequired, 17 }; 18 19 static defaultProps = { 20 fetchPage: () => {}, 21 }; 22 12 23 componentDidMount() { 13 this. getPage();14 } ,24 this.fetchPage(); 25 } 15 26 16 componentDidUpdate( previousProps) {17 if ( this.props.route.path !== previousProps.route.path ) {18 this. getPage();27 componentDidUpdate( { route } ) { 28 if ( this.props.route.path !== route.path ) { 29 this.fetchPage(); 19 30 } 20 } ,31 } 21 32 22 getPage() {23 this.props. dispatch( getPage( this.props.route.path ));24 } ,33 fetchPage() { 34 this.props.fetchPage( this.props.route.path ); 35 } 25 36 26 37 render() { 27 return <Page { ...this.props }/>;38 return <Page />; 28 39 } 29 } );40 } 30 41 31 const mapStateToProps = ( state, ownProps ) => ( { 32 page: find( state.pages, { slug: ownProps.route.path } ) 33 } ); 34 35 export default connect( mapStateToProps )( PageContainer ); 42 export default connect( 43 null, 44 { 45 fetchPage, 46 } 47 )( PageContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/page/page.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 2 6 3 export default React.createClass( { 4 displayName: 'Page', 7 /** 8 * Internal dependencies. 9 */ 10 import { getPage } from 'state/selectors'; 5 11 6 render() { 7 if ( ! this.props.page ) { 8 return ( 9 <article className="page type-page"> 10 <header className="entry-header"> 11 <h1 className="entry-title"> </h1> 12 </header> 13 <div className="entry-content"> 14 <section> 15 <div className="container"> LOADING </div> 16 </section> 17 </div> 18 </article> 19 ) 20 } 21 12 const Page = ( { page } ) => { 13 if ( page && page.title ) { 22 14 return ( 23 15 <article className="page type-page"> 24 16 <header className="entry-header"> 25 <h1 className="entry-title">{ this.props.page.title.rendered }</h1>17 <h1 className="entry-title">{ page.title.rendered }</h1> 26 18 </header> 27 19 <div className="entry-content"> 28 20 <section> 29 <div className="container" dangerouslySetInnerHTML={ { __html: this.props.page.content.rendered } } />21 <div className="container" dangerouslySetInnerHTML={ { __html: page.content.rendered } } /> 30 22 </section> 31 23 </div> 32 24 </article> 33 ) 25 ); 34 26 } 35 } ); 27 28 return ( 29 <article className="page type-page"> 30 <header className="entry-header"> 31 <h1 className="entry-title"> </h1> 32 </header> 33 <div className="entry-content"> 34 <section> 35 <div className="container"> LOADING </div> 36 </section> 37 </div> 38 </article> 39 ); 40 }; 41 42 Page.propTypes = { 43 page: PropTypes.object, 44 }; 45 46 Page.defaultProps = { 47 page: {}, 48 }; 49 50 export default connect( 51 ( state ) => ( { 52 page: getPage( state ), 53 } ), 54 )( Page ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-card/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 import find from 'lodash/find';4 6 5 7 /** … … 7 9 */ 8 10 import PluginCard from './plugin-card'; 9 import { getPlugin } from 'actions'; 11 import { fetchPlugin } from 'state/plugins/actions'; 12 import { getPlugin } from 'state/selectors'; 10 13 11 const PluginCardContainer = React.createClass( { 14 export class PluginCardContainer extends Component { 15 static propTypes = { 16 fetchPlugin: PropTypes.func, 17 plugin: PropTypes.object, 18 slug: PropTypes.string, 19 }; 20 21 static defaultProps = { 22 fetchPlugin: () => {}, 23 plugin: {}, 24 slug: '', 25 }; 26 12 27 componentDidMount() { 13 this. getPlugin();14 } ,28 this.fetchPlugin(); 29 } 15 30 16 componentDidUpdate( previousProps) {17 if ( this.props.slug !== previousProps.slug) {18 this. getPlugin();31 componentDidUpdate( { plugin, slug } ) { 32 if ( this.props.slug !== slug || this.props.plugin !== plugin ) { 33 this.fetchPlugin(); 19 34 } 20 } ,35 } 21 36 22 getPlugin() {23 this.props.dispatch( getPlugin( this.props.slug ));24 } ,37 fetchPlugin() { 38 // this.props.fetchPlugin( this.props.slug ); 39 } 25 40 26 41 render() { 27 return <PluginCard { ...this.props} />;42 return <PluginCard plugin={ this.props.plugin } />; 28 43 } 29 } );44 } 30 45 31 const mapStateToProps = ( state, ownProps ) => ( { 32 plugin: find( state.plugins, { slug: ownProps.slug } ) 33 } ); 34 35 export default connect( mapStateToProps )( PluginCardContainer ); 36 37 46 export default connect( 47 ( state, { plugin, slug } ) => ( { 48 plugin: plugin || getPlugin( state, slug ), 49 } ), 50 { 51 fetchPlugin, 52 }, 53 )( PluginCardContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-card/plugin-card.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 2 5 import { Link } from 'react-router'; 3 6 … … 8 11 import PluginRatings from 'components/plugin-ratings'; 9 12 10 export default React.createClass( { 11 displayName: 'PluginCard', 13 export const PluginCard = ( { plugin } ) => ( 14 <article className="plugin type-plugin plugin-card"> 15 <PluginIcon slug={ plugin.slug } /> 16 <div className="entry"> 17 <header className="entry-header"> 18 <h2 className="entry-title"> 19 <Link 20 to={ `${ plugin.slug }/` } 21 rel="bookmark" 22 dangerouslySetInnerHTML={ { __html: plugin.title.rendered } } 23 /> 24 </h2> 25 </header> 12 26 13 render() { 14 if ( ! this.props.plugin ) { 15 return ( 16 <div /> 17 ); 18 } 27 { plugin.ratings && <PluginRatings rating={ plugin.meta.rating } ratingCount={ plugin.ratings.length } /> } 19 28 20 return ( 21 <article className="plugin type-plugin plugin-card"> 22 <PluginIcon plugin={ this.props.plugin } /> 23 <div className="entry"> 24 <header className="entry-header"> 25 <h2 className="entry-title"> 26 <Link to={ `${ this.props.plugin.slug }/` } rel="bookmark">{ this.props.plugin.name }</Link> 27 </h2> 28 </header> 29 <div className="entry-excerpt" dangerouslySetInnerHTML={ { __html: plugin.excerpt.rendered } } /> 30 </div> 31 </article> 32 ); 29 33 30 <PluginRatings rating={ this.props.plugin.rating } ratingCount={ this.props.plugin.num_ratings } /> 34 PluginCard.propTypes = { 35 plugin: PropTypes.object, 36 }; 31 37 32 <div className="entry-excerpt">{ this.props.plugin.short_description }</div> 33 </div> 34 </article> 35 ) 36 } 37 } ); 38 export default PluginCard; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-directory.jsx
r4223 r5024 1 import React from 'react'; 2 import { IndexLink } from 'react-router'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 3 5 6 /** 7 * Internal dependencies. 8 */ 4 9 import TextWidget from 'components/widget-area/widgets/text'; 5 10 import WidgetArea from 'components/widget-area'; 6 11 7 export default React.createClass( {8 displayName: 'PluginDirectory',9 10 widgetArea() {11 return (12 <WidgetArea { ...this.props }>13 { this.props.widgets.map( widget=>12 export const PluginDirectory = ( { header, main, router, widgets } ) => ( 13 <div> 14 { header } 15 { main } 16 { router.isActive( '/', true ) && 17 <WidgetArea> 18 { widgets.map( ( widget ) => 14 19 <TextWidget key={ widget.title } widget={ widget } /> 15 20 ) } 16 21 </WidgetArea> 17 ); 18 }, 22 } 23 </div> 24 ); 19 25 20 render() { 21 return ( 22 <div> 23 { this.props.header } 24 { this.props.main } 25 { this.props.router.isActive( '/', true ) ? this.widgetArea() : <div /> } 26 </div> 27 ) 28 } 29 } ); 26 PluginDirectory.propTypes = { 27 header: PropTypes.object, 28 main: PropTypes.object, 29 router: PropTypes.object, 30 widgets: PropTypes.arrayOf( PropTypes.object ), 31 }; 30 32 33 PluginDirectory.defaultProps = { 34 header: {}, 35 main: {}, 36 router: {}, 37 widgets: [], 38 }; 39 40 export default PluginDirectory; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-icon/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 2 6 3 export default React.createClass( { 4 displayName: 'PluginIcon', 7 /** 8 * Internal dependencies. 9 */ 10 import { getPlugin } from 'state/selectors'; 5 11 6 render() { 7 const { icons, slug } = this.props.plugin; 8 let icon; 12 /** 13 * 14 * @param {Object} plugin Plugin object. 15 * @return {*} React element or null. 16 * @constructor 17 */ 18 export const PluginIcon = ( { plugin } ) => { 19 const { icons, slug } = plugin; 20 let icon; 9 21 10 11 return <div />;12 22 if ( ! icons ) { 23 return null; 24 } 13 25 14 if ( icons[ '1x' ]) {15 icon = icons[ '1x' ]16 } else if ( icons.svg) {17 icon = icons.svg;18 19 20 26 if ( icons.svg ) { 27 icon = icons.svg; 28 } else if ( icons[ '1x' ] ) { 29 icon = icons[ '1x' ]; 30 } else { 31 icon = icons.default; 32 } 21 33 22 return ( 23 <div className="entry-thumbnail"> 24 <div className="plugin-icon" id={ `plugin-icon-${ slug }` }></div> 25 <style type='text/css'> 26 { `#plugin-icon-${ slug } { background-image: url('${ icon }'); } .plugin-icon { background-size: contain; height: 128px; width: 128px; }` } 27 { icons[ '2x' ] && icon !== icons.default ? 28 `@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { #plugin-icon-${ slug } { background-image: url('${ icons[ '2x' ] }'); } }` : '' 29 } } 30 </style> 31 </div> 32 ) 33 } 34 } ); 34 return ( 35 <div className="entry-thumbnail"> 36 <div className="plugin-icon" id={ `plugin-icon-${ slug }` } /> 37 <style type="text/css"> 38 { `#plugin-icon-${ slug } { background-image: url('${ icon }'); }` } 39 { icons[ '2x' ] && icon !== icons.default 40 // eslint-disable-next-line max-len 41 ? `@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) { #plugin-icon-${ slug } { background-image: url('${ icons[ '2x' ] }'); } }` 42 : '' 43 } 44 </style> 45 </div> 46 ); 47 }; 48 49 PluginIcon.propTypes = { 50 plugin: PropTypes.object, 51 slug: PropTypes.string, 52 }; 53 54 PluginIcon.defaultProps = { 55 plugin: {}, 56 slug: '', 57 }; 58 59 export default connect( 60 ( state, { slug } ) => ( { 61 plugin: getPlugin( state, slug ), 62 } ), 63 )( PluginIcon ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-icon/style.scss
r4223 r5024 2 2 display: none; 3 3 max-width: 128px; 4 5 .plugin-icon { 6 background-size: cover; 7 height: 128px; 8 width: 128px; 9 } 4 10 5 11 @media screen and ( min-width: 21em ) { -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-ratings/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { localize } from 'i18n-calypso'; 6 import { identity } from 'lodash'; 2 7 3 8 /** … … 6 11 import Stars from './stars'; 7 12 8 export default React.createClass( { 9 displayName: 'PluginRatings', 13 export const PluginRatings = ( { numberFormat, rating, ratingCount, translate } ) => ( 14 <div className="plugin-rating" itemProp="aggregateRating" itemScope="" itemType="http://schema.org/AggregateRating"> 15 <meta itemProp="ratingCount" content={ ratingCount } /> 16 <meta itemProp="ratingValue" content={ rating } /> 10 17 11 render() { 12 return ( 13 <div className="plugin-rating" itemProp="aggregateRating" itemScope="" itemType="http://schema.org/AggregateRating"> 14 <meta itemProp="ratingCount" content={ this.props.ratingCount } /> 15 <meta itemProp="ratingValue" content={ this.props.rating } /> 18 <Stars rating={ rating } /> 19 <span className="rating-count"> 20 { translate( '(%(count)s{{span}} total ratings{{/span}})', { 21 args: { count: numberFormat( ratingCount ) }, 22 components: { span: <span className="screen-reader-text" /> }, 23 } ) } 24 </span> 25 </div> 26 ); 16 27 17 <Stars rating={ this.props.rating } /> 18 <span className="rating-count">({ this.props.ratingCount }<span className="screen-reader-text"> total ratings</span>)</span> 19 </div> 20 ) 21 } 22 } ); 28 PluginRatings.propTypes = { 29 numberFormat: PropTypes.func, 30 rating: PropTypes.number, 31 ratingCount: PropTypes.number, 32 translate: PropTypes.func, 33 }; 34 35 PluginRatings.defaultProps = { 36 numberFormat: identity, 37 rating: 0, 38 ratingCount: 0, 39 translate: identity, 40 }; 41 42 export default localize( PluginRatings ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin-ratings/stars/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 export default React.createClass( { 4 displayName: 'Stars', 8 export class Stars extends Component { 9 static propTypes = { 10 rating: PropTypes.number, 11 translate: PropTypes.func, 12 }; 5 13 6 fillStars( rating ) { 7 const template = '<span class="%1$s"></span>'; 14 static defaultProps = { 15 rating: 0, 16 translate: identity, 17 }; 18 19 /** 20 * Returns filled stars representative of rating. 21 * 22 * @param {Number} rating Plugin rating. 23 * @return {String} Rating stars. 24 */ 25 fillStars = ( rating ) => { 8 26 let counter = rating * 2, 9 27 output = '', … … 13 31 switch ( counter ) { 14 32 case 0: 15 output += template.replace( '%1$s', 'dashicons dashicons-star-empty' );33 output += '<span class="dashicons dashicons-star-empty"></span>'; 16 34 break; 17 35 18 36 case 1: 19 output += template.replace( '%1$s', 'dashicons dashicons-star-half' );37 output += '<span class="dashicons dashicons-star-half"></span>'; 20 38 counter--; 21 39 break; 22 40 23 41 default: 24 output += template.replace( '%1$s', 'dashicons dashicons-star-filled' );42 output += '<span class="dashicons dashicons-star-filled"></span>'; 25 43 counter -= 2; 26 44 } … … 28 46 29 47 return output; 30 } ,48 }; 31 49 32 50 render() { 33 const titleTemplate = '%s out of 5 stars',34 title = titleTemplate.replace( '%s', this.props.rating / 20 );51 const { rating, translate } = this.props; 52 const stars = Math.round( rating / 0.5 ) * 0.5; 35 53 36 54 return ( 37 55 <div 38 56 className="wporg-ratings" 39 aria-label={ title } 40 data-title-template={ titleTemplate } 41 data-rating={ this.props.rating / 20 } 42 dangerouslySetInnerHTML={ { __html: this.fillStars( Math.round( this.props.rating / 10 ) / 2 ) } } 43 ></div> 44 ) 57 aria-label={ translate( '%(stars)s out of 5 stars', { args: { stars } } ) } 58 dangerouslySetInnerHTML={ { __html: this.fillStars( stars ) } } 59 /> 60 ); 45 61 } 46 } ); 62 } 63 64 export default localize( Stars ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/download-button/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 3 export default React.createClass( { 4 displayName: 'DownloadButton', 9 /** 10 * Internal dependencies. 11 */ 12 import { getPlugin } from 'state/selectors'; 5 13 6 render() { 7 return ( 8 <span> 9 <a className="plugin-download button download-button button-large" href={ this.props.plugin.download_link } itemProp="downloadUrl"> 10 Download 11 </a> 12 <meta itemProp="softwareVersion" content={ this.props.plugin.version } /> 13 <meta itemProp="fileFormat" content="application/zip" /> 14 </span> 15 ) 16 } 17 } ); 14 export const DownloadButton = ( { plugin, translate } ) => ( 15 <span> 16 <a 17 className="plugin-download button download-button button-large" 18 href={ plugin.download_link } 19 itemProp="downloadUrl" 20 > 21 { translate( 'Download' ) } 22 </a> 23 <meta itemProp="softwareVersion" content={ plugin.version } /> 24 <meta itemProp="fileFormat" content="application/zip" /> 25 </span> 26 ); 27 28 DownloadButton.propTypes = { 29 plugin: PropTypes.object, 30 translate: PropTypes.func, 31 }; 32 33 DownloadButton.defaultProps = { 34 plugin: {}, 35 translate: identity, 36 }; 37 38 export default connect( 39 ( state ) => ( { 40 plugin: getPlugin( state ), 41 } ), 42 )( localize( DownloadButton ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/favorite-button/index.jsx
r4467 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 3 import FavoriteButton from './button'; 4 import { 5 getFavorites, 6 favoritePlugin, 7 unfavoritePlugin 8 } from 'actions/index'; 9 /** 10 * Internal dependencies. 11 */ 12 import { favoritePlugin } from 'state/favorites/actions'; 13 import { isFavorite } from 'state/selectors'; 9 14 10 export default React.createClass( { 11 componentDidMount() { 12 this.getFavorites(); 13 }, 15 export class FavoriteButton extends Component { 16 static propTypes = { 17 favorite: PropTypes.bool, 18 favoritePlugin: PropTypes.func, 19 plugin: PropTypes.object, 20 translate: PropTypes.func, 21 }; 14 22 15 componentDidUpdate( previousProps ) { 16 if ( this.props.plugin.slug !== previousProps.plugin.slug ) { 17 this.getFavorites(); 18 } 19 }, 23 static defaultProps = { 24 favorite: false, 25 favoritePlugin: () => {}, 26 plugin: {}, 27 translate: identity, 28 }; 20 29 21 getFavorites() { 22 this.props.dispatch( getFavorites( this.props.plugin.slug ) ); 23 }, 30 toggleFavorite = ( event ) => { 31 const $button = jQuery( event.target ); 24 32 25 toggleFavorite( event ) { 26 if ( event.target.classList.contains( 'favorited' ) ) { 27 this.props.dispatch( unfavoritePlugin( this.props.plugin.slug ) ); 28 } else { 29 this.props.dispatch( favoritePlugin( this.props.plugin.slug ) ); 30 } 31 }, 33 this.props.favoritePlugin( this.props.plugin ); 34 35 $button.addClass( 'is-animating' ).one( 'animationend', () => { 36 $button.toggleClass( 'is-animating favorited' ); 37 } ); 38 }; 32 39 33 40 render() { 34 return <FavoriteButton toggleFavorite={ this.toggleFavorite } />; 41 if ( 0 === pluginDirectory.userId ) { 42 return null; 43 } 44 45 const { favorite, plugin, translate } = this.props; 46 const classNames = [ 'plugin-favorite-heart' ]; 47 48 if ( favorite ) { 49 classNames.push( 'favorited' ); 50 } 51 52 return ( 53 <div className="plugin-favorite"> 54 <button type="button" className={ classNames.join( ' ' ) } onClick={ this.toggleFavorite } > 55 <span className="screen-reader-text"> 56 { favorite 57 ? translate( 'Unfavorite %(name)s', { components: { name: plugin.name } } ) 58 : translate( 'Favorite %(name)s', { components: { name: plugin.name } } ) 59 } 60 </span> 61 </button> 62 </div> 63 ); 35 64 } 36 } ); 65 } 66 67 export default connect( 68 ( state ) => ( { 69 favorite: isFavorite( state ), 70 } ), 71 { 72 favoritePlugin, 73 }, 74 )( localize( FavoriteButton ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 import find from 'lodash/find';4 6 7 /** 8 * Internal dependencies. 9 */ 5 10 import Plugin from './plugin'; 6 import { getPlugin } from 'actions';11 import { fetchPlugin } from 'state/plugins/actions'; 7 12 8 const PluginContainer = React.createClass( { 13 class PluginContainer extends Component { 14 static PropTypes = { 15 fetchPlugin: PropTypes.func, 16 params: PropTypes.object, 17 }; 18 19 static defaultProps = { 20 fetchPlugin: () => {}, 21 params: {}, 22 }; 23 9 24 componentDidMount() { 10 this. getPlugin();11 } ,25 this.fetchPlugin(); 26 } 12 27 13 componentDidUpdate( previousProps) {14 if ( this.props. route.path !== previousProps.route.path) {15 this. getPlugin();28 componentDidUpdate( { params } ) { 29 if ( this.props.params.slug !== params.slug ) { 30 this.fetchPlugin(); 16 31 } 17 } ,32 } 18 33 19 getPlugin() {20 this.props. dispatch( getPlugin( this.props.params.slug ));21 } ,34 fetchPlugin() { 35 this.props.fetchPlugin( this.props.params.slug ); 36 } 22 37 23 38 render() { 24 return <Plugin { ...this.props }/>;39 return <Plugin />; 25 40 } 26 } );41 } 27 42 28 const mapStateToProps = ( state, ownProps ) => ( { 29 plugin: find( state.plugins, { slug: ownProps.params.slug } ) 30 } ); 31 32 export default connect( mapStateToProps )( PluginContainer ); 43 export default connect( 44 null, 45 { 46 fetchPlugin, 47 }, 48 )( PluginContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/plugin-banner/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 2 6 3 export default React.createClass( { 4 displayName: 'PluginBanner', 7 /** 8 * Internal dependencies. 9 */ 10 import { getPlugin } from 'state/selectors'; 5 11 6 render() { 7 const { banners, slug } = this.props.plugin; 8 let banner; 12 /** 13 * 14 * @param {Object} plugin Plugin object. 15 * @return {*} React element. 16 * @constructor 17 */ 18 export const PluginBanner = ( { plugin } ) => { 19 const { banners, slug } = plugin; 9 20 10 11 return <div />;12 21 if ( ! banners ) { 22 return null; 23 } 13 24 14 banner = banners[ 'low' ] ? banners[ 'low' ] : banners[ 'high' ];25 const banner = banners.low || banners.high; 15 26 16 17 return <div />;18 27 if ( ! banner ) { 28 return null; 29 } 19 30 20 return ( 21 <div className="entry-banner"> 22 <div className="plugin-banner" id={ `plugin-banner-${ slug }` }></div> 23 <style type='text/css'> 24 { `#plugin-banner-${ slug } { background-image: url('${ banner }'); }` } 25 { banners[ 'high' ] ? 26 `@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { #plugin-banner-${ slug } { background-image: url('${ banners[ 'high' ] }'); } }` : '' 27 } } 28 </style> 29 </div> 30 ) 31 } 32 } ); 31 return ( 32 <div className="entry-banner"> 33 <div className="plugin-banner" id={ `plugin-banner-${ slug }` } /> 34 <style type="text/css"> 35 { `#plugin-banner-${ slug } { background-image: url('${ banner }'); }` } 36 { banners.high && '@media ' + 37 'only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) ' + 38 `{ #plugin-banner-${ slug } { background-image: url('${ banners.high }'); } }` 39 } } 40 </style> 41 </div> 42 ); 43 }; 44 45 PluginBanner.propTypes = { 46 plugin: PropTypes.object, 47 }; 48 49 PluginBanner.defaultProps = { 50 plugin: {}, 51 }; 52 53 export default connect( 54 ( state ) => ( { 55 plugin: getPlugin( state ), 56 } ), 57 )( PluginBanner ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/plugin.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 8 import { values } from 'lodash'; 2 9 10 /** 11 * Internal dependencies. 12 */ 3 13 import Developers from './sections/developers'; 4 14 import DonateWidget from 'components/widget-area/widgets/donate'; … … 6 16 import FAQ from './sections/faq'; 7 17 import FavoriteButton from './favorite-button'; 18 import { getPlugin } from 'state/selectors'; 8 19 import MetaWidget from 'components/widget-area/widgets/meta/index'; 9 20 import PluginBanner from './plugin-banner'; … … 15 26 import SupportWidget from 'components/widget-area/widgets/support/index'; 16 27 17 export default React.createClass( { 18 displayName: 'Plugin', 19 20 render() { 21 if ( ! this.props.plugin ) { 22 return ( 23 <article className="plugin type-plugin"> 24 <header className="entry-header"> 25 <h1 className="entry-title"> </h1> 26 </header> 27 <div className="entry-content"> 28 <section> 29 <div className="container"> LOADING </div> 30 </section> 31 </div> 32 </article> 33 ) 34 } 35 28 export const Plugin = ( { plugin, translate } ) => { 29 if ( ! plugin ) { 36 30 return ( 37 31 <article className="plugin type-plugin"> 38 <PluginBanner plugin={ this.props.plugin } /> 39 <header className="plugin-header"> 40 <PluginIcon plugin={ this.props.plugin } /> 41 <div className="plugin-actions"> 42 <FavoriteButton plugin={ this.props.plugin } /> 43 <DownloadButton plugin={ this.props.plugin } /> 44 </div> 45 <h1 className="plugin-title">{ this.props.plugin.name }</h1> 46 <span className="byline">By <span className="author vcard" dangerouslySetInnerHTML={ { __html: this.props.plugin.author } } /></span> 32 <header className="entry-header"> 33 <h1 className="entry-title"> </h1> 47 34 </header> 48 35 <div className="entry-content"> 49 <Section slug="description" title="Description" content={ this.props.plugin.sections.description } /> 50 <Screenshots screenshots={ this.props.plugin.screenshots } /> 51 <FAQ content={ this.props.plugin.sections.faq } /> 52 <Reviews slug={ this.props.plugin.slug } content={ this.props.plugin.sections.reviews } numRatings={ this.props.plugin.num_ratings } /> 53 <Section slug="changelog" title="Changelog" content={ this.props.plugin.sections.changelog } /> 54 <Developers slug={ this.props.plugin.slug } contributors={ this.props.plugin.contributors } /> 55 </div> 56 <div className="entry-meta"> 57 <MetaWidget plugin={ this.props.plugin } /> 58 <RatingsWidget plugin={ this.props.plugin } /> 59 <SupportWidget plugin={ this.props.plugin } /> 60 <DonateWidget plugin={ this.props.plugin } /> 36 <section> 37 <div className="container"> LOADING </div> 38 </section> 61 39 </div> 62 40 </article> 63 ) 41 ); 64 42 } 65 } ); 43 44 return ( 45 <article className="plugin type-plugin"> 46 <PluginBanner /> 47 <header className="plugin-header"> 48 <PluginIcon /> 49 <div className="plugin-actions"> 50 <FavoriteButton plugin={ plugin } /> 51 <DownloadButton /> 52 </div> 53 <h1 className="plugin-title" dangerouslySetInnerHTML={ { __html: plugin.title.rendered } } /> 54 <span className="byline"> 55 { translate( 'By {{span/}}', { components: { 56 span: <span className="author vcard" dangerouslySetInnerHTML={ { __html: plugin.author } } />, 57 } } ) } 58 </span> 59 </header> 60 <div className="entry-content"> 61 <Section slug="description" title="Description" content={ plugin.sections.description } /> 62 <Screenshots screenshots={ values( plugin.screenshots ) } /> 63 <FAQ content={ plugin.sections.faq } /> 64 <Reviews 65 slug={ plugin.slug } 66 content={ plugin.sections.reviews } 67 numRatings={ plugin.ratings.length } /> 68 <Section slug="changelog" title="Changelog" content={ plugin.sections.changelog } /> 69 <Developers /> 70 </div> 71 <div className="entry-meta"> 72 <MetaWidget /> 73 <RatingsWidget /> 74 <SupportWidget /> 75 <DonateWidget /> 76 </div> 77 </article> 78 ); 79 }; 80 81 Plugin.propTypes = { 82 plugin: PropTypes.object, 83 translate: PropTypes.func, 84 }; 85 86 Plugin.defaultProps = { 87 plugin: {}, 88 translate: identity, 89 }; 90 91 export default connect( 92 ( state ) => ( { 93 plugin: getPlugin( state ), 94 } ), 95 )( localize( Plugin ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/changelog/style.scss
r4322 r5024 1 #changelog {2 font-size: ms( -2);1 .plugin-changelog { 2 font-size: ms( -2 ); 3 3 4 4 code { 5 font-size: ms( -2);5 font-size: ms( -2 ); 6 6 } 7 7 … … 10 10 } 11 11 } 12 -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/developers/index.jsx
r4464 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 9 /** 10 * Internal dependencies. 11 */ 3 12 import DeveloperList from './list'; 13 import { getPlugin } from 'state/selectors'; 4 14 5 export default React.createClass( { 6 displayName: 'Developers', 15 export const Developers = ( { plugin, translate } ) => ( 16 <div> 17 <div id="developers" className="section read-more plugin-developers"> 18 <h2>{ translate( 'Contributors & Developers' ) }</h2> 19 <p> 20 { translate( 'This is open source software. The following people have contributed to this plugin.' ) } 21 </p> 22 <DeveloperList contributors={ plugin.contributors } /> 7 23 8 render() { 9 return ( 10 <div> 11 <div id="developers" className="read-more"> 12 <h2>Contributors & Developers</h2> 13 <p>This is open source software. The following people have contributed to this plugin.</p> 14 <DeveloperList contributors={ this.props.contributors } /> 24 <h5>{ translate( 'Interested in development?' ) }</h5> 25 <p> 26 { 27 /* eslint-disable max-len */ 28 translate( '{{code}}Browse the code{{/code}} or subscribe to the {{log}}development log{{/log}} by {{rss}}RSS{{/rss}}.', { 29 components: { 30 code: <a href={ `https://plugins.svn.wordpress.org/${ plugin.slug }/` } rel="nofollow" />, 31 log: <a href={ `https://plugins.trac.wordpress.org/log/${ plugin.slug }/` } rel="nofollow" />, 32 rss: <a href={ `https://plugins.trac.wordpress.org/log/${ plugin.slug }/?limit=100&mode=stop_on_copy&format=rss` } rel="nofollow" />, 33 }, 34 } ) 35 /* eslint-enable max-len */ 36 } 37 </p> 38 </div> 39 <button type="button" className="button-link section-toggle" aria-controls="developers" aria-expanded="false"> 40 { translate( 'Read more' ) } 41 </button> 42 </div> 43 ); 15 44 16 <h5>Interested in development?</h5> 17 <p><a href={ `https://plugins.svn.wordpress.org/${ this.props.slug }/` } rel="nofollow">Browse the code</a> or subscribe to the <a href={ `https://plugins.trac.wordpress.org/log/${ this.props.slug }/` } rel="nofollow">development log</a> by <a href={ `https://plugins.trac.wordpress.org/log/${ this.props.slug }/?limit=100&mode=stop_on_copy&format=rss` } rel="nofollow">RSS</a>.</p> 18 </div> 19 <button type="button" className="button-link section-toggle" aria-controls="developers" aria-expanded="false">Read more</button> 20 </div> 21 ) 22 } 23 } ); 45 Developers.propTypes = { 46 plugin: PropTypes.object, 47 translate: PropTypes.func, 48 }; 49 50 Developers.defaultProps = { 51 plugin: {}, 52 translate: identity, 53 }; 54 55 export default connect( 56 ( state ) => ( { 57 plugin: getPlugin( state ), 58 } ), 59 )( localize( Developers ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/developers/list.jsx
r4223 r5024 1 import React from 'react'; 2 import values from 'lodash/values'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { map } from 'lodash'; 3 6 4 export default React.createClass( { 5 displayName: 'DeveloperList', 6 7 render() { 8 if ( ! this.props.contributors ) { 9 return <div />; 10 } 11 7 /** 8 * 9 * @param {Object} contributors Plugin contributors. 10 * @return {*} React Element 11 * @constructor 12 */ 13 export const DeveloperList = ( { contributors } ) => { 14 if ( contributors ) { 12 15 return ( 13 16 <ul className="plugin-developers"> 14 { values( this.props.contributors ).map(( contributor, index ) =>17 { map( contributors, ( contributor, index ) => 15 18 <li key={ index }> 16 <img className="avatar avatar-32 photo" height="32" width="32" src={ contributor.avatar } /> 17 <a href={ contributor.profile }>{ contributor.display_name }</a> 19 <a href={ contributor.profile }> 20 <img className="avatar avatar-32 photo" height="32" width="32" src={ contributor.avatar } /> 21 { contributor.display_name } 22 </a> 18 23 </li> 19 24 ) } 20 25 </ul> 21 ) 26 ); 22 27 } 23 } ); 28 29 return null; 30 }; 31 32 DeveloperList.propTypes = { 33 contributors: PropTypes.object, 34 }; 35 36 DeveloperList.defaultProps = { 37 contributors: {}, 38 }; 39 40 export default DeveloperList; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/faq/index.jsx
r4410 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 export default React.createClass( { 4 displayName: 'FAQ', 8 export class FAQ extends Component { 9 static propTypes = { 10 content: PropTypes.string, 11 translate: PropTypes.func, 12 }; 5 13 6 toggleAnswer( event ) { 7 var $question = jQuery( event.target ); 14 static defaultProps = { 15 content: null, 16 translate: identity, 17 }; 18 19 toggleAnswer = ( event ) => { 20 const $question = jQuery( event.target ); 8 21 9 22 if ( ! $question.is( '.open' ) ) { 10 $question.siblings( '.open' ).toggleClass( 'open' ).attr( 'aria-expanded', false ).next( 'dd' ).slideToggle( 200 ); 23 $question.siblings( '.open' ).toggleClass( 'open' ).attr( 'aria-expanded', false ) 24 .next( 'dd' ).slideToggle( 200 ); 11 25 } 12 26 13 $question.toggleClass( 'open' ).attr( 'aria-expanded', function( index, attribute ) { 14 return 'true' !== attribute; 15 } ).next( 'dd' ).slideToggle( 200 ); 16 }, 27 $question.toggleClass( 'open' ).attr( 'aria-expanded', ( index, attribute ) => ( 'true' !== attribute ) ) 28 .next( 'dd' ).slideToggle( 200 ); 29 }; 17 30 18 31 render() { 19 if ( ! this.props.content ) { 20 return <div />; 32 const { content, translate } = this.props; 33 34 if ( content ) { 35 return ( 36 <div id="faq" className="section plugin-faq"> 37 <h2>{ translate( 'FAQ' ) }</h2> 38 <div onClick={ this.toggleAnswer } dangerouslySetInnerHTML={ { __html: content } } /> 39 </div> 40 ); 21 41 } 22 42 23 return ( 24 <div id="faq"> 25 <h2>FAQ</h2> 26 <div onClick={ this.toggleAnswer } dangerouslySetInnerHTML={ { __html: this.props.content } } /> 27 </div> 28 ) 43 return null; 29 44 } 30 } ); 45 } 46 47 export default localize( FAQ ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/faq/style.scss
r4410 r5024 1 #faq {1 .plugin-faq { 2 2 h2:first-of-type { 3 3 font-size: ms( 2 ); … … 40 40 margin: 0 0 1rem; 41 41 42 .no-js & { 43 display: block; 44 } 45 42 46 & p { 43 47 margin: 0; … … 49 53 } 50 54 } 51 52 .no-js #faq dd {53 display: block;54 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/index.jsx
r4464 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 export default React.createClass( { 4 displayName: 'Section', 8 export const Section = ( { content, slug, title, translate } ) => ( 9 <div> 10 <div id={ slug } className={ `section read-more plugin-${ slug }` }> 11 <h2>{ title }</h2> 12 <div dangerouslySetInnerHTML={ { __html: content } } /> 13 </div> 14 <button 15 type="button" 16 className="button-link section-toggle" 17 aria-controls={ slug } 18 aria-expanded="false" 19 data-show-less={ translate( 'Show less' ) } 20 data-read-more={ translate( 'Read more' ) } 21 > 22 { translate( 'Read more' ) } 23 </button> 24 </div> 25 ); 5 26 6 render(){7 return (8 <div>9 <div id={ this.props.slug } className="section read-more">10 <h2>{ this.props.title }</h2>11 <div dangerouslySetInnerHTML={ { __html: this.props.content } } /> 12 </div> 13 <button type="button" className="button-link section-toggle" aria-controls={ this.props.slug } aria-expanded="false">Read more</button> 14 </div>15 ) 16 } 17 });27 Section.propTypes = { 28 content: PropTypes.string.isRequired, 29 slug: PropTypes.string.isRequired, 30 title: PropTypes.string.isRequired, 31 translate: PropTypes.func, 32 }; 33 34 Section.defaultProps = { 35 translate: identity, 36 }; 37 38 export default localize( Section ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/reviews/index.jsx
r4464 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 export default React.createClass( { 4 displayName: 'Reviews', 8 export const Reviews = ( { content, numberFormat, numRatings, slug, translate } ) => { 9 if ( ! numRatings ) { 10 return null; 11 } 5 12 6 render() { 7 return ( 8 <div> 9 <div id="reviews" className="read-more"> 10 <div className="plugin-reviews"> 11 <h2>Reviews</h2> 12 <div dangerouslySetInnerHTML={ { __html: this.props.content } } /> 13 </div> 13 return ( 14 <div> 15 <div id="reviews" className="section"> 16 <div className="plugin-reviews"> 17 <h2>{ translate( 'Reviews' ) }</h2> 18 <div dangerouslySetInnerHTML={ { __html: content } }/> 14 19 </div> 15 <a className="reviews-link" href={ `https://wordpress.org/support/plugin/${ this.props.slug }/reviews/` } aria-expanded="false">Read all { this.props.numRatings } reviews</a>16 20 </div> 17 ) 18 } 19 } ); 21 <a 22 className="reviews-link" 23 href={ `https://wordpress.org/support/plugin/${ slug }/reviews/` } 24 aria-expanded="false" 25 > 26 { translate( 'Read all %(numRatings)s reviews', { 27 args: { numRatings: numberFormat( numRatings ) }, 28 } ) } 29 </a> 30 </div> 31 ); 32 }; 33 34 Reviews.propTypes = { 35 content: PropTypes.string, 36 numberFormat: PropTypes.func, 37 numRatings: PropTypes.number.isRequired, 38 slug: PropTypes.string.isRequired, 39 translate: PropTypes.func, 40 }; 41 42 Reviews.defaultProps = { 43 content: null, 44 numberFormat: identity, 45 translate: identity, 46 }; 47 48 export default localize( Reviews ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/screenshots/image-gallery/index.jsx
r4506 r5024 551 551 </span>, 552 552 553 <div className="image-gallery-slides">{ slides }</div>553 <div key={ this.state.currentIndex } className="image-gallery-slides">{ slides }</div> 554 554 ] 555 555 : -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/screenshots/index.jsx
r4469 r5024 1 import React from 'react'; 2 import values from 'lodash/values'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 //import { localize } from 'i18n-calypso'; 6 import { identity, map } from 'lodash'; 3 7 8 /** 9 * Internal dependencies. 10 */ 4 11 import ImageGallery from './image-gallery'; 5 12 6 export default React.createClass( { 7 displayName: 'Screenshots', 13 export const Screenshots = ( { screenshots, translate } ) => { 14 const items = map( screenshots, ( { caption, src } ) => ( { 15 original: src, 16 originalAlt: '', 17 thumbnail: src + '&width=100', 18 thumbnailAlt: caption || '', 19 description: caption || false, 20 } ) ); 8 21 9 render() { 10 const items = values( this.props.screenshots ).map( ( { caption, src } ) => ( { 11 original: src, 12 originalAlt: '', 13 thumbnail: src + '&width=100', 14 thumbnailAlt: caption || '', 15 description: caption || false, 16 } ) ); 17 18 if ( ! items ) { 19 return; 20 } 21 22 if ( items ) { 22 23 return ( 23 24 <div id="screenshots" className="plugin-screenshots"> 24 <h2> Screenshots</h2>25 <h2>{ translate( 'Screenshots' ) }</h2> 25 26 <ImageGallery items={ items } /> 26 27 </div> 27 ) 28 ); 28 29 } 29 } ); 30 31 return null; 32 }; 33 34 Screenshots.propTypes = { 35 screenshots: PropTypes.arrayOf( PropTypes.object ), 36 translate: PropTypes.func, 37 }; 38 39 Screenshots.defaultProps = { 40 screenshots: [], 41 translate: identity, 42 }; 43 44 //export default localize( Screenshots ); 45 export default Screenshots; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/plugin/sections/style.scss
r4425 r5024 7 7 padding-bottom: 1px; 8 8 9 & #description {9 &.plugin-description { 10 10 max-height: 400px; 11 11 … … 19 19 } 20 20 21 .no-js & { 22 max-height: none; 23 overflow: auto; 24 } 21 25 } 22 26 … … 59 63 } 60 64 61 .no-js .read-more {62 overflow: auto;63 max-height: none;64 }65 66 65 .section-toggle { 67 66 color: $color__link; … … 70 69 margin-top: 0.5rem; 71 70 position: relative; 71 72 .no-js & { 73 display: none; 74 } 75 72 76 73 77 &:after { … … 89 93 } 90 94 } 91 92 .no-js .section-toggle {93 display: none;94 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/search-form/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * Internal dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 2 6 import { withRouter } from 'react-router'; 3 7 … … 5 9 * Internal dependencies. 6 10 */ 11 import { getSearchTerm } from 'state/selectors'; 7 12 import SearchForm from './search-form'; 8 13 9 const SearchFormContainer = React.createClass( { 10 getInitialState() { 11 return { 12 searchTerm: this.props.searchTerm 13 }; 14 }, 14 export class SearchFormContainer extends Component { 15 static propTypes = { 16 router: PropTypes.object, 17 search: PropTypes.string, 18 }; 15 19 16 onChange( searchTerm ) { 17 this.setState( { 18 searchTerm: searchTerm 19 } ); 20 }, 20 static defaultProps = { 21 router: {}, 22 search: '', 23 }; 21 24 22 componentWillReceiveProps( nextProps ) { 23 this.setState( { 24 searchTerm: nextProps.searchTerm 25 } ); 26 }, 25 onChange = ( search ) => { 26 this.setState( { search } ); 27 }; 27 28 28 onSubmit ( event ){29 var searchTerm = encodeURIComponent( this.state.searchTerm);29 onSubmit = ( event ) => { 30 const search = encodeURIComponent( this.state.search ); 30 31 event.preventDefault(); 31 32 32 if ( search Term) {33 this.props.router.push( `/search/${ search Term}/` );33 if ( search ) { 34 this.props.router.push( `/search/${ search }/` ); 34 35 } else { 35 36 this.props.router.push( '/' ); 36 37 } 37 }, 38 }; 39 40 constructor() { 41 super( ...arguments ); 42 43 this.state = { 44 search: this.props.search, 45 }; 46 } 47 48 componentWillReceiveProps( { search } ) { 49 this.setState( { search } ); 50 } 38 51 39 52 render() { 40 return <SearchForm searchTerm={ this.state.searchTerm }onSubmit={ this.onSubmit } onChange={ this.onChange } />;53 return <SearchForm onSubmit={ this.onSubmit } onChange={ this.onChange } />; 41 54 } 42 } );55 } 43 56 44 export default withRouter( SearchFormContainer ); 57 export default withRouter( connect( 58 ( state ) => ( { 59 search: getSearchTerm( state ), 60 } ), 61 )( SearchFormContainer ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/search-form/search-form.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * Internal dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 2 7 3 export default React.createClass( { 4 displayName: 'SearchForm', 8 export class SearchForm extends Component { 9 static propTypes = { 10 onChange: PropTypes.func, 11 onSubmit: PropTypes.func, 12 search: PropTypes.string, 13 translate: PropTypes.func, 14 }; 5 15 6 onChange() { 7 this.props.onChange( this.refs.search.value ); 8 }, 16 static defaultProps = { 17 onChange: () => {}, 18 onSubmit: () => {}, 19 search: '', 20 translate: identity, 21 }; 22 23 onChange = () => this.props.onChange( this.refs.search.value ); 9 24 10 25 render() { 26 const { onSubmit, search, translate } = this.props; 27 11 28 return ( 12 <form onSubmit={ this.props.onSubmit } role="search" method="get" className="search-form">13 <label htmlFor="s" className="screen-reader-text"> Search for:</label>29 <form onSubmit={ onSubmit } role="search" method="get" className="search-form"> 30 <label htmlFor="s" className="screen-reader-text">{ translate( 'Search for:' ) }</label> 14 31 <input 15 32 className="search-field" … … 20 37 ref="search" 21 38 type="search" 22 value={ this.props.searchTerm}39 defaultValue={ search } 23 40 /> 24 41 <button className="button button-primary button-search"> 25 <i className="dashicons dashicons-search" ></i>26 <span className="screen-reader-text"> Search plugins</span>42 <i className="dashicons dashicons-search" /> 43 <span className="screen-reader-text">{ translate( 'Search plugins' ) }</span> 27 44 </button> 28 45 </form> 29 ) 46 ); 30 47 } 31 } ); 48 } 49 50 export default localize( SearchForm ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/search/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 2 5 import { connect } from 'react-redux'; 3 6 7 /** 8 * Internal dependencies. 9 */ 4 10 import Search from './search'; 5 import { searchPlugins } from 'actions';11 import { fetchSearch } from 'state/search/actions'; 6 12 7 const SearchContainer = React.createClass( { 13 export class SearchContainer extends Component { 14 static propTypes = { 15 fetchSearch: PropTypes.func, 16 params: PropTypes.object, 17 }; 18 19 static defaultProps = { 20 fetchSearch: () => {}, 21 params: {}, 22 }; 23 8 24 componentDidMount() { 9 this. searchPlugins();10 } ,25 this.fetchSearch(); 26 } 11 27 12 componentDidUpdate( previousProps) {13 if ( this.props.params.search Term !== previousProps.params.searchTerm) {14 this. searchPlugins();28 componentDidUpdate( { params } ) { 29 if ( this.props.params.search !== params.search ) { 30 this.fetchSearch(); 15 31 } 16 } ,32 } 17 33 18 searchPlugins() {19 this.props. dispatch( searchPlugins( this.props.params.searchTerm ));20 } ,34 fetchSearch() { 35 this.props.fetchSearch( this.props.params.search ); 36 } 21 37 22 38 render() { 23 39 return <Search { ...this.props } />; 24 40 } 25 } );41 } 26 42 27 const mapStateToProps = ( state, ownProps ) => ( { 28 plugins: state.search[ ownProps.params.searchTerm ] || null 29 } ); 30 31 export default connect( mapStateToProps )( SearchContainer ); 43 export default connect( 44 null, 45 { 46 fetchSearch, 47 }, 48 )( SearchContainer ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/search/search.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 9 /** 10 * Internal dependencies. 11 */ 3 12 import ContentNone from 'components/content-none'; 4 13 import PluginCard from 'components/plugin-card'; 14 import { getSearchResults } from 'state/selectors'; 5 15 6 export default React.createClass( { 7 displayName: 'Search', 16 export const Search = ( { params, plugins, translate } ) => { 17 if ( ! plugins ) { 18 return <div>{ translate( 'Loading…' ) }</div>; 19 } 8 20 9 render() { 10 if ( ! this.props.plugins ) { 11 return <div>{ 'Loading...' }</div>; 12 } 21 if ( 0 === plugins.length ) { 22 return <ContentNone />; 23 } 13 24 14 if ( 0 === this.props.plugins.length ) { 15 return <ContentNone { ...this.props } />; 16 } 25 return ( 26 <div> 27 <header className="page-header"> 28 <h1 className="page-title"> 29 { translate( 'Search results for: {{strong}}%(search)s{{/strong}}', { 30 args: { search: params.search }, 31 components: { strong: <strong /> }, 32 } ) } 33 </h1> 34 <div className="taxonomy-description" /> 35 </header> 36 { plugins.map( ( slug ) => <PluginCard key={ slug } slug={ slug } /> ) } 37 </div> 38 ); 39 }; 17 40 18 return ( 19 <div> 20 <header className="page-header"> 21 <h1 className="page-title">Search results for: <strong>{ this.props.params.searchTerm }</strong></h1> 22 <div className="taxonomy-description"></div> 23 </header> 24 { this.props.plugins.map( slug => 25 <PluginCard key={ slug } slug={ slug } /> 26 ) } 27 </div> 28 ); 29 } 30 } ); 41 Search.propTypes = { 42 params: PropTypes.object, 43 plugins: PropTypes.arrayOf( PropTypes.string ), 44 translate: PropTypes.func, 45 }; 46 47 Search.defaultProps = { 48 params: {}, 49 plugins: [], 50 translate: identity, 51 }; 52 53 export default connect( 54 ( state ) => ( { 55 plugins: getSearchResults( state ), 56 } ), 57 )( localize( Search ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-header/index.jsx
r5023 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { withRouter } from 'react-router'; 2 6 7 /** 8 * Internal dependencies. 9 */ 3 10 import SearchForm from 'components/search-form'; 4 11 import SiteDescription from './site-description'; … … 6 13 import MainNavigation from './main-navigation'; 7 14 8 export default React.createClass( { 9 displayName: 'SiteHeader', 15 export const SiteHeader = ( { router } ) => { 16 const classes = [ 'site-header' ]; 17 const isHome = router.isActive( '/', true ); 10 18 11 render() {12 c onst classes = ['site-header'];13 classes.push( this.props.isHome ? 'home' : '' );19 if ( isHome ) { 20 classes.push( 'home' ); 21 } 14 22 15 return ( 16 <header id="masthead" className={ classes.join( ' ' ) } role="banner"> 17 <div className="site-branding"> 18 <SiteTitle isHome={ this.props.isHome } /> 19 <SiteDescription isHome={ this.props.isHome } /> 20 { this.props.isHome ? <SearchForm searchTerm={ this.props.searchTerm } /> : <MainNavigation searchTerm={ this.props.searchTerm } /> } 21 </div> 22 </header> 23 ) 24 } 25 } ); 23 return ( 24 <header id="masthead" className={ classes.join( ' ' ) } role="banner"> 25 <div className="site-branding"> 26 <SiteTitle /> 27 <SiteDescription /> 28 { isHome ? <SearchForm /> : <MainNavigation /> } 29 </div> 30 </header> 31 ); 32 }; 33 34 SiteHeader.propTypes = { 35 router: PropTypes.object, 36 }; 37 38 SiteHeader.defaultProps = { 39 router: {}, 40 }; 41 42 export default withRouter( SiteHeader ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-header/main-navigation/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 9 /** 10 * Internal dependencies. 11 */ 3 12 import MenuItem from './menu-item'; 4 13 import SearchForm from 'components/search-form'; 5 14 6 export default React.createClass( { 7 displayName: 'MainNavigation', 15 export const MainNavigation = ( { menuItems, translate } ) => ( 16 <nav id="site-navigation" className="main-navigation" role="navigation"> 17 <button 18 className="menu-toggle dashicons dashicons-arrow-down-alt2" 19 aria-controls="primary-menu" 20 aria-expanded="false" 21 aria-label={ translate( 'Primary Menu' ) } 22 /> 23 <div id="primary-menu" className="menu"> 24 <ul> 25 { menuItems.map( ( menuItem, key ) => <MenuItem key={ key } item={ menuItem } /> ) } 26 <li><SearchForm /></li> 27 </ul> 28 </div> 29 </nav> 30 ); 8 31 9 getDefaultProps() { 10 return { 11 menuItems: [ 12 { 13 path: 'browse/favorites/', 14 label: 'My Favorites' 15 }, 16 { 17 path: 'browse/beta/', 18 label: 'Beta Testing' 19 }, 20 { 21 path: 'developers/', 22 label: 'Developers' 23 } 24 ] 25 } 26 }, 32 MainNavigation.propTypes = { 33 menuItems: PropTypes.arrayOf( PropTypes.object ), 34 translate: PropTypes.func, 35 }; 27 36 28 render() { 29 var menuItems = this.props.menuItems.map( ( menuItem, key ) => <MenuItem key={ key } item={ menuItem } /> ); 37 MainNavigation.defaultProps = { 38 menuItems: [], 39 translate: identity, 40 }; 30 41 31 return ( 32 <nav id="site-navigation" className="main-navigation" role="navigation"> 33 <button className="menu-toggle dashicons dashicons-arrow-down-alt2" aria-controls="primary-menu" aria-expanded="false" aria-label="Primary Menu"></button> 34 <div id="primary-menu" className="menu"> 35 <ul> 36 { menuItems } 37 <li> 38 <SearchForm searchTerm={ this.props.searchTerm } /> 39 </li> 40 </ul> 41 </div> 42 </nav> 43 ) 44 } 45 } ); 42 export default localize( connect( 43 ( state, { translate } ) => ( { 44 menuItems: [ 45 { 46 path: 'browse/favorites/', 47 label: translate( 'My Favorites' ), 48 }, 49 { 50 path: 'browse/beta/', 51 label: translate( 'Beta Testing' ), 52 }, 53 { 54 path: 'developers/', 55 label: translate( 'Developers' ), 56 }, 57 ], 58 } ), 59 )( MainNavigation ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-header/main-navigation/menu-item/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 2 5 import { Link } from 'react-router'; 3 6 4 export default React.createClass( { 5 displayName: 'MenuItem', 7 export const MenuItem = ( { item } ) => ( 8 <li className="page_item"> 9 <Link to={ item.path } activeClassName="active">{ item.label }</Link> 10 </li> 11 ); 6 12 7 render(){8 return (9 <li className="page_item">10 <Link to={ this.props.item.path } activeClassName="active">{ this.props.item.label }</Link>11 </li>12 ) 13 } 14 } );13 MenuItem.propTypes = { 14 params: PropTypes.shape( { 15 label: PropTypes.string, 16 path: PropTypes.string, 17 } ), 18 }; 19 20 export default MenuItem; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-header/site-description/index.jsx
r4223 r5024 1 import React from 'react'; 2 import { IndexLink } from 'react-router'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { identity } from 'lodash'; 6 import { localize } from 'i18n-calypso'; 7 import { withRouter } from 'react-router'; 3 8 4 export default React.createClass( { 5 displayName: 'SiteDescription', 9 /** 10 * 11 * @param {Boolean} router Router object. 12 * @param {Function} translate i18n translation function. 13 * @return {*} Component or null. 14 * @constructor 15 */ 16 export const SiteDescription = ( { router, translate } ) => { 17 if ( router.isActive( '/', true ) ) { 18 return ( 19 <p className="site-description"> 20 { translate( 'Extend your WordPress experience with 40,000 plugins.' ) } 21 </p> 22 ); 23 } 6 24 7 render() { 8 if ( this.props.isHome ) { 9 return <p className="site-description">Extend your WordPress experience with 40,000 plugins.</p>; 10 } else { 11 return <span />; 12 } 13 } 14 } ); 25 return null; 26 }; 27 28 SiteDescription.propTypes = { 29 router: PropTypes.object, 30 translate: PropTypes.func, 31 }; 32 33 SiteDescription.defaultProps = { 34 router: {}, 35 translate: identity, 36 }; 37 38 export default withRouter( localize( SiteDescription ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-header/site-title/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { identity } from 'lodash'; 2 6 import { IndexLink } from 'react-router'; 7 import { localize } from 'i18n-calypso'; 8 import { withRouter } from 'react-router'; 3 9 4 export default React.createClass( { 5 displayName: 'SiteTitle', 10 export const SiteTitle = ( { router, translate } ) => ( 11 router.isActive( '/', true ) 12 ? <h1 className="site-title"><IndexLink to="/" rel="home">{ translate( 'Plugins' ) }</IndexLink></h1> 13 : <p className="site-title"><IndexLink to="/" rel="home">{ translate( 'Plugins' ) }</IndexLink></p> 14 ); 6 15 7 render() { 8 if ( this.props.isHome ) { 9 return <h1 className="site-title"><IndexLink to="/" rel="home">Plugins</IndexLink></h1>; 10 } else { 11 return <p className="site-title"><IndexLink to="/" rel="home">Plugins</IndexLink></p>; 12 } 13 } 14 } ); 16 SiteTitle.propTypes = { 17 router: PropTypes.object, 18 translate: PropTypes.func, 19 }; 20 21 SiteTitle.defaultProps = { 22 router: {}, 23 translate: identity, 24 }; 25 26 export default withRouter( localize( SiteTitle ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/site-main/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 2 5 3 export default React.createClass({4 displayName: 'SiteMain',6 export const SiteMain = ( { children, params } ) => { 7 const classNames = [ 'site-main' ]; 5 8 6 render() { 7 let classNames = [ 'site-main' ]; 9 if ( params.slug ) { 10 classNames.push( 'single' ); 11 } 8 12 9 if ( this.props.params.slug ) { 10 classNames.push( 'single' ); 11 } 13 return ( 14 <main id="main" className={ classNames.join( ' ' ) } role="main"> 15 { children } 16 </main> 17 ); 18 }; 12 19 13 return ( 14 <main id="main" className={ classNames.join( ' ' ) } role="main"> 15 { this.props.children } 16 </main> 17 ) 18 } 19 } ); 20 SiteMain.propTypes = { 21 params: PropTypes.object, 22 }; 23 24 SiteMain.defaultProps = { 25 params: {}, 26 }; 27 28 export default SiteMain; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { withRouter } from 'react-router'; 2 6 3 export default React.createClass({4 displayName: 'WidgetArea',7 export const WidgetArea = ( { children, router } ) => { 8 const classNames = [ 'widget-area' ]; 5 9 6 render() { 7 let classNames = [ 'widget-area' ]; 10 if ( router.isActive( '/', true ) ) { 11 classNames.push( 'home' ); 12 } 8 13 9 if ( this.props.router.isActive( '/', true ) ) { 10 classNames.push( 'home' ); 11 } 14 return ( 15 <aside id="secondary" className={ classNames.join( ' ' ) } role="complementary"> 16 { children } 17 </aside> 18 ); 19 }; 12 20 13 return ( 14 <aside id="secondary" className={ classNames.join( ' ' ) } role="complementary"> 15 { this.props.children } 16 </aside> 17 ) 18 } 19 } ); 21 WidgetArea.propTypes = { 22 router: PropTypes.object, 23 }; 24 25 WidgetArea.defaultProps = { 26 router: {}, 27 }; 28 29 export default withRouter( WidgetArea ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/donate.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 3 export default React.createClass( { 4 displayName: 'DonateWidget', 9 /** 10 * Internal dependencies. 11 */ 12 import { getPlugin } from 'state/selectors'; 5 13 6 render() { 7 if ( ! this.props.plugin.donate_link ) { 8 return <div />; 9 } 10 14 /** 15 * Donate Widget component. 16 * 17 * @param {Object} plugin Plugin object. 18 * @param {Function} translate Translation function. 19 * @return {*} Component or null. 20 * @constructor 21 */ 22 export const DonateWidget = ( { plugin, translate } ) => { 23 if ( plugin.donate_link ) { 11 24 return ( 12 25 <div className="widget plugin-donate"> 13 <h4 className="widget-title"> Donate</h4>14 <p className="aside"> Would you like to support the advancement of this plugin?</p>26 <h4 className="widget-title">{ translate( 'Donate' ) }</h4> 27 <p className="aside">{ translate( 'Would you like to support the advancement of this plugin?' ) }</p> 15 28 <p> 16 <a className="button button-secondary" href={ this.props.plugin.donate_link } rel="nofollow">17 Donate to this plugin29 <a className="button button-secondary" href={ plugin.donate_link } rel="nofollow"> 30 { translate( 'Donate to this plugin' ) } 18 31 </a> 19 32 </p> 20 33 </div> 21 ) 34 ); 22 35 } 23 } ); 36 37 return null; 38 }; 39 40 DonateWidget.propTypes = { 41 plugin: PropTypes.object, 42 translate: PropTypes.func, 43 }; 44 45 DonateWidget.defaultProps = { 46 plugin: {}, 47 translate: identity, 48 }; 49 50 export default connect( 51 ( state ) => ( { 52 plugin: getPlugin( state ), 53 } ), 54 )( localize( DonateWidget ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/meta/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { Link } from 'react-router'; 7 import { localize } from 'i18n-calypso'; 8 import { identity } from 'lodash'; 2 9 3 export default React.createClass( { 4 displayName: 'MetaWidget', 10 /** 11 * Internal dependencies. 12 */ 13 import { getPlugin } from 'state/selectors'; 5 14 15 export class MetaWidget extends Component { 16 static propTypes = { 17 moment: PropTypes.func, 18 numberFormat: PropTypes.func, 19 plugin: PropTypes.object, 20 translate: PropTypes.func, 21 }; 22 23 static defaultProps = { 24 moment: identity, 25 numberFormat: identity, 26 plugin: {}, 27 translate: identity, 28 }; 29 30 /** 31 * Returns a string representing the number of active installs for a plugin. 32 * 33 * @return {String} Active installs. 34 */ 35 activeInstalls() { 36 const { numberFormat, translate, plugin } = this.props; 37 let text; 38 39 if ( plugin.meta.active_installs <= 10 ) { 40 text = translate( 'Less than 10' ); 41 } else if ( plugin.meta.active_installs >= 1000000 ) { 42 text = translate( '1+ million' ); 43 } else { 44 text = numberFormat( plugin.meta.active_installs ) + '+'; 45 } 46 47 return text; 48 } 49 50 /** 51 * Returns markup to display tags, if there are any. 52 * 53 * @return {XML} Tags markup. 54 */ 6 55 renderTags() { 7 if ( this.props.plugin.tags.length ) { 8 return ( <li>Categories: <div className="tags">{ this.props.plugin.tags.map( tag => 9 <a key={ tag } href={ `https://wordpress.org/plugins-wp/category/${ tag }/` } rel="tag">{ tag }</a> 10 ) }</div></li> ); 56 const { plugin_tags: tags } = this.props.plugin; 57 58 if ( tags && tags.length ) { 59 const tagsList = ( 60 <div className="tags"> 61 { tags.map( ( tag ) => <Link key={ tag } to={ `tags/${ tag }/` } rel="tag">{ tag }</Link> ) } 62 </div> 63 ); 64 65 return ( 66 <li> 67 { this.props.translate( 'Tag: {{tagsList/}}', 'Tags: {{tagsList/}}', { 68 count: tags.length, 69 components: { tagsList }, 70 } ) } 71 </li> 72 ); 11 73 } 12 } ,74 } 13 75 14 76 render() { 77 const { moment, plugin, translate } = this.props; 15 78 16 79 return ( 17 80 <div className="widget plugin-meta"> 18 <h3 className="screen-reader-text"> Meta</h3>81 <h3 className="screen-reader-text">{ translate( 'Meta' ) }</h3> 19 82 <link itemProp="applicationCategory" href="http://schema.org/OtherApplication" /> 20 83 <span itemProp="offers" itemScope itemType="http://schema.org/Offer"> … … 27 90 28 91 <ul> 29 <li>Version: <strong>{ this.props.plugin.version }</strong></li> 30 <li>Last updated: <strong><span itemProp="dateModified" content={ this.props.plugin.last_updated }>{ this.props.plugin.last_updated }</span> ago</strong></li> 31 <li>Active installs: <strong>{ this.props.plugin.active_installs }</strong></li> 32 <li>Tested up to: <strong>{ this.props.plugin.tested }</strong></li> 92 <li> 93 { translate( 'Version: {{strong}}%(version)s{{/strong}}', { 94 args: { version: plugin.meta.version }, 95 components: { strong: <strong /> }, 96 } ) } 97 </li> 98 <li> 99 { translate( 'Last updated: {{strong}}%(updated)s{{/strong}}', { 100 args: { updated: moment( plugin.modified_gmt ).fromNow() }, 101 components: { strong: <strong itemProp="dateModified" content={ plugin.modified_gmt } /> }, 102 } ) } 103 </li> 104 <li> 105 { translate( 'Active installs: {{strong}}%(installs)s{{/strong}}', { 106 args: { installs: this.activeInstalls() }, 107 components: { strong: <strong /> }, 108 } ) } 109 </li> 110 <li> 111 { translate( 'Tested up to: {{strong}}%(tested)s{{/strong}}', { 112 args: { tested: plugin.meta.tested }, 113 components: { strong: <strong /> }, 114 } ) } 115 </li> 33 116 { this.renderTags() } 34 117 </ul> 35 118 </div> 36 ) 119 ); 37 120 } 38 } ); 121 } 122 123 export default connect( 124 ( state ) => ( { 125 plugin: getPlugin( state ), 126 } ), 127 )( localize( MetaWidget ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/ratings/index.jsx
r4223 r5024 1 import React from 'react'; 2 import rangeRight from 'lodash/rangeRight'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 8 import { rangeRight } from 'lodash'; 3 9 10 /** 11 * Internal dependencies. 12 */ 13 import { getPlugin } from 'state/selectors'; 4 14 import PluginRatings from 'components/plugin-ratings'; 5 15 6 export default React.createClass( { 7 displayName: 'RatingsWidget', 16 export class RatingsWidget extends Component { 17 static propTypes = { 18 plugin: PropTypes.object, 19 translate: PropTypes.func, 20 }; 21 22 static defaultProps = { 23 plugin: {}, 24 translate: identity, 25 }; 8 26 9 27 ratingsBreakdown() { 28 const { plugin, translate } = this.props; 29 30 if ( ! plugin.ratings.length ) { 31 return ( 32 <div className="rating"><p>{ translate( 'This plugin has not been rated yet.' ) }</p></div> 33 ); 34 } 35 10 36 return ( 11 37 <div> 12 <a className="reviews-link" href={ `https://wordpress.org/support/plugin/${ this.props.plugin.slug }/reviews/` }>See all</a> 38 <a className="reviews-link" href={ `https://wordpress.org/support/plugin/${ plugin.slug }/reviews/` }> 39 { translate( 'See all' ) } 40 </a> 13 41 14 <PluginRatings rating={ this.props.plugin.rating } ratingCount={ this.props.plugin.num_ratings} />42 <PluginRatings rating={ plugin.meta.rating } ratingCount={ plugin.ratings.length } /> 15 43 16 44 <ul className="ratings-list"> 17 { rangeRight( 1, 6 ).map( stars => { 18 const barWidth = this.props.plugin.num_ratings ? 100 * this.props.plugin.ratings[ stars ] / this.props.plugin.num_ratings : 0; 45 { rangeRight( 1, 6 ).map( ( stars ) => { 46 const barWidth = plugin.ratings.length ? 100 * plugin.ratings[ stars ] / plugin.ratings.length : 0; 47 const link = `https://wordpress.org/support/plugin/${ plugin.slug }/reviews/?filter=${ stars }`; 19 48 20 49 return ( 21 <li className="counter-container"> 22 <a href={ `https://wordpress.org/support/plugin/${ this.props.plugin.slug }/reviews/?filter=${ stars }` }> 23 <span className="counter-label">{ stars > 1 ? `${ stars } stars` : `${ stars } star` }</span> 50 <li key={ stars } className="counter-container"> 51 <a href={ link }> 52 <span className="counter-label"> 53 { translate( '1 star', '%(stars)s stars', { count: stars, args: { stars } } ) } 54 </span> 24 55 <span className="counter-back"> 25 56 <span className="counter-bar" style={ { width: `${ barWidth }%` } } /> 26 57 </span> 27 <span className="counter-count">{ this.props.plugin.ratings[ stars ] }</span>58 <span className="counter-count">{ plugin.ratings[ stars ] }</span> 28 59 </a> 29 60 </li> … … 33 64 </div> 34 65 ); 35 } ,66 } 36 67 37 68 render() { 69 const { plugin, translate } = this.props; 70 38 71 return ( 39 72 <div className="widget plugin-ratings"> 40 <h4 className="widget-title">Ratings</h4> 41 <meta itemProp="ratingCount" content={ this.props.plugin.num_ratings } /> 42 { this.props.plugin.num_ratings ? 43 this.ratingsBreakdown() : 44 <div className="rating"><p>This plugin has not been rated yet.</p></div> 45 } 73 <h4 className="widget-title">{ translate( 'Ratings' ) }</h4> 74 <meta itemProp="ratingCount" content={ plugin.ratings.length } /> 75 76 { this.ratingsBreakdown() } 77 46 78 <div className="user-rating"> 47 <a className="button button-secondary" href={ `https://wordpress.org/support/plugin/${ this.props.plugin.slug }/reviews/#new-post` }>Add my review</a> 79 <a 80 className="button button-secondary" 81 href={ `https://wordpress.org/support/plugin/${ plugin.slug }/reviews/#new-post` } 82 > 83 { translate( 'Add my review' ) } 84 </a> 48 85 </div> 49 86 </div> 50 ) 87 ); 51 88 } 52 } ); 89 } 90 91 export default connect( 92 ( state ) => ( { 93 plugin: getPlugin( state ), 94 } ), 95 )( localize( RatingsWidget ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/support/index.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { Component, PropTypes } from 'react'; 5 import { connect } from 'react-redux'; 6 import { identity } from 'lodash'; 7 import { localize } from 'i18n-calypso'; 2 8 3 export default React.createClass( { 4 displayName: 'SupportWidget', 5 resolutions: false, 9 /** 10 * Internal dependencies. 11 */ 12 import { getPlugin } from 'state/selectors'; 13 14 export class SupportWidget extends Component { 15 resolutions: false; 16 17 static propTypes = { 18 plugin: PropTypes.object, 19 translate: PropTypes.func, 20 }; 21 22 static defaultProps = { 23 plugin: {}, 24 translate: identity, 25 }; 6 26 7 27 componentWillMount() { 8 this.resolutions = ( this.props.plugin.support_threads || 'buddypress' === this.props.plugin.slug || 'bbpress' === this.props.plugin.slug ); 9 }, 28 const { meta, slug } = this.props.plugin; 29 this.resolutions = ( meta.support_threads || 'buddypress' === slug || 'bbpress' === slug ); 30 } 10 31 11 32 componentDidUpdate() { 12 this.resolutions = this.resolutions || this.props.plugin. support_threads;13 } ,33 this.resolutions = this.resolutions || this.props.plugin.meta.support_threads; 34 } 14 35 15 36 supportBar() { 16 const { support_threads: threads, support_threads_resolved: resolved } = this.props.plugin; 37 const { support_threads: threads, support_threads_resolved: resolved } = this.props.plugin.meta; 38 39 if ( ! this.resolutions ) { 40 return ( 41 <p>{ this.props.translate( 'Got something to say? Need help?' ) }</p> 42 ); 43 } 17 44 18 45 return ( 19 46 <div> 20 <p className="aside"> Issues resolved in last two months:</p>47 <p className="aside">{ this.props.translate( 'Issues resolved in last two months:' ) }</p> 21 48 <p className="counter-container"> 22 49 <span className="counter-back"> … … 24 51 </span> 25 52 <span className="counter-count"> 26 { resolved } out of { threads}53 { this.props.translate( '%(resolved)s out of %(threads)s', { args: { resolved, threads } } ) } 27 54 </span> 28 55 </p> 29 56 </div> 30 ) 31 } ,57 ); 58 } 32 59 33 60 getSupportUrl() { 34 let supportURL = `https://wordpress.org/support/plugin/${ this.props.plugin.slug }/`; 61 const { slug } = this.props.plugin; 62 let supportURL = `https://wordpress.org/support/plugin/${ slug }/`; 35 63 36 64 /* … … 38 66 * In the future we could open this up to all plugins that define a custom support URL. 39 67 */ 40 if ( 'buddypress' === this.props.plugin.slug ) {68 if ( 'buddypress' === slug ) { 41 69 supportURL = 'https://buddypress.org/support/'; 42 } else if ( 'bbpress' === this.props.plugin.slug ) {70 } else if ( 'bbpress' === slug ) { 43 71 supportURL = 'https://bbpress.org/forums/'; 44 72 } 45 73 46 74 return supportURL; 47 } ,75 } 48 76 49 77 render() { 50 78 return ( 51 79 <div className="widget plugin-support"> 52 <h4 className="widget-title">Support</h4> 53 { this.resolutions ? 54 this.supportBar() : 55 <p>Got something to say? Need help?</p> 56 } 80 <h4 className="widget-title">{ this.props.translate( 'Support' ) }</h4> 81 82 { this.supportBar() } 83 57 84 <p> 58 <a className="button" href={ this.getSupportUrl() }>View support forum</a> 85 <a className="button" href={ this.getSupportUrl() }> 86 { this.props.translate( 'View support forum' ) } 87 </a> 59 88 </p> 60 89 </div> 61 ) 90 ); 62 91 } 63 } ); 92 } 93 94 export default connect( 95 ( state ) => ( { 96 plugin: getPlugin( state ), 97 } ), 98 )( localize( SupportWidget ) ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/text.jsx
r4223 r5024 1 import React from 'react'; 1 /** 2 * External dependencies. 3 */ 4 import React, { PropTypes } from 'react'; 2 5 3 export default React.createClass( { 4 displayName: 'TextWidget', 6 export const TextWidget = ( { widget } ) => ( 7 <div className="widget widget_text"> 8 <h3 className="widget-title">{ widget.title }</h3> 9 <div className="textwidget">{ widget.text }</div> 10 </div> 11 ); 5 12 6 render(){7 return (8 <div className="widget widget_text"> 9 <h3 className="widget-title">{ this.props.widget.title }</h3> 10 <div className="textwidget">{ this.props.widget.text }</div> 11 </div>12 ) 13 } 14 } );13 TextWidget.propTypes = { 14 widget: PropTypes.object, 15 }; 16 17 TextWidget.defaultProps = { 18 widget: {}, 19 }; 20 21 export default TextWidget; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/index.jsx
r4409 r5024 1 /** 2 * External dependencies. 3 */ 1 4 import React from 'react'; 2 5 import { render } from 'react-dom'; 6 import { Provider } from 'react-redux'; 7 import { setLocale } from 'i18n-calypso'; 3 8 4 import Screenshots from 'components/plugin/sections/screenshots'; 9 /** 10 * Internal dependencies. 11 */ 12 import Router from 'modules/router'; 13 import getStore from 'modules/store'; 5 14 6 // Temporary hack to use the srceenshot viewer without the full React client 7 var elements = document.querySelectorAll( '#screenshots figure' ); 8 var images = []; 9 for ( var i=0; i < elements.length; i++ ) { 10 var caption = elements[i].querySelector('figcaption'); 11 var item = { 12 src: elements[i].querySelector('img.screenshot').src, 13 caption: caption ? caption.textContent : '', 14 } 15 images.push( item ); 16 } 15 //setLocale( localeData ); 17 16 18 if ( images.length > 0 ) { 19 render( 20 <Screenshots screenshots={images}> 21 </Screenshots>, 22 document.getElementById( 'screenshots' ) 23 ); 24 } 17 render( 18 <Provider store={ getStore() }> 19 { Router } 20 </Provider>, 21 document.getElementById( 'content' ) 22 ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/modules/api.js
r4223 r5024 1 /** 2 * The API module incorporates code from Feelingrestful WordPress React JS theme, Copyright Human Made 3 * Feelingrestful WordPress React JS theme is distributed under the terms of the GNU GPL v3 4 */ 5 /* global app_data:object */ 1 import WPAPI from 'wpapi'; 6 2 7 import $ajax from 'jquery/src/ajax'; 8 import $xhr from 'jquery/src/ajax/xhr'; 3 import routes from 'default-routes.json'; 9 4 10 const $ = Object.assign( {}, $ajax,$xhr ); 5 /** @type {Object} pluginDirectory Config variable */ 6 const pluginDirectory = window.pluginDirectory || {}; 7 pluginDirectory.routes = routes; 11 8 12 const API = { 9 const api = new WPAPI( pluginDirectory ); 10 api.sections = api.registerRoute( 'wp/v2', '/plugin_section/(?P<id>)' ); 13 11 14 api_url: app_data.api_url, 15 16 lastRequest: null, 17 18 get: function( url, data, callback ) { 19 return this.request( 'GET', url, data, callback ); 20 }, 21 22 post: function( url, data, callback ) { 23 return this.request( 'POST', url, data, callback ); 24 }, 25 26 request: function( method, url, data, callback ) { 27 28 this.lastRequest = { 29 method: method, 30 url: url, 31 args: data, 32 isLoading: true, 33 data: null 34 }; 35 36 var xhr = $.ajax( this.api_url + url, { 37 data: data, 38 global: false, 39 40 success: ( data ) => { 41 this.lastRequest.isLoading = false; 42 this.lastRequest.data = data; 43 if ( ! callback ) { 44 return; 45 } 46 callback( data, null, xhr.getAllResponseHeaders() ); 47 }, 48 method: method, 49 50 beforeSend: ( jqxhr ) => { 51 jqxhr.setRequestHeader( 'X-WP-Nonce', app_data.nonce ); 52 } 53 } ); 54 55 xhr.fail( err => { 56 this.lastRequest.isLoading = false; 57 58 if ( 0 === xhr.status ) { 59 if ( 'abort' === xhr.statusText ) { 60 // Has been aborted 61 return; 62 } else { 63 // Offline mode 64 } 65 } 66 67 if ( err.responseJSON && err.responseJSON[0] ) { 68 this.lastRequest.data = err.responseJSON[0]; 69 70 if ( callback ) { 71 callback( null, err.responseJSON[0] ); 72 } 73 } else { 74 window.console.error( err.statusText ); 75 } 76 } ); 77 78 return xhr; 79 } 80 }; 81 82 export default API; 12 export default api; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/modules/local-storage.js
r4223 r5024 19 19 const serializedState = JSON.stringify( state ); 20 20 localStorage.setItem( storageKey, serializedState ); 21 } catch ( error ) {}21 } catch ( error ) {} 22 22 }; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/modules/router.jsx
r4223 r5024 1 /* global add_data:object */ 1 /** 2 * External dependencies. 3 */ 2 4 import React from 'react'; 3 import { connect } from 'react-redux'; 4 import { Router, Route, IndexRoute, useRouterHistory } from 'react-router'; 5 import createBrowserHistory from 'history/lib/createBrowserHistory'; 5 import { Route, IndexRoute } from 'react-router'; 6 import { ReduxRouter } from 'redux-router'; 6 7 8 /** 9 * Internal dependencies. 10 */ 7 11 import ArchiveBrowse from 'components/archive/browse'; 8 12 import FrontPage from 'components/front-page'; … … 15 19 import SiteMain from 'components/site-main'; 16 20 17 const history = useRouterHistory( createBrowserHistory )( { 18 /** @type {object} app_data Description */ 19 basename: app_data.base 20 } ); 21 const onUpdate = () => window.scrollTo( 0, 0 ); 22 23 export const routes = ( 24 <Route name="root" component={ PluginDirectory }> 25 <Route path="/" components={ { header: SiteHeader, main: SiteMain } }> 26 <IndexRoute component={ FrontPage } /> 27 <Route path="browse/favorites/:username" component={ ArchiveBrowse } /> 28 <Route path="browse/:type/page/:page" component={ ArchiveBrowse } /> 29 <Route path="browse/:type" component={ ArchiveBrowse } /> 30 <Route path="developers" component={ Page } /> 31 <Route path="search/:search" component={ Search } /> 32 <Route path=":slug" component={ Plugin } /> 33 <Route path="*" component={ NotFound } /> 34 </Route> 35 </Route> 36 ); 21 37 22 38 export default ( 23 <Router history={ history } onUpdate={ () => window.scrollTo( 0, 0 ) }> 24 <Route name="root" component={ PluginDirectory }> 25 <Route path="/" components={ { header: SiteHeader, main: SiteMain } }> 26 <IndexRoute component={ FrontPage } /> 27 <Route path="browse/favorites/:username" component={ ArchiveBrowse } /> 28 <Route path="browse/:type" component={ ArchiveBrowse } /> 29 <Route path="developers" component={ Page } /> 30 <Route path="search/:searchTerm" component={ Search } /> 31 <Route path=":slug" component={ Plugin } /> 32 <Route path="*" component={ NotFound } /> 33 </Route> 34 </Route> 35 </Router> 39 <ReduxRouter onUpdate={ onUpdate }> 40 { routes } 41 </ReduxRouter> 36 42 ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/modules/store.js
r4223 r5024 1 /** 2 * External dependencies. 3 */ 1 4 import { compose, createStore, applyMiddleware } from 'redux'; 5 import createBrowserHistory from 'history/lib/createBrowserHistory'; 6 import { reduxReactRouter } from 'redux-router'; 2 7 import thunk from 'redux-thunk'; 3 import throttle from 'lodash/throttle'; 8 import { throttle } from 'lodash'; 9 import { useRouterHistory } from 'react-router'; 10 import { values } from 'lodash'; 4 11 5 import reducers from 'reducers'; 12 /** 13 * Internal dependencies. 14 */ 15 import { fetchUser } from 'state/user/actions'; 6 16 import { loadState, saveState } from 'modules/local-storage'; 17 import * as middlewares from './middlewares'; 18 import reducers from 'state/reducers'; 19 import { routes } from './router'; 20 21 const history = useRouterHistory( createBrowserHistory )( { 22 /** @type {object} pluginDirectory Description */ 23 basename: pluginDirectory.base, 24 } ); 7 25 8 26 const getStore = () => { 9 const store = compose( 10 applyMiddleware( thunk ) 11 )( createStore )( reducers, loadState() ); 27 const composeDev = ( 'production' !== process.env.NODE_ENV && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ); 28 const composeEnhancers = composeDev || compose; 29 const store = createStore( reducers, loadState(), composeEnhancers( 30 reduxReactRouter( { routes, history } ), 31 applyMiddleware( thunk, ...values( middlewares ) ), 32 ) ); 12 33 13 34 // Save state to local storage when the store gets updated. … … 16 37 }, 1000 ) ); 17 38 39 // Set up user object. 40 if ( '0' !== pluginDirectory.userId ) { 41 store.dispatch( fetchUser( pluginDirectory.userId ) ); 42 } 43 18 44 return store; 19 45 }; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/action-types.js
r5023 r5024 1 export const SECTION_RECEIVE = 'SECTION_RECEIVE'; 2 export const SECTION_REQUEST = 'SECTION_REQUEST'; 3 export const SECTION_REQUEST_SUCCESS = 'SECTION_REQUEST_SUCCESS'; 4 export const SECTION_REQUEST_FAILURE = 'SECTION_REQUEST_FAILURE'; 5 export const SECTIONS_RECEIVE = 'SECTIONS_RECEIVE'; 6 export const SECTIONS_REQUEST = 'SECTIONS_REQUEST'; 7 export const SECTIONS_REQUEST_SUCCESS = 'SECTIONS_REQUEST_SUCCESS'; 8 export const SECTIONS_REQUEST_FAILURE = 'SECTIONS_REQUEST_FAILURE'; 1 9 2 export const GET_BROWSE = 'GET_BROWSE'; 3 export const GET_PAGE = 'GET_PAGE'; 4 export const GET_PLUGIN = 'GET_PLUGIN'; 5 export const SEARCH_PLUGINS = 'SEARCH_PLUGINS'; 10 export const PAGE_RECEIVE = 'PAGE_RECEIVE'; 11 export const PAGE_REQUEST = 'PAGE_REQUEST'; 12 export const PAGE_REQUEST_SUCCESS = 'PAGE_REQUEST_SUCCESS'; 13 export const PAGE_REQUEST_FAILURE = 'PAGE_REQUEST_FAILURE'; 14 15 export const PLUGIN_RECEIVE = 'PLUGIN_RECEIVE'; 16 export const PLUGIN_REQUEST = 'PLUGIN_REQUEST'; 17 export const PLUGIN_REQUEST_SUCCESS = 'PLUGIN_REQUEST_SUCCESS'; 18 export const PLUGIN_REQUEST_FAILURE = 'PLUGIN_REQUEST_FAILURE'; 19 export const PLUGINS_RECEIVE = 'PLUGINS_RECEIVE'; 20 export const PLUGINS_REQUEST = 'PLUGINS_REQUEST'; 21 export const PLUGINS_REQUEST_SUCCESS = 'PLUGINS_REQUEST_SUCCESS'; 22 export const PLUGINS_REQUEST_FAILURE = 'PLUGINS_REQUEST_FAILURE'; 23 24 export const SEARCH_RECEIVE = 'SEARCH_RECEIVE'; 25 export const SEARCH_REQUEST = 'SEARCH_REQUEST'; 26 export const SEARCH_REQUEST_SUCCESS = 'SEARCH_REQUEST_SUCCESS'; 27 export const SEARCH_REQUEST_FAILURE = 'SEARCH_REQUEST_FAILURE'; 28 29 export const USER_RECEIVE = 'USER_RECEIVE'; 30 export const USER_REQUEST = 'USER_REQUEST'; 31 export const USER_REQUEST_SUCCESS = 'USER_REQUEST_SUCCESS'; 32 export const USER_REQUEST_FAILURE = 'USER_REQUEST_FAILURE'; 6 33 7 34 export const GET_FAVORITES = 'GET_FAVORITES'; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/browse/reducer.js
r5023 r5024 1 /** 2 * External dependencies. 3 */ 1 4 import { combineReducers } from 'redux'; 5 import union from 'lodash/union'; 2 6 3 7 /** 4 8 * Internal dependencies. 5 9 */ 6 import beta from './beta'; 7 import favorites from './favorites'; 8 import featured from './featured'; 9 import popular from './popular'; 10 import { BROWSE_RECEIVE } from 'state/action-types'; 11 12 const beta = ( state = [], action ) => { // jshint ignore:line 13 switch ( action.type ) { 14 case BROWSE_RECEIVE: 15 if ( 'beta' === action.term ) { 16 state = union( state, action.plugins ); 17 } 18 break; 19 } 20 21 return state; 22 }; 23 24 const favorites = ( state = [], action ) => { // jshint ignore:line 25 switch ( action.type ) { 26 case BROWSE_RECEIVE: 27 if ( 'favorites' === action.term ) { 28 state = union( state, action.plugins ); 29 } 30 break; 31 } 32 33 return state; 34 }; 35 36 const featured = ( state = [], action ) => { // jshint ignore:line 37 switch ( action.type ) { 38 case BROWSE_RECEIVE: 39 if ( 'featured' === action.term ) { 40 state = union( state, action.plugins ); 41 } 42 break; 43 } 44 45 return state; 46 }; 47 48 const popular = ( state = [], action ) => { // jshint ignore:line 49 switch ( action.type ) { 50 case BROWSE_RECEIVE: 51 if ( 'popular' === action.term ) { 52 state = union( state, action.plugins ); 53 } 54 break; 55 } 56 57 return state; 58 }; 10 59 11 60 export default combineReducers( { … … 13 62 favorites, 14 63 featured, 15 popular 64 popular, 16 65 } ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/favorites/reducer.js
r5023 r5024 1 import union from 'lodash/union'; 2 import without from 'lodash/without'; 1 /** 2 * External dependencies. 3 */ 4 import { uniq, without } from 'lodash'; 3 5 6 /** 7 * Internal dependencies. 8 */ 4 9 import { 5 10 FAVORITE_PLUGIN, 6 11 GET_FAVORITES, 7 UNFAVORITE_PLUGIN 8 } from ' actions/action-types';12 UNFAVORITE_PLUGIN, 13 } from 'state/action-types'; 9 14 10 const favorites = ( state = [], action ) => { // jshint ignore:line 11 15 const favorites = ( state = [], action ) => { 12 16 switch ( action.type ) { 13 17 case FAVORITE_PLUGIN: 14 18 case GET_FAVORITES: 15 state = uni on( state, state.concat( [ action.plugin ] ));19 state = uniq( [ ...state, action.plugin ] ); 16 20 break; 17 21 -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/pages/reducer.js
r5023 r5024 1 import find from 'lodash/find'; 1 /** 2 * External dependencies. 3 */ 4 import { find } from 'lodash'; 2 5 3 6 /** 4 7 * Internal dependencies. 5 8 */ 6 import { GET_PAGE } from 'actions/action-types';9 import { PAGE_RECEIVE } from 'state/action-types'; 7 10 8 const pages = ( state = [], action ) => { // jshint ignore:line 9 11 const pages = ( state = {}, action ) => { 10 12 switch ( action.type ) { 11 case GET_PAGE: 12 if ( ! find( state, { id: action.page.id } ) ) { 13 state = state.concat( [ action.page ] ); 13 case PAGE_RECEIVE: 14 const page = find( action.pages, { slug: action.slug } ); 15 if ( page ) { 16 state = { ...state, [ page.slug ]: page }; 14 17 } 15 18 break; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/plugins/reducer.js
r5023 r5024 1 import union from 'lodash/union'; 1 /** 2 * External dependencies. 3 */ 4 import { keyBy } from 'lodash'; 2 5 3 6 /** 4 7 * Internal dependencies. 5 8 */ 6 import { GET_PLUGIN } from 'actions/action-types'; 9 import { 10 PLUGIN_RECEIVE, 11 PLUGINS_RECEIVE, 12 } from 'state/action-types'; 7 13 8 const plugins = ( state = [], action ) => { // jshint ignore:line 14 const plugins = ( state = {}, action ) => { 15 switch ( action.type ) { 16 case PLUGIN_RECEIVE: 17 state = { ...state, [ action.plugin.slug ]: action.plugin }; 18 break; 9 19 10 switch ( action.type ) { 11 case GET_PLUGIN: 12 state = union( state, state.concat( [ action.plugin ] ) ); 20 case PLUGINS_RECEIVE: 21 state = { ...state, ...keyBy( action.plugins, 'slug' ) }; 13 22 break; 14 23 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/reducers.js
r5023 r5024 1 /** 2 * External dependencies. 3 */ 1 4 import { combineReducers } from 'redux'; 2 import { router Reducer } from 'react-router-redux';5 import { routerStateReducer } from 'redux-router'; 3 6 4 import browse from './browse/index'; 5 import favorites from './favorites'; 6 import pages from './pages'; 7 import plugins from './plugins'; 8 import search from './search'; 7 /** 8 * Internal dependencies. 9 */ 10 import browse from './browse/reducer'; 11 import favorites from './favorites/reducer'; 12 import pages from './pages/reducer'; 13 import plugins from './plugins/reducer'; 14 import search from './search/reducer'; 15 import sections from './sections/reducer'; 16 import user from './user/reducer'; 9 17 10 18 export default combineReducers( { … … 14 22 plugins, 15 23 search, 16 routing: routerReducer 24 sections, 25 router: routerStateReducer, 26 user, 17 27 } ); -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/search/actions.js
r5023 r5024 1 /** 2 * Internal dependencies. 3 */ 1 4 import Api from 'modules/api'; 2 5 import { 3 FAVORITE_PLUGIN, 4 GET_BROWSE, 5 GET_FAVORITES, 6 GET_PAGE, 7 GET_PLUGIN, 8 SEARCH_PLUGINS, 9 UNFAVORITE_PLUGIN 10 } from './action-types'; 6 SEARCH_RECEIVE, 7 SEARCH_REQUEST, 8 SEARCH_REQUEST_SUCCESS, 9 SEARCH_REQUEST_FAILURE, 10 } from 'state/action-types'; 11 11 12 export const getBrowse = ( type) => ( dispatch ) => {13 Api.get( '/plugins/v1/query-plugins', { browse: type }, ( data, error ) =>{14 if ( ! data.plugins.length || error ) {15 return;16 }12 export const fetchSearch = ( search ) => ( dispatch ) => { 13 dispatch( { 14 type: SEARCH_REQUEST, 15 search, 16 } ); 17 17 18 dispatch( { 19 type: GET_BROWSE, 20 plugins: data.plugins, 21 term: type 22 } ); 23 } ); 18 Api.plugin() 19 .then( ( plugins ) => { 20 dispatch( { 21 type: SEARCH_REQUEST_SUCCESS, 22 search, 23 } ); 24 dispatch( { 25 type: SEARCH_RECEIVE, 26 plugins, 27 search, 28 } ); 29 } ) 30 .catch( () => dispatch( { 31 type: SEARCH_REQUEST_FAILURE, 32 search, 33 } ) ); 24 34 }; 25 26 export const getFavorites = ( slug ) => ( dispatch ) => {27 Api.get( '/plugins/v1/plugin/' + slug + '/favorite', {}, ( data, error ) => {28 if ( ! data.favorite || error ) {29 return;30 }31 32 dispatch( {33 type: GET_FAVORITES,34 plugin: slug35 } );36 } );37 };38 39 export const favoritePlugin = ( slug ) => ( dispatch ) => {40 Api.get( '/plugins/v1/plugin/' + slug + '/favorite', { favorite: 1 }, ( data, error ) => {41 if ( ! data.favorite || error ) {42 return;43 }44 45 dispatch( {46 type: FAVORITE_PLUGIN,47 plugin: slug48 } );49 } );50 };51 52 export const unfavoritePlugin = ( slug ) => ( dispatch ) => {53 Api.get( '/plugins/v1/plugin/' + slug + '/favorite', { unfavorite: 1 }, ( data, error ) => {54 if ( ! data.favorite || error ) {55 return;56 }57 58 dispatch( {59 type: UNFAVORITE_PLUGIN,60 plugin: slug61 } );62 } );63 };64 65 export const getPage = ( slug ) => ( dispatch ) => {66 Api.get( '/wp/v2/pages', { filter: { name: slug } }, ( data, error ) => {67 if ( ! data.length || error ) {68 return;69 }70 71 dispatch( {72 type: GET_PAGE,73 page: data[0]74 } );75 } );76 };77 78 export const getPlugin = ( slug ) => ( dispatch ) => {79 Api.get( '/plugins/v1/plugin/' + slug, {}, ( data, error ) => {80 if ( ! data || error ) {81 return;82 }83 84 dispatch( {85 type: GET_PLUGIN,86 plugin: data87 } );88 } );89 };90 91 export const searchPlugins = ( searchTerm ) => ( dispatch ) => {92 Api.get( '/wp/v2/plugin', { search: searchTerm }, ( data, error ) => {93 if ( ! data || error ) {94 return;95 }96 97 dispatch( {98 type: SEARCH_PLUGINS,99 searchTerm: searchTerm,100 plugins: data101 } );102 } );103 }; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/state/search/reducer.js
r5023 r5024 3 3 * Internal dependencies. 4 4 */ 5 import { SEARCH_ PLUGINS } from 'actions/action-types';5 import { SEARCH_RECEIVE } from 'state/action-types'; 6 6 7 const plugins = ( state = {}, action ) => { // jshint ignore:line 8 7 const search = ( state = {}, action ) => { // jshint ignore:line 9 8 switch ( action.type ) { 10 case SEARCH_PLUGINS: 11 state = Object.assign( {}, state, { 12 [ action.searchTerm.toLowerCase() ] : action.plugins.map( plugin => ( plugin.slug ) ) 13 } ); 14 9 case SEARCH_RECEIVE: 10 state = { ...state, 11 [ action.search.toLowerCase() ]: action.plugins.map( ( plugin ) => plugin.slug ), 12 }; 15 13 break; 16 14 } … … 19 17 }; 20 18 21 export default plugins;19 export default search; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/styles/_components.scss
r4466 r5024 10 10 @import "../components/plugin/plugin-banner/style"; 11 11 @import "../components/plugin/sections/changelog/style"; 12 @import "../components/plugin/sections/committers/style";13 12 @import "../components/plugin/sections/developers/style"; 14 13 @import "../components/plugin/sections/faq/style"; -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/styles/modules/_accessibility.scss
r4278 r5024 28 28 29 29 /* Do not show the outline on the skip link target. */ 30 #content[tabindex="-1"]:focus {30 .site-content[tabindex="-1"]:focus { 31 31 outline: 0; 32 32 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/css/style-rtl.css
r4795 r5024 1408 1408 1409 1409 /* Do not show the outline on the skip link target. */ 1410 #content[tabindex="-1"]:focus {1410 .site-content[tabindex="-1"]:focus { 1411 1411 outline: 0; 1412 1412 } … … 1985 1985 display: none; 1986 1986 max-width: 128px; 1987 } 1988 1989 .entry-thumbnail .plugin-icon { 1990 -webkit-background-size: cover; 1991 background-size: cover; 1992 height: 128px; 1993 width: 128px; 1987 1994 } 1988 1995 … … 2219 2226 } 2220 2227 2221 #changelog {2228 .plugin-changelog { 2222 2229 font-size: 12.8px; 2223 2230 font-size: 0.8rem; 2224 2231 } 2225 2232 2226 #changelog code {2233 .plugin-changelog code { 2227 2234 font-size: 12.8px; 2228 2235 font-size: 0.8rem; 2229 2236 } 2230 2237 2231 #changelog h4 {2238 .plugin-changelog h4 { 2232 2239 margin-top: 0; 2233 }2234 2235 .contributors-list {2236 list-style: none;2237 margin: 0;2238 font-size: 0.9em;2239 }2240 2241 .contributors-list li {2242 padding-bottom: 0.5em;2243 2240 } 2244 2241 … … 2268 2265 } 2269 2266 2270 #faq h2:first-of-type {2267 .plugin-faq h2:first-of-type { 2271 2268 font-size: 20px; 2272 2269 font-size: 1.25rem; … … 2281 2278 } 2282 2279 2283 #faq dl {2280 .plugin-faq dl { 2284 2281 border-bottom: 1px solid #eee; 2285 2282 } 2286 2283 2287 #faq dt {2284 .plugin-faq dt { 2288 2285 border-top: 1px solid #eee; 2289 2286 cursor: pointer; … … 2295 2292 } 2296 2293 2297 #faq dt:before {2294 .plugin-faq dt:before { 2298 2295 content: "\f347"; 2299 2296 float: left; … … 2303 2300 } 2304 2301 2305 #faq dt.open:before {2302 .plugin-faq dt.open:before { 2306 2303 content: "\f343"; 2307 2304 } 2308 2305 2309 #faq dd {2306 .plugin-faq dd { 2310 2307 display: none; 2311 2308 margin: 0 0 16px; … … 2313 2310 } 2314 2311 2315 #faq dd p { 2312 .no-js .plugin-faq dd { 2313 display: block; 2314 } 2315 2316 .plugin-faq dd p { 2316 2317 margin: 0; 2317 2318 } 2318 2319 2319 #faq dd p + p {2320 .plugin-faq dd p + p { 2320 2321 margin-top: 16px; 2321 2322 margin-top: 1rem; 2322 }2323 2324 .no-js #faq dd {2325 display: block;2326 2323 } 2327 2324 … … 2633 2630 } 2634 2631 2635 .section.read-more #description {2632 .section.read-more.plugin-description { 2636 2633 max-height: 400px; 2637 2634 } 2638 2635 2639 .section.read-more #description.toggled {2636 .section.read-more.plugin-description.toggled { 2640 2637 max-height: none; 2641 2638 } … … 2643 2640 .section.read-more.toggled { 2644 2641 max-height: none; 2642 } 2643 2644 .no-js .section.read-more { 2645 max-height: none; 2646 overflow: auto; 2645 2647 } 2646 2648 … … 2685 2687 } 2686 2688 2687 .no-js .read-more {2688 overflow: auto;2689 max-height: none;2690 }2691 2692 2689 .section-toggle { 2693 2690 color: #0073aa; … … 2700 2697 } 2701 2698 2699 .no-js .section-toggle { 2700 display: none; 2701 } 2702 2702 2703 .section-toggle:after { 2703 2704 content: "\f347"; … … 2716 2717 .section-toggle:hover { 2717 2718 text-decoration: underline; 2718 }2719 2720 .no-js .section-toggle {2721 display: none;2722 2719 } 2723 2720 -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/css/style.css
r4777 r5024 1408 1408 1409 1409 /* Do not show the outline on the skip link target. */ 1410 #content[tabindex="-1"]:focus {1410 .site-content[tabindex="-1"]:focus { 1411 1411 outline: 0; 1412 1412 } … … 1985 1985 display: none; 1986 1986 max-width: 128px; 1987 } 1988 1989 .entry-thumbnail .plugin-icon { 1990 -webkit-background-size: cover; 1991 background-size: cover; 1992 height: 128px; 1993 width: 128px; 1987 1994 } 1988 1995 … … 2219 2226 } 2220 2227 2221 #changelog {2228 .plugin-changelog { 2222 2229 font-size: 12.8px; 2223 2230 font-size: 0.8rem; 2224 2231 } 2225 2232 2226 #changelog code {2233 .plugin-changelog code { 2227 2234 font-size: 12.8px; 2228 2235 font-size: 0.8rem; 2229 2236 } 2230 2237 2231 #changelog h4 {2238 .plugin-changelog h4 { 2232 2239 margin-top: 0; 2233 }2234 2235 .contributors-list {2236 list-style: none;2237 margin: 0;2238 font-size: 0.9em;2239 }2240 2241 .contributors-list li {2242 padding-bottom: 0.5em;2243 2240 } 2244 2241 … … 2268 2265 } 2269 2266 2270 #faq h2:first-of-type {2267 .plugin-faq h2:first-of-type { 2271 2268 font-size: 20px; 2272 2269 font-size: 1.25rem; … … 2281 2278 } 2282 2279 2283 #faq dl {2280 .plugin-faq dl { 2284 2281 border-bottom: 1px solid #eee; 2285 2282 } 2286 2283 2287 #faq dt {2284 .plugin-faq dt { 2288 2285 border-top: 1px solid #eee; 2289 2286 cursor: pointer; … … 2295 2292 } 2296 2293 2297 #faq dt:before {2294 .plugin-faq dt:before { 2298 2295 content: "\f347"; 2299 2296 float: right; … … 2303 2300 } 2304 2301 2305 #faq dt.open:before {2302 .plugin-faq dt.open:before { 2306 2303 content: "\f343"; 2307 2304 } 2308 2305 2309 #faq dd {2306 .plugin-faq dd { 2310 2307 display: none; 2311 2308 margin: 0 0 16px; … … 2313 2310 } 2314 2311 2315 #faq dd p { 2312 .no-js .plugin-faq dd { 2313 display: block; 2314 } 2315 2316 .plugin-faq dd p { 2316 2317 margin: 0; 2317 2318 } 2318 2319 2319 #faq dd p + p {2320 .plugin-faq dd p + p { 2320 2321 margin-top: 16px; 2321 2322 margin-top: 1rem; 2322 }2323 2324 .no-js #faq dd {2325 display: block;2326 2323 } 2327 2324 … … 2633 2630 } 2634 2631 2635 .section.read-more #description {2632 .section.read-more.plugin-description { 2636 2633 max-height: 400px; 2637 2634 } 2638 2635 2639 .section.read-more #description.toggled {2636 .section.read-more.plugin-description.toggled { 2640 2637 max-height: none; 2641 2638 } … … 2643 2640 .section.read-more.toggled { 2644 2641 max-height: none; 2642 } 2643 2644 .no-js .section.read-more { 2645 max-height: none; 2646 overflow: auto; 2645 2647 } 2646 2648 … … 2685 2687 } 2686 2688 2687 .no-js .read-more {2688 overflow: auto;2689 max-height: none;2690 }2691 2692 2689 .section-toggle { 2693 2690 color: #0073aa; … … 2700 2697 } 2701 2698 2699 .no-js .section-toggle { 2700 display: none; 2701 } 2702 2702 2703 .section-toggle:after { 2703 2704 content: "\f347"; … … 2716 2717 .section-toggle:hover { 2717 2718 text-decoration: underline; 2718 }2719 2720 .no-js .section-toggle {2721 display: none;2722 2719 } 2723 2720 … … 3415 3412 } 3416 3413 } 3417 /*# sourceMappingURL=style.css.map */ -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php
r4505 r5024 77 77 wp_enqueue_script( 'google-jsapi', 'https://www.google.com/jsapi', array(), false, true ); 78 78 wp_enqueue_script( 'wporg-plugins-stats', get_template_directory_uri() . '/js/stats.js', array( 'jquery', 'google-jsapi' ), '20161019', true ); 79 80 79 81 80 wp_localize_script( 'wporg-plugins-stats', 'pluginStats', array( … … 91 90 ), 92 91 ) ); 93 94 92 } 95 93 … … 97 95 if ( is_single() ) { 98 96 wp_enqueue_script( 'wporg-plugins-client', get_template_directory_uri() . '/js/theme.js', array(), false, true ); 99 wp_localize_script( 'wporg-plugins-client', 'app_data', array( 100 'api_url' => untrailingslashit( rest_url() ), 101 'nonce' => wp_create_nonce( 'wp_rest' ), 102 'base' => get_blog_details()->path, 97 wp_localize_script( 'wporg-plugins-client', 'pluginDirectory', array( 98 'endpoint' => untrailingslashit( rest_url() ), // 'https://wordpress.org/plugins-wp/wp-json', 99 'nonce' => wp_create_nonce( 'wp_rest' ), 100 'base' => get_blog_details()->path, 101 'userId' => get_current_user_id(), 102 ) ); 103 wp_localize_script( 'wporg-plugins-client', 'localeData', array( 104 '' => array( 105 'Plural-Forms' => _x( 'nplurals=2; plural=n != 1;', 'plural forms', 'wporg-plugins' ), 106 'Language' => _x( 'en', 'language (fr, fr_CA)', 'wporg-plugins' ), 107 'localeSlug' => _x( 'en', 'locale slug', 'wporg-plugins' ) , 108 ), 103 109 ) ); 104 110 } -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/js/section-accordion.js
r4465 r5024 35 35 } else { 36 36 // If the description starts with an embed/video, set the min-height to include it. 37 if ( 'description' === element.id && $section.children().next( 'p, div' ).first().find( 'video, iframe' ) ) {37 if ( 'description' === element.id && $section.children().next( 'p, div' ).first().find( 'video, iframe' ).length ) { 38 38 var height = $section.children().next( 'p,div' ).first().outerHeight( true ) /* embed */ + $section.children().first().outerHeight( true ) /* h2 */; 39 39 -
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/js/theme.js
r4506 r5024 1 !function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}( [function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}for(var o=n(2),a=r(o),i=n(30),s=n(162),u=r(s),l=document.querySelectorAll("#screenshots figure"),c=[],p=0;p<l.length;p++){var d=l[p].querySelector("figcaption"),f={src:l[p].querySelector("img.screenshot").src,caption:d?d.textContent:""};c.push(f)}c.length>0&&(0,i.render)(a["default"].createElement(u["default"],{screenshots:c}),document.getElementById("screenshots"))},function(e,t,n){"use strict";e.exports=n(3)},function(e,t,n){"use strict";var r=n(4),o=n(5),a=n(17),i=n(20),s=n(25),u=n(9),l=n(27),c=n(28),p=n(29),d=(n(11),u.createElement),f=u.createFactory,h=u.cloneElement,m=r,v={Children:{map:o.map,forEach:o.forEach,count:o.count,toArray:o.toArray,only:p},Component:a,createElement:d,cloneElement:h,isValidElement:u.isValidElement,PropTypes:l,createClass:i.createClass,createFactory:f,createMixin:function(e){return e},DOM:s,version:c,__spread:m};e.exports=v},function(e,t){"use strict";function n(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}function r(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(t).map(function(e){return t[e]});if("0123456789"!==r.join(""))return!1;var o={};return"abcdefghijklmnopqrst".split("").forEach(function(e){o[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},o)).join("")}catch(a){return!1}}var o=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;e.exports=r()?Object.assign:function(e,t){for(var r,i,s=n(e),u=1;u<arguments.length;u++){r=Object(arguments[u]);for(var l in r)o.call(r,l)&&(s[l]=r[l]);if(Object.getOwnPropertySymbols){i=Object.getOwnPropertySymbols(r);for(var c=0;c<i.length;c++)a.call(r,i[c])&&(s[i[c]]=r[i[c]])}}return s}},function(e,t,n){"use strict";function r(e){return(""+e).replace(_,"$&/")}function o(e,t){this.func=e,this.context=t,this.count=0}function a(e,t,n){var r=e.func,o=e.context;r.call(o,t,e.count++)}function i(e,t,n){if(null==e)return e;var r=o.getPooled(t,n);g(e,a,r),o.release(r)}function s(e,t,n,r){this.result=e,this.keyPrefix=t,this.func=n,this.context=r,this.count=0}function u(e,t,n){var o=e.result,a=e.keyPrefix,i=e.func,s=e.context,u=i.call(s,t,e.count++);Array.isArray(u)?l(u,o,n,v.thatReturnsArgument):null!=u&&(m.isValidElement(u)&&(u=m.cloneAndReplaceKey(u,a+(!u.key||t&&t.key===u.key?"":r(u.key)+"/")+n)),o.push(u))}function l(e,t,n,o,a){var i="";null!=n&&(i=r(n)+"/");var l=s.getPooled(t,i,o,a);g(e,u,l),s.release(l)}function c(e,t,n){if(null==e)return e;var r=[];return l(e,r,null,t,n),r}function p(e,t,n){return null}function d(e,t){return g(e,p,null)}function f(e){var t=[];return l(e,t,null,v.thatReturnsArgument),t}var h=n(6),m=n(9),v=n(12),g=n(14),y=h.twoArgumentPooler,b=h.fourArgumentPooler,_=/\/+/g;o.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},h.addPoolingTo(o,y),s.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},h.addPoolingTo(s,b);var C={forEach:i,map:c,mapIntoWithKeyPrefixInternal:l,count:d,toArray:f};e.exports=C},function(e,t,n){"use strict";var r=n(7),o=(n(8),function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)}),a=function(e,t){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,e,t),r}return new n(e,t)},i=function(e,t,n){var r=this;if(r.instancePool.length){var o=r.instancePool.pop();return r.call(o,e,t,n),o}return new r(e,t,n)},s=function(e,t,n,r){var o=this;if(o.instancePool.length){var a=o.instancePool.pop();return o.call(a,e,t,n,r),a}return new o(e,t,n,r)},u=function(e,t,n,r,o){var a=this;if(a.instancePool.length){var i=a.instancePool.pop();return a.call(i,e,t,n,r,o),i}return new a(e,t,n,r,o)},l=function(e){var t=this;e instanceof t?void 0:r("25"),e.destructor(),t.instancePool.length<t.poolSize&&t.instancePool.push(e)},c=10,p=o,d=function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||p,n.poolSize||(n.poolSize=c),n.release=l,n},f={addPoolingTo:d,oneArgumentPooler:o,twoArgumentPooler:a,threeArgumentPooler:i,fourArgumentPooler:s,fiveArgumentPooler:u};e.exports=f},function(e,t){"use strict";function n(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,r=0;r<t;r++)n+="&args[]="+encodeURIComponent(arguments[r+1]);n+=" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";var o=new Error(n);throw o.name="Invariant Violation",o.framesToPop=1,o}e.exports=n},function(e,t,n){"use strict";function r(e,t,n,r,o,a,i,s){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,a,i,s],c=0;u=new Error(t.replace(/%s/g,function(){return l[c++]})),u.name="Invariant Violation"}throw u.framesToPop=1,u}}e.exports=r},function(e,t,n){"use strict";function r(e){return void 0!==e.ref}function o(e){return void 0!==e.key}var a=n(4),i=n(10),s=(n(11),n(13),Object.prototype.hasOwnProperty),u="function"==typeof Symbol&&Symbol["for"]&&Symbol["for"]("react.element")||60103,l={key:!0,ref:!0,__self:!0,__source:!0},c=function(e,t,n,r,o,a,i){var s={$$typeof:u,type:e,key:t,ref:n,props:i,_owner:a};return s};c.createElement=function(e,t,n){var a,u={},p=null,d=null,f=null,h=null;if(null!=t){r(t)&&(d=t.ref),o(t)&&(p=""+t.key),f=void 0===t.__self?null:t.__self,h=void 0===t.__source?null:t.__source;for(a in t)s.call(t,a)&&!l.hasOwnProperty(a)&&(u[a]=t[a])}var m=arguments.length-2;if(1===m)u.children=n;else if(m>1){for(var v=Array(m),g=0;g<m;g++)v[g]=arguments[g+2];u.children=v}if(e&&e.defaultProps){var y=e.defaultProps;for(a in y)void 0===u[a]&&(u[a]=y[a])}return c(e,p,d,f,h,i.current,u)},c.createFactory=function(e){var t=c.createElement.bind(null,e);return t.type=e,t},c.cloneAndReplaceKey=function(e,t){var n=c(e.type,t,e.ref,e._self,e._source,e._owner,e.props);return n},c.cloneElement=function(e,t,n){var u,p=a({},e.props),d=e.key,f=e.ref,h=e._self,m=e._source,v=e._owner;if(null!=t){r(t)&&(f=t.ref,v=i.current),o(t)&&(d=""+t.key);var g;e.type&&e.type.defaultProps&&(g=e.type.defaultProps);for(u in t)s.call(t,u)&&!l.hasOwnProperty(u)&&(void 0===t[u]&&void 0!==g?p[u]=g[u]:p[u]=t[u])}var y=arguments.length-2;if(1===y)p.children=n;else if(y>1){for(var b=Array(y),_=0;_<y;_++)b[_]=arguments[_+2];p.children=b}return c(e.type,d,f,h,m,v,p)},c.isValidElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===u},c.REACT_ELEMENT_TYPE=u,e.exports=c},function(e,t){"use strict";var n={current:null};e.exports=n},function(e,t,n){"use strict";var r=n(12),o=r;e.exports=o},function(e,t){"use strict";function n(e){return function(){return e}}var r=function(){};r.thatReturns=n,r.thatReturnsFalse=n(!1),r.thatReturnsTrue=n(!0),r.thatReturnsNull=n(null),r.thatReturnsThis=function(){return this},r.thatReturnsArgument=function(e){return e},e.exports=r},function(e,t,n){"use strict";var r=!1;e.exports=r},function(e,t,n){"use strict";function r(e,t){return e&&"object"==typeof e&&null!=e.key?l.escape(e.key):t.toString(36)}function o(e,t,n,a){var d=typeof e;if("undefined"!==d&&"boolean"!==d||(e=null),null===e||"string"===d||"number"===d||s.isValidElement(e))return n(a,e,""===t?c+r(e,0):t),1;var f,h,m=0,v=""===t?c:t+p;if(Array.isArray(e))for(var g=0;g<e.length;g++)f=e[g],h=v+r(f,g),m+=o(f,h,n,a);else{var y=u(e);if(y){var b,_=y.call(e);if(y!==e.entries)for(var C=0;!(b=_.next()).done;)f=b.value,h=v+r(f,C++),m+=o(f,h,n,a);else for(;!(b=_.next()).done;){var E=b.value;E&&(f=E[1],h=v+l.escape(E[0])+p+r(f,0),m+=o(f,h,n,a))}}else if("object"===d){var x="",T=String(e);i("31","[object Object]"===T?"object with keys {"+Object.keys(e).join(", ")+"}":T,x)}}return m}function a(e,t,n){return null==e?0:o(e,"",t,n)}var i=n(7),s=(n(10),n(9)),u=n(15),l=(n(8),n(16)),c=(n(11),"."),p=":";e.exports=a},function(e,t){"use strict";function n(e){var t=e&&(r&&e[r]||e[o]);if("function"==typeof t)return t}var r="function"==typeof Symbol&&Symbol.iterator,o="@@iterator";e.exports=n},function(e,t){"use strict";function n(e){var t=/[=:]/g,n={"=":"=0",":":"=2"},r=(""+e).replace(t,function(e){return n[e]});return"$"+r}function r(e){var t=/(=0|=2)/g,n={"=0":"=","=2":":"},r="."===e[0]&&"$"===e[1]?e.substring(2):e.substring(1);return(""+r).replace(t,function(e){return n[e]})}var o={escape:n,unescape:r};e.exports=o},function(e,t,n){"use strict";function r(e,t,n){this.props=e,this.context=t,this.refs=i,this.updater=n||a}var o=n(7),a=n(18),i=(n(13),n(19));n(8),n(11);r.prototype.isReactComponent={},r.prototype.setState=function(e,t){"object"!=typeof e&&"function"!=typeof e&&null!=e?o("85"):void 0,this.updater.enqueueSetState(this,e),t&&this.updater.enqueueCallback(this,t,"setState")},r.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this),e&&this.updater.enqueueCallback(this,e,"forceUpdate")};e.exports=r},function(e,t,n){"use strict";function r(e,t){}var o=(n(11),{isMounted:function(e){return!1},enqueueCallback:function(e,t){},enqueueForceUpdate:function(e){r(e,"forceUpdate")},enqueueReplaceState:function(e,t){r(e,"replaceState")},enqueueSetState:function(e,t){r(e,"setState")}});e.exports=o},function(e,t,n){"use strict";var r={};e.exports=r},function(e,t,n){"use strict";function r(e,t){var n=E.hasOwnProperty(t)?E[t]:null;T.hasOwnProperty(t)&&(n!==_.OVERRIDE_BASE?p("73",t):void 0),e&&(n!==_.DEFINE_MANY&&n!==_.DEFINE_MANY_MERGED?p("74",t):void 0)}function o(e,t){if(t){"function"==typeof t?p("75"):void 0,h.isValidElement(t)?p("76"):void 0;var n=e.prototype,o=n.__reactAutoBindPairs;t.hasOwnProperty(b)&&x.mixins(e,t.mixins);for(var a in t)if(t.hasOwnProperty(a)&&a!==b){var i=t[a],l=n.hasOwnProperty(a);if(r(l,a),x.hasOwnProperty(a))x[a](e,i);else{var c=E.hasOwnProperty(a),d="function"==typeof i,f=d&&!c&&!l&&t.autobind!==!1;if(f)o.push(a,i),n[a]=i;else if(l){var m=E[a];!c||m!==_.DEFINE_MANY_MERGED&&m!==_.DEFINE_MANY?p("77",m,a):void 0,m===_.DEFINE_MANY_MERGED?n[a]=s(n[a],i):m===_.DEFINE_MANY&&(n[a]=u(n[a],i))}else n[a]=i}}}}function a(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in x;o?p("78",n):void 0;var a=n in e;a?p("79",n):void 0,e[n]=r}}}function i(e,t){e&&t&&"object"==typeof e&&"object"==typeof t?void 0:p("80");for(var n in t)t.hasOwnProperty(n)&&(void 0!==e[n]?p("81",n):void 0,e[n]=t[n]);return e}function s(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);if(null==n)return r;if(null==r)return n;var o={};return i(o,n),i(o,r),o}}function u(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}function l(e,t){var n=t.bind(e);return n}function c(e){for(var t=e.__reactAutoBindPairs,n=0;n<t.length;n+=2){var r=t[n],o=t[n+1];e[r]=l(e,o)}}var p=n(7),d=n(4),f=n(17),h=n(9),m=(n(21),n(23),n(18)),v=n(19),g=(n(8),n(22)),y=n(24),b=(n(11),y({mixins:null})),_=g({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),C=[],E={mixins:_.DEFINE_MANY,statics:_.DEFINE_MANY,propTypes:_.DEFINE_MANY,contextTypes:_.DEFINE_MANY,childContextTypes:_.DEFINE_MANY,getDefaultProps:_.DEFINE_MANY_MERGED,getInitialState:_.DEFINE_MANY_MERGED,getChildContext:_.DEFINE_MANY_MERGED,render:_.DEFINE_ONCE,componentWillMount:_.DEFINE_MANY,componentDidMount:_.DEFINE_MANY,componentWillReceiveProps:_.DEFINE_MANY,shouldComponentUpdate:_.DEFINE_ONCE,componentWillUpdate:_.DEFINE_MANY,componentDidUpdate:_.DEFINE_MANY,componentWillUnmount:_.DEFINE_MANY,updateComponent:_.OVERRIDE_BASE},x={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)o(e,t[n])},childContextTypes:function(e,t){e.childContextTypes=d({},e.childContextTypes,t)},contextTypes:function(e,t){e.contextTypes=d({},e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps?e.getDefaultProps=s(e.getDefaultProps,t):e.getDefaultProps=t},propTypes:function(e,t){e.propTypes=d({},e.propTypes,t)},statics:function(e,t){a(e,t)},autobind:function(){}},T={replaceState:function(e,t){this.updater.enqueueReplaceState(this,e),t&&this.updater.enqueueCallback(this,t,"replaceState")},isMounted:function(){return this.updater.isMounted(this)}},w=function(){};d(w.prototype,f.prototype,T);var N={createClass:function(e){var t=function(e,n,r){this.__reactAutoBindPairs.length&&c(this),this.props=e,this.context=n,this.refs=v,this.updater=r||m,this.state=null;var o=this.getInitialState?this.getInitialState():null;"object"!=typeof o||Array.isArray(o)?p("82",t.displayName||"ReactCompositeComponent"):void 0,this.state=o};t.prototype=new w,t.prototype.constructor=t,t.prototype.__reactAutoBindPairs=[],C.forEach(o.bind(null,t)),o(t,e),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),t.prototype.render?void 0:p("83");for(var n in E)t.prototype[n]||(t.prototype[n]=null);return t},injection:{injectMixin:function(e){C.push(e)}}};e.exports=N},function(e,t,n){"use strict";var r=n(22),o=r({prop:null,context:null,childContext:null});e.exports=o},function(e,t,n){"use strict";var r=n(8),o=function(e){var t,n={};e instanceof Object&&!Array.isArray(e)?void 0:r(!1);for(t in e)e.hasOwnProperty(t)&&(n[t]=t);return n};e.exports=o},function(e,t,n){"use strict";var r={};e.exports=r},function(e,t){"use strict";var n=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return t;return null};e.exports=n},function(e,t,n){"use strict";function r(e){return o.createFactory(e)}var o=n(9),a=n(26),i=a({a:"a",abbr:"abbr",address:"address",area:"area",article:"article",aside:"aside",audio:"audio",b:"b",base:"base",bdi:"bdi",bdo:"bdo",big:"big",blockquote:"blockquote",body:"body",br:"br",button:"button",canvas:"canvas",caption:"caption",cite:"cite",code:"code",col:"col",colgroup:"colgroup",data:"data",datalist:"datalist",dd:"dd",del:"del",details:"details",dfn:"dfn",dialog:"dialog",div:"div",dl:"dl",dt:"dt",em:"em",embed:"embed",fieldset:"fieldset",figcaption:"figcaption",figure:"figure",footer:"footer",form:"form",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",head:"head",header:"header",hgroup:"hgroup",hr:"hr",html:"html",i:"i",iframe:"iframe",img:"img",input:"input",ins:"ins",kbd:"kbd",keygen:"keygen",label:"label",legend:"legend",li:"li",link:"link",main:"main",map:"map",mark:"mark",menu:"menu",menuitem:"menuitem",meta:"meta",meter:"meter",nav:"nav",noscript:"noscript",object:"object",ol:"ol",optgroup:"optgroup",option:"option",output:"output",p:"p",param:"param",picture:"picture",pre:"pre",progress:"progress",q:"q",rp:"rp",rt:"rt",ruby:"ruby",s:"s",samp:"samp",script:"script",section:"section",select:"select",small:"small",source:"source",span:"span",strong:"strong",style:"style",sub:"sub",summary:"summary",sup:"sup",table:"table",tbody:"tbody",td:"td",textarea:"textarea",tfoot:"tfoot",th:"th",thead:"thead",time:"time",title:"title",tr:"tr",track:"track",u:"u",ul:"ul","var":"var",video:"video",wbr:"wbr",circle:"circle",clipPath:"clipPath",defs:"defs",ellipse:"ellipse",g:"g",image:"image",line:"line",linearGradient:"linearGradient",mask:"mask",path:"path",pattern:"pattern",polygon:"polygon",polyline:"polyline",radialGradient:"radialGradient",rect:"rect",stop:"stop",svg:"svg",text:"text",tspan:"tspan"},r);e.exports=i},function(e,t){"use strict";function n(e,t,n){if(!e)return null;var o={};for(var a in e)r.call(e,a)&&(o[a]=t.call(n,e[a],a,e));return o}var r=Object.prototype.hasOwnProperty;e.exports=n},function(e,t,n){"use strict";function r(e,t){return e===t?0!==e||1/e===1/t:e!==e&&t!==t}function o(e){function t(t,n,r,o,a,i){if(o=o||T,i=i||r,null==n[r]){var s=C[a];return t?new Error("Required "+s+" `"+i+"` was not specified in "+("`"+o+"`.")):null}return e(n,r,o,a,i)}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function a(e){function t(t,n,r,o,a){var i=t[n],s=g(i);if(s!==e){var u=C[o],l=y(i);return new Error("Invalid "+u+" `"+a+"` of type "+("`"+l+"` supplied to `"+r+"`, expected ")+("`"+e+"`."))}return null}return o(t)}function i(){return o(E.thatReturns(null))}function s(e){function t(t,n,r,o,a){if("function"!=typeof e)return new Error("Property `"+a+"` of component `"+r+"` has invalid PropType notation inside arrayOf.");var i=t[n];if(!Array.isArray(i)){var s=C[o],u=g(i);return new Error("Invalid "+s+" `"+a+"` of type "+("`"+u+"` supplied to `"+r+"`, expected an array."))}for(var l=0;l<i.length;l++){var c=e(i,l,r,o,a+"["+l+"]");if(c instanceof Error)return c}return null}return o(t)}function u(){function e(e,t,n,r,o){if(!_.isValidElement(e[t])){var a=C[r];return new Error("Invalid "+a+" `"+o+"` supplied to "+("`"+n+"`, expected a single ReactElement."))}return null}return o(e)}function l(e){function t(t,n,r,o,a){if(!(t[n]instanceof e)){var i=C[o],s=e.name||T,u=b(t[n]);return new Error("Invalid "+i+" `"+a+"` of type "+("`"+u+"` supplied to `"+r+"`, expected ")+("instance of `"+s+"`."))}return null}return o(t)}function c(e){function t(t,n,o,a,i){for(var s=t[n],u=0;u<e.length;u++)if(r(s,e[u]))return null;var l=C[a],c=JSON.stringify(e);return new Error("Invalid "+l+" `"+i+"` of value `"+s+"` "+("supplied to `"+o+"`, expected one of "+c+"."))}return o(Array.isArray(e)?t:function(){return new Error("Invalid argument supplied to oneOf, expected an instance of array.")})}function p(e){function t(t,n,r,o,a){if("function"!=typeof e)return new Error("Property `"+a+"` of component `"+r+"` has invalid PropType notation inside objectOf.");var i=t[n],s=g(i);if("object"!==s){var u=C[o];return new Error("Invalid "+u+" `"+a+"` of type "+("`"+s+"` supplied to `"+r+"`, expected an object."))}for(var l in i)if(i.hasOwnProperty(l)){var c=e(i,l,r,o,a+"."+l);if(c instanceof Error)return c}return null}return o(t)}function d(e){function t(t,n,r,o,a){for(var i=0;i<e.length;i++){var s=e[i];if(null==s(t,n,r,o,a))return null}var u=C[o];return new Error("Invalid "+u+" `"+a+"` supplied to "+("`"+r+"`."))}return o(Array.isArray(e)?t:function(){return new Error("Invalid argument supplied to oneOfType, expected an instance of array.")})}function f(){function e(e,t,n,r,o){if(!m(e[t])){var a=C[r];return new Error("Invalid "+a+" `"+o+"` supplied to "+("`"+n+"`, expected a ReactNode."))}return null}return o(e)}function h(e){function t(t,n,r,o,a){var i=t[n],s=g(i);if("object"!==s){var u=C[o];return new Error("Invalid "+u+" `"+a+"` of type `"+s+"` "+("supplied to `"+r+"`, expected `object`."))}for(var l in e){var c=e[l];if(c){var p=c(i,l,r,o,a+"."+l);if(p)return p}}return null}return o(t)}function m(e){switch(typeof e){case"number":case"string":case"undefined":return!0;case"boolean":return!e;case"object":if(Array.isArray(e))return e.every(m);if(null===e||_.isValidElement(e))return!0;var t=x(e);if(!t)return!1;var n,r=t.call(e);if(t!==e.entries){for(;!(n=r.next()).done;)if(!m(n.value))return!1}else for(;!(n=r.next()).done;){var o=n.value;if(o&&!m(o[1]))return!1}return!0;default:return!1}}function v(e,t){return"symbol"===e||("Symbol"===t["@@toStringTag"]||"function"==typeof Symbol&&t instanceof Symbol)}function g(e){var t=typeof e;return Array.isArray(e)?"array":e instanceof RegExp?"object":v(t,e)?"symbol":t}function y(e){var t=g(e);if("object"===t){if(e instanceof Date)return"date";if(e instanceof RegExp)return"regexp"}return t}function b(e){return e.constructor&&e.constructor.name?e.constructor.name:T}var _=n(9),C=n(23),E=n(12),x=n(15),T="<<anonymous>>",w={array:a("array"),bool:a("boolean"),func:a("function"),number:a("number"),object:a("object"),string:a("string"),symbol:a("symbol"),any:i(),arrayOf:s,element:u(),instanceOf:l,node:f(),objectOf:p,oneOf:c,oneOfType:d,shape:h};e.exports=w},function(e,t){"use strict";e.exports="15.2.1"},function(e,t,n){"use strict";function r(e){return a.isValidElement(e)?void 0:o("23"),e}var o=n(7),a=n(9);n(8);e.exports=r},function(e,t,n){"use strict";e.exports=n(31)},function(e,t,n){"use strict";var r=n(32),o=n(35),a=n(154),i=n(55),s=n(52),u=n(28),l=n(159),c=n(160),p=n(161);n(11);o.inject();var d={findDOMNode:l,render:a.render,unmountComponentAtNode:a.unmountComponentAtNode,version:u,unstable_batchedUpdates:s.batchedUpdates,unstable_renderSubtreeIntoContainer:p};"undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject&&__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ComponentTree:{getClosestInstanceFromNode:r.getClosestInstanceFromNode,getNodeFromInstance:function(e){return e._renderedComponent&&(e=c(e)),e?r.getNodeFromInstance(e):null}},Mount:a,Reconciler:i});e.exports=d},function(e,t,n){"use strict";function r(e){for(var t;t=e._renderedComponent;)e=t;return e}function o(e,t){var n=r(e);n._hostNode=t,t[m]=n}function a(e){var t=e._hostNode;t&&(delete t[m],e._hostNode=null)}function i(e,t){if(!(e._flags&h.hasCachedChildNodes)){var n=e._renderedChildren,a=t.firstChild;e:for(var i in n)if(n.hasOwnProperty(i)){var s=n[i],u=r(s)._domID;if(null!=u){for(;null!==a;a=a.nextSibling)if(1===a.nodeType&&a.getAttribute(f)===String(u)||8===a.nodeType&&a.nodeValue===" react-text: "+u+" "||8===a.nodeType&&a.nodeValue===" react-empty: "+u+" "){o(s,a);continue e}c("32",u)}}e._flags|=h.hasCachedChildNodes}}function s(e){if(e[m])return e[m];for(var t=[];!e[m];){if(t.push(e),!e.parentNode)return null;e=e.parentNode}for(var n,r;e&&(r=e[m]);e=t.pop())n=r,t.length&&i(r,e);return n}function u(e){var t=s(e);return null!=t&&t._hostNode===e?t:null}function l(e){if(void 0===e._hostNode?c("33"):void 0,e._hostNode)return e._hostNode;for(var t=[];!e._hostNode;)t.push(e),e._hostParent?void 0:c("34"),e=e._hostParent;for(;t.length;e=t.pop())i(e,e._hostNode);return e._hostNode}var c=n(7),p=n(33),d=n(34),f=(n(8),p.ID_ATTRIBUTE_NAME),h=d,m="__reactInternalInstance$"+Math.random().toString(36).slice(2),v={getClosestInstanceFromNode:s,getInstanceFromNode:u,getNodeFromInstance:l,precacheChildNodes:i,precacheNode:o,uncacheNode:a};e.exports=v},function(e,t,n){"use strict";function r(e,t){return(e&t)===t}var o=n(7),a=(n(8),{MUST_USE_PROPERTY:1,HAS_BOOLEAN_VALUE:4,HAS_NUMERIC_VALUE:8,HAS_POSITIVE_NUMERIC_VALUE:24,HAS_OVERLOADED_BOOLEAN_VALUE:32,injectDOMPropertyConfig:function(e){var t=a,n=e.Properties||{},i=e.DOMAttributeNamespaces||{},u=e.DOMAttributeNames||{},l=e.DOMPropertyNames||{},c=e.DOMMutationMethods||{};e.isCustomAttribute&&s._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var p in n){s.properties.hasOwnProperty(p)?o("48",p):void 0;var d=p.toLowerCase(),f=n[p],h={attributeName:d,attributeNamespace:null,propertyName:p,mutationMethod:null,mustUseProperty:r(f,t.MUST_USE_PROPERTY),hasBooleanValue:r(f,t.HAS_BOOLEAN_VALUE),hasNumericValue:r(f,t.HAS_NUMERIC_VALUE),hasPositiveNumericValue:r(f,t.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:r(f,t.HAS_OVERLOADED_BOOLEAN_VALUE)};if(h.hasBooleanValue+h.hasNumericValue+h.hasOverloadedBooleanValue<=1?void 0:o("50",p),u.hasOwnProperty(p)){var m=u[p];h.attributeName=m}i.hasOwnProperty(p)&&(h.attributeNamespace=i[p]),l.hasOwnProperty(p)&&(h.propertyName=l[p]),c.hasOwnProperty(p)&&(h.mutationMethod=c[p]),s.properties[p]=h}}}),i=":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",s={ID_ATTRIBUTE_NAME:"data-reactid",ROOT_ATTRIBUTE_NAME:"data-reactroot",ATTRIBUTE_NAME_START_CHAR:i,ATTRIBUTE_NAME_CHAR:i+"\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<s._isCustomAttributeFunctions.length;t++){var n=s._isCustomAttributeFunctions[t];if(n(e))return!0}return!1},injection:a};e.exports=s},function(e,t){"use strict";var n={hasCachedChildNodes:1};e.exports=n},function(e,t,n){"use strict";function r(){E||(E=!0,g.EventEmitter.injectReactEventListener(v),g.EventPluginHub.injectEventPluginOrder(i),g.EventPluginUtils.injectComponentTree(p),g.EventPluginUtils.injectTreeTraversal(f),g.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:C,EnterLeaveEventPlugin:s,ChangeEventPlugin:a,SelectEventPlugin:_,BeforeInputEventPlugin:o}),g.HostComponent.injectGenericComponentClass(c),g.HostComponent.injectTextComponentClass(h),g.DOMProperty.injectDOMPropertyConfig(u),g.DOMProperty.injectDOMPropertyConfig(b),g.EmptyComponent.injectEmptyComponentFactory(function(e){return new d(e)}),g.Updates.injectReconcileTransaction(y),g.Updates.injectBatchingStrategy(m),g.Component.injectEnvironment(l))}var o=n(36),a=n(51),i=n(63),s=n(64),u=n(69),l=n(70),c=n(84),p=n(32),d=n(125),f=n(126),h=n(127),m=n(128),v=n(129),g=n(132),y=n(133),b=n(141),_=n(142),C=n(143),E=!1;e.exports={inject:r}},function(e,t,n){"use strict";function r(){var e=window.opera;return"object"==typeof e&&"function"==typeof e.version&&parseInt(e.version(),10)<=12}function o(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}function a(e){switch(e){case P.topCompositionStart:return S.compositionStart;case P.topCompositionEnd:return S.compositionEnd;case P.topCompositionUpdate:return S.compositionUpdate}}function i(e,t){return e===P.topKeyDown&&t.keyCode===C}function s(e,t){switch(e){case P.topKeyUp:return _.indexOf(t.keyCode)!==-1;case P.topKeyDown:return t.keyCode!==C;case P.topKeyPress:case P.topMouseDown:case P.topBlur:return!0;default:return!1}}function u(e){var t=e.detail;return"object"==typeof t&&"data"in t?t.data:null}function l(e,t,n,r){var o,l;if(E?o=a(e):I?s(e,n)&&(o=S.compositionEnd):i(e,n)&&(o=S.compositionStart),!o)return null;w&&(I||o!==S.compositionStart?o===S.compositionEnd&&I&&(l=I.getData()):I=v.getPooled(r));var c=g.getPooled(o,t,n,r);if(l)c.data=l;else{var p=u(n);null!==p&&(c.data=p)}return h.accumulateTwoPhaseDispatches(c),c}function c(e,t){switch(e){case P.topCompositionEnd:return u(t);case P.topKeyPress:var n=t.which;return n!==N?null:(M=!0,k);case P.topTextInput:var r=t.data;return r===k&&M?null:r;default:return null}}function p(e,t){if(I){if(e===P.topCompositionEnd||s(e,t)){var n=I.getData();return v.release(I),I=null,n}return null}switch(e){case P.topPaste:return null;case P.topKeyPress:return t.which&&!o(t)?String.fromCharCode(t.which):null;case P.topCompositionEnd:return w?null:t.data;default:return null}}function d(e,t,n,r){var o;if(o=T?c(e,n):p(e,n),!o)return null;var a=y.getPooled(S.beforeInput,t,n,r);return a.data=o,h.accumulateTwoPhaseDispatches(a),a}var f=n(37),h=n(38),m=n(45),v=n(46),g=n(48),y=n(50),b=n(24),_=[9,13,27,32],C=229,E=m.canUseDOM&&"CompositionEvent"in window,x=null;m.canUseDOM&&"documentMode"in document&&(x=document.documentMode);var T=m.canUseDOM&&"TextEvent"in window&&!x&&!r(),w=m.canUseDOM&&(!E||x&&x>8&&x<=11),N=32,k=String.fromCharCode(N),P=f.topLevelTypes,S={beforeInput:{phasedRegistrationNames:{bubbled:b({onBeforeInput:null}),captured:b({onBeforeInputCapture:null})},dependencies:[P.topCompositionEnd,P.topKeyPress,P.topTextInput,P.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:b({onCompositionEnd:null}),captured:b({onCompositionEndCapture:null})},dependencies:[P.topBlur,P.topCompositionEnd,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:b({onCompositionStart:null}),captured:b({onCompositionStartCapture:null})},dependencies:[P.topBlur,P.topCompositionStart,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:b({onCompositionUpdate:null}),captured:b({onCompositionUpdateCapture:null})},dependencies:[P.topBlur,P.topCompositionUpdate,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]}},M=!1,I=null,R={eventTypes:S,extractEvents:function(e,t,n,r){return[l(e,t,n,r),d(e,t,n,r)]}};e.exports=R},function(e,t,n){"use strict";var r=n(22),o=r({bubbled:null,captured:null}),a=r({topAbort:null,topAnimationEnd:null,topAnimationIteration:null,topAnimationStart:null,topBlur:null,topCanPlay:null,topCanPlayThrough:null,topChange:null,topClick:null,topCompositionEnd:null,topCompositionStart:null,topCompositionUpdate:null,topContextMenu:null,topCopy:null,topCut:null,topDoubleClick:null,topDrag:null,topDragEnd:null,topDragEnter:null,topDragExit:null,topDragLeave:null,topDragOver:null,topDragStart:null,topDrop:null,topDurationChange:null,topEmptied:null,topEncrypted:null,topEnded:null,topError:null,topFocus:null,topInput:null,topInvalid:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topLoad:null,topLoadedData:null,topLoadedMetadata:null,topLoadStart:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topPaste:null,topPause:null,topPlay:null,topPlaying:null,topProgress:null,topRateChange:null,topReset:null,topScroll:null,topSeeked:null,topSeeking:null,topSelectionChange:null,topStalled:null,topSubmit:null,topSuspend:null,topTextInput:null,topTimeUpdate:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null,topTransitionEnd:null,topVolumeChange:null,topWaiting:null,topWheel:null}),i={topLevelTypes:a,PropagationPhases:o};e.exports=i},function(e,t,n){"use strict";function r(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return b(e,r)}function o(e,t,n){var o=t?y.bubbled:y.captured,a=r(e,n,o);a&&(n._dispatchListeners=v(n._dispatchListeners,a),n._dispatchInstances=v(n._dispatchInstances,e))}function a(e){e&&e.dispatchConfig.phasedRegistrationNames&&m.traverseTwoPhase(e._targetInst,o,e)}function i(e){if(e&&e.dispatchConfig.phasedRegistrationNames){var t=e._targetInst,n=t?m.getParentInstance(t):null;m.traverseTwoPhase(n,o,e)}}function s(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=b(e,r);o&&(n._dispatchListeners=v(n._dispatchListeners,o),n._dispatchInstances=v(n._dispatchInstances,e))}}function u(e){e&&e.dispatchConfig.registrationName&&s(e._targetInst,null,e)}function l(e){g(e,a)}function c(e){g(e,i)}function p(e,t,n,r){m.traverseEnterLeave(n,r,s,e,t)}function d(e){g(e,u)}var f=n(37),h=n(39),m=n(41),v=n(43),g=n(44),y=(n(11),f.PropagationPhases),b=h.getListener,_={accumulateTwoPhaseDispatches:l,accumulateTwoPhaseDispatchesSkipTarget:c,accumulateDirectDispatches:d,accumulateEnterLeaveDispatches:p};e.exports=_},function(e,t,n){"use strict";var r=n(7),o=n(40),a=n(41),i=n(42),s=n(43),u=n(44),l=(n(8),{}),c=null,p=function(e,t){e&&(a.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e))},d=function(e){return p(e,!0)},f=function(e){return p(e,!1)},h={injection:{injectEventPluginOrder:o.injectEventPluginOrder,injectEventPluginsByName:o.injectEventPluginsByName},putListener:function(e,t,n){"function"!=typeof n?r("94",t,typeof n):void 0;var a=l[t]||(l[t]={});a[e._rootNodeID]=n;var i=o.registrationNameModules[t];i&&i.didPutListener&&i.didPutListener(e,t,n)},getListener:function(e,t){var n=l[t];return n&&n[e._rootNodeID]},deleteListener:function(e,t){var n=o.registrationNameModules[t];n&&n.willDeleteListener&&n.willDeleteListener(e,t);var r=l[t];r&&delete r[e._rootNodeID]},deleteAllListeners:function(e){for(var t in l)if(l.hasOwnProperty(t)&&l[t][e._rootNodeID]){var n=o.registrationNameModules[t];n&&n.willDeleteListener&&n.willDeleteListener(e,t),delete l[t][e._rootNodeID]}},extractEvents:function(e,t,n,r){for(var a,i=o.plugins,u=0;u<i.length;u++){var l=i[u];if(l){var c=l.extractEvents(e,t,n,r);c&&(a=s(a,c))}}return a},enqueueEvents:function(e){e&&(c=s(c,e))},processEventQueue:function(e){var t=c;c=null,e?u(t