Introduce aurora-core

This commit is contained in:
misund committed 2017-04-09 12:48:07 +02:00
1 parent e669040286
commit 6da788f09a
112 files changed
+3872

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
{
"presets": [
"es2015",
"stage-0",
"react"
]
}
+9
View File
@@ -0,0 +1,9 @@
[*]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
+6
View File
@@ -0,0 +1,6 @@
# Tests
**/*.test.*.js
**/*.test.*.jsx
# Dummy router
src/services/dummy-router.js
+41
View File
@@ -0,0 +1,41 @@
{
"env": {
"browser": true,
"node": true,
"es6": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"jsx": true,
"experimentalObjectRestSpread": true
},
},
"plugins": [
"react"
],
"rules": {
"comma-dangle": [0],
"no-dupe-args": [2],
"no-dupe-keys": [2],
"no-duplicate-case": [2],
"no-extra-semi": [2],
"no-irregular-whitespace": [0],
"no-undef": [2],
"valid-typeof": [2],
"curly": [0],
"dot-notation": [1],
"eqeqeq": [2],
"semi": [2, "always"],
"quotes": [1, "single"],
"no-unused-vars": [1],
"array-bracket-spacing": [2, "never"],
"brace-style": [2],
"comma-spacing": [2],
"comma-style": [2],
"one-var": [2, "never"],
"no-shadow": 0,
"arrow-body-style": 0,
"react/jsx-max-props-per-line": [2, {"maximum": 5}]
}
}
+52
View File
@@ -0,0 +1,52 @@
{
"extends": "airbnb",
"parser": "babel-eslint",
"env": {
"browser": true,
"node": true
},
"settings": {
"ecmascript": 6,
"jsx": true
},
"plugins": [
"react"
],
"globals": {
"before": true,
"assert": true,
"path": true
},
"rules": {
"jsx-a11y/img-uses-alt": 0,
"jsx-a11y/redundant-alt": 0,
"jsx-a11y/valid-aria-role": 0,
"arrow-body-style": [0],
"comma-dangle": [2, "always-multiline"],
"import/extensions": [2, "never"],
"func-names": 2,
"global-require": 1,
"max-len": [1, 120, 2, {"ignoreComments": true}],
"new-cap": [1, { "capIsNew": false }],
"no-unused-expressions": 0,
"no-unused-vars": ["error"],
"no-cond-assign": [2, "except-parens"],
"no-extra-strict": 0,
"no-mixed-operators": ["error", {"allowSamePrecedence": true}],
"no-multi-spaces": 0,
"no-param-reassign": 0,
"no-shadow": [0],
"no-unneeded-ternary": [2, {"defaultAssignment": true}],
"no-unused-vars": [1, {"vars": "local", "args": "none"}],
"no-use-before-define": ["error", "nofunc"],
"no-use-before-define": ["error", { "functions": false, "classes": true }],
"quote-props": [1, "consistent-as-needed"],
"radix": 0,
"react/jsx-indent": [2, 2],
"react/no-array-index-key": 0,
"react/no-unused-prop-types": 1,
"react/prefer-es6-class": 0,
"react/require-extension": [0, { "extensions": [".jsx"] }],
"space-infix-ops": 0
}
}
+66
View File
@@ -0,0 +1,66 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
dist
out
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Shellscripts
#####################
*.sh
# Custom
#####################
/node_modules
/public/static/*.js
/public/static/*.css
/public/static/*.map
/public/static/*.app.js
# Generated bundle hash file
############################
.build
# Editors
#########
.idea
*.iml
# ESLint
########
.jshintrc
eslintrc.json-ci-runner
+32
View File
@@ -0,0 +1,32 @@
Aurora Core Frontend Demo
=========================
Demo implementation of a frontend conforming to [aurora-core](https://github.com/soldotno/aurora-core) specifications.
#### Install dependencies
* [Install node.js (5.x)](https://nodejs.org/)
* `npm install`
#### Development shellscript example:
```sh
#!/bin/sh
export PORT=3000
export HOSTNAME="localhost"
export DEBUG="*,-babel"
export NODE_ENV="development"
export API_URL="http://localhost:3001"
npm run develop
```
#### Production shellscript example:
```sh
#!/bin/sh
export PORT=3000
export HOSTNAME="localhost"
export DEBUG="*,-babel"
export NODE_ENV="production"
export API_URL="http://localhost:3001"
npm run build && npm start
```
+8
View File
@@ -0,0 +1,8 @@
const config = {
port: process.env.PORT || 3000,
hostname: process.env.HOSTNAME || 'localhost',
apiUrl: process.env.API_URL || 'http://localhost::3001',
nodeEnv: process.env.NODE_ENV || 'development',
};
module.exports = config;
+18
View File
@@ -0,0 +1,18 @@
const port = require('./config').port;
const webpackConfig = require('./webpack.config');
/**
* Environment
*/
/**
* Import / run the dev server
*/
require('aurora-core/dev-server')({
webpackConfig,
port,
onListen(err) { // eslint-disable-line consistent-return
if (err) return console.log(err);
console.log('Listening at localhost:', port);
},
});
+9
View File
@@ -0,0 +1,9 @@
/**
* Import the existing webpack config
*/
var webpackConfig = require('./webpack.config.js');
/**
* Export the karma config (with the webpack config injected)
*/
module.exports = require('aurora-core/karma.conf.js').extend(webpackConfig);
+110
View File
@@ -0,0 +1,110 @@
{
"name": "aurora-demo-frontend",
"version": "1.0.0",
"description": "SOL frontpage frontend application",
"main": "app.js",
"engines": {
"node": "7.7.4"
},
"scripts": {
"test": "npm run test:server && npm run test:client",
"test:client": "karma start",
"test:server": "mocha --require babel-register \"./src/**/*.test.server.js\"",
"watch:test": "karma start --no-single-run --browsers Firefox",
"test:lint": "eslint src/**/*.js*",
"pretest": "npm run test:lint",
"build": "webpack",
"postinstall": "npm run build",
"start": "node ./src/server-bootstrap",
"develop": "node dev-server"
},
"repository": {
"type": "git",
"url": "https://github.com/soldotno/aurora-demo-frontend.git"
},
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/soldotno/aurora-demo-frontend/issues"
},
"homepage": "https://github.com/soldotno/aurora-demo-frontend",
"dependencies": {
"aurora-core": "2.0.2",
"aurora-sass-loader": "github:soldotno/aurora-sass-loader#master",
"autoprefixer": "6.7.7",
"axios": "0.16.0",
"babel": "6.0.15",
"babel-cli": "6.24.0",
"babel-core": "6.24.0",
"babel-eslint": "7.2.1",
"babel-loader": "6.4.1",
"babel-polyfill": "6.23.0",
"babel-preset-es2015": "6.24.0",
"babel-preset-react": "6.23.0",
"babel-preset-stage-0": "6.22.0",
"babel-runtime": "6.23.0",
"bluebird": "3.5.0",
"classnames": "2.2.5",
"compression": "1.6.2",
"cookie-parser": "1.4.3",
"css-loader": "0.28.0",
"debug": "2.6.3",
"es5-shim": "4.5.9",
"express": "4.15.2",
"express-useragent": "1.0.7",
"is-client": "0.0.2",
"isomorphic-ensure": "1.0.1",
"js-cookie": "2.1.4",
"location-bar": "3.0.1",
"lodash": "4.17.4",
"lodash.compose": "2.4.1",
"lodash.set": "4.3.2",
"md5": "2.2.1",
"moment": "2.18.1",
"ms": "1.0.0",
"newrelic": "1.38.2",
"no-op": "1.0.3",
"node-sass": "4.5.2",
"postcss-loader": "1.3.3",
"progress-bar-webpack-plugin": "1.9.3",
"qs": "6.4.0",
"query-string": "4.2.2",
"react": "15.4.2",
"react-dom": "15.4.2",
"react-hot-loader": "1.3.1",
"react-redux": "5.0.3",
"redis": "2.7.1",
"redux": "3.6.0",
"redux-logger": "3.0.1",
"redux-thunk": "2.2.0",
"sass-loader": "6.0.3",
"serve-favicon": "2.4.2",
"stringify-clone": "2.0.0",
"style-loader": "0.16.1",
"url-join": "1.1.0",
"url-parse": "1.1.8",
"uuid": "3.0.1",
"uuid-validate": "0.0.2",
"webpack": "2.3.3"
},
"devDependencies": {
"eslint": "3.19.0",
"eslint-config-airbnb": "14.1.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "4.0.0",
"eslint-plugin-react": "6.10.3",
"expect": "1.20.2",
"expect-jsx": "3.0.0",
"inject-loader": "3.0.0",
"karma": "1.6.0",
"karma-chrome-launcher": "2.0.0",
"karma-firefox-launcher": "1.0.1",
"karma-mocha": "1.3.0",
"karma-mocha-reporter": "2.2.3",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "2.0.3",
"mocha": "3.2.0",
"mockery": "2.0.0",
"webpack-dev-server": "2.4.2"
}
}
+12
View File
@@ -0,0 +1,12 @@
/* eslint-disable no-var */
var autoprefixer = require('autoprefixer');
module.exports = {
plugins: [
autoprefixer({
browsers: [
'last 3 versions',
],
}),
],
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Aurora Frontend Demo (development)</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<link rel="icon" type="image/png" href="/images/touch-icon-ipad.png">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/static/app.js"></script>
</body>
</html>
+42
View File
@@ -0,0 +1,42 @@
/**
* Polyfills and shims
*/
require('es5-shim/es5-shim');
require('es5-shim/es5-sham');
require('babel-polyfill');
/**
* Use bluebird for better error handling in development
*/
if (__DEVELOPMENT__) {
/**
* Use bluebird for promises
*/
window.Promise = require('bluebird');
/**
* Suppress warnings of runaway Promises.
* Bug when used together with Babel causes
* harmless and non-applicative (but annyoing) warnings..
*/
Promise.config({
warnings: false
});
/**
* Globally handle unhandled promise rejections
*/
window.addEventListener('unhandledrejection', function(e) {
e.preventDefault();
throw e.detail.reason;
});
}
/**
* Initialize and render the client app
*/
require('aurora-core/dist/render/client')({
getRoute: require('./services/get-route-config'),
getModule: require('./modules/get-module'),
isVisible: require('./utils/is-visible'),
});
+109
View File
@@ -0,0 +1,109 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Aurora specific mixin to conveniently
* render modules for higher order components
*/
const RenderChildrenMixin = require('aurora-core/dist/mixins/render-children-mixin');
/**
* Import shared components
*/
const VersionAlert = require('../../shared-components/VersionAlert.jsx');
/**
* An app module
* that should be used as a
* top level module
* in the config
*/
const DemoAppModule = React.createClass({
/**
* These are all Aurora-specific mixins
* to include different functionality
* that the module needs
*/
mixins: [
RenderChildrenMixin()
],
propTypes: {
pagination: React.PropTypes.shape({
isLoading: React.PropTypes.bool
}),
newVersionAvailable: React.PropTypes.bool,
},
getDefaultProps() {
return {
pagination: {
isLoading: false
},
newVersionAvailable: false,
};
},
render() {
const {
pagination: { isLoading },
newVersionAvailable,
} = this.props;
return (
<main style={{ height: '101vh' }}>
{newVersionAvailable && <VersionAlert />}
{/* the function below is exposed by render-modules-mixin */}
{this.renderChildren()}
{isLoading && <div>Loading...</div>}
</main>
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-app-styles.scss`,
clientStyles: isBrowser && require('./styles/my-app-styles.scss'),
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
}),
);
/**
* Finally export the module
* extended with Aurora functionality
*/
module.exports = extendWithAuroraFunctionality(DemoAppModule);
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
+78
View File
@@ -0,0 +1,78 @@
Aurora App Module Template
==========================
A module template for building top level Aurora app modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
__NOTE:__
An app module means that your module renders other modules passed into it, and has an array of `modules` in `options`.
#### Include it in the module-map to enable use
```js
// ./src/modules/module-map.js
const moduleMap = {
'my-app-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyAppModule/MyAppModule.jsx'));
});
},
...
};
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-app-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....',
modules: [...] // other modules
}
}
```
#### Document the module interface
```js
<MyAppModule
a={'...'}
b={'....'}
c={'.....'}
modules={[...]}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
- `modules` - a set of modules
__Example implementation__
```js
render() {
//......
let children = this.props.modules.map((module, i) => {
let Module = module.type;
return (
<Module
key={i}
{...module.options}
/>
);
});
//......
}
```
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,3 @@
.awesome-app {
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,93 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* A higher order module
* that can wrap any number of modules
*
* A flow within the flow (grouping things f.ex)
*/
const DemoHigherOrderModule = React.createClass({
propTypes: {
element: React.PropTypes.string,
classes: React.PropTypes.string,
modules: React.PropTypes.array,
},
getDefaultProps() {
return {
element: 'div',
classes: '',
modules: [],
};
},
render() {
let {
element,
classes,
modules,
} = this.props;
/**
* This is the higher order part
* (just copy/paste this basically)
* and do whatever you need to
* render stuff the way you want
*/
let children = modules.map((module, i) => {
let Module = module.type;
return (
<Module
key={i}
{...module.options}
/>
);
});
return (
React.createElement(element, {
className: classes
}, children)
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-container-styles.scss`,
clientStyles: isBrowser && require('./styles/my-container-styles.scss'),
}),
);
/**
* Finally export the module
* extended with Aurora functionality
*/
module.exports = extendWithAuroraFunctionality(DemoHigherOrderModule);
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,78 @@
Aurora Higher Order Module Template
===================================
A module template for building higher order Aurora modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
__NOTE:__
A higher order module means that your module renders other modules passed into it, and has an array of `modules` in its `options`.
#### Include it in the module-map to enable use
```js
// module-map.js
const moduleMap = {
'my-higher-order-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyHigherOrderModule/MyHigherOrderModule.jsx'));
});
},
...
};
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-higher-order-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....',
modules: [...] // other modules
}
}
```
#### Document the module interface
```js
<MyHigherOrderModule
a={'...'}
b={'....'}
c={'.....'}
modules={[...]}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
- `modules` - a set of modules
__Example implementation__
```js
render() {
//......
let children = this.props.modules.map((module, i) => {
let Module = module.type;
return (
<Module
key={i}
{...module.options}
/>
);
});
//......
}
```
@@ -0,0 +1,3 @@
.awesome-container {
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
+66
View File
@@ -0,0 +1,66 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Loading = require('./components/Loading.jsx');
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModule = React.createClass({
render() {
return (
<Main {...this.props} />
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
}),
);
/**
* Finally export the module
* extended with Aurora functionality
*/
module.exports = extendWithAuroraFunctionality(DemoModule);
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,30 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Main = React.createClass({
propTypes: {
data: React.PropTypes.shape({
name: React.PropTypes.string,
age: React.PropTypes.number
})
},
render() {
const {
data = {}
} = this.props;
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(data)}
</div>
);
}
});
module.exports = Main;
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
+8
View File
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
+28
View File
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
+51
View File
@@ -0,0 +1,51 @@
Aurora Module Template
======================
A module template for building Aurora modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
#### Include it in the module-map to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
+4
View File
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,98 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Loading = require('./components/Loading.jsx');
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModuleWithData = React.createClass({
render() {
/**
* Handle data loading if you want
* a loading spinner and not "dead" data
*/
const {
isLoadingData,
data
} = this.props;
/**
* Until we have data
* show a loading indicator
*/
if (isLoadingData) {
return (
<Loading />
);
}
/**
* The actual stuff you want to show
*/
return (
<Main {...this.props} />
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withData = require('aurora-core/dist/decorators/with-data');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Aurora
* data fetching
* (optional)
*/
withData({
fetchData: require('./services/get-data'),
dataProp: 'data',
loadingProp: 'isLoadingData'
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
})
);
/**
* Finally export the module
*/
module.exports = extendWithAuroraFunctionality(DemoModuleWithData);
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,30 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Main = React.createClass({
propTypes: {
data: React.PropTypes.shape({
name: React.PropTypes.string,
age: React.PropTypes.number
})
},
render() {
const {
data = {}
} = this.props;
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(data)}
</div>
);
}
});
module.exports = Main;
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
+51
View File
@@ -0,0 +1,51 @@
Aurora Module Template
======================
A module template for building Aurora modules that fetch their own data (both on the server and client-side).
__NOTE:__
This readme is for building modules inside of Aurora Frontend
#### Include it in the module-map to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,13 @@
/**
* Dependencies
*/
const request = require('axios');
/**
* Export a function that returns
* a Promise of the data needed for
* the module.
*/
module.exports = function(options) {
return Promise.resolve(JSON.parse(JSON.stringify(options)));
};
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,106 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Loading = require('./components/Loading.jsx');
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModuleWithGeolocation = React.createClass({
render() {
/**
* Handle data loading if you want
* a loading spinner and not "dead" data
*/
const {
isLoadingData,
data
} = this.props;
/**
* Until we have data
* show a loading indicator
*/
if (isLoadingData) {
return (
<Loading />
);
}
/**
* The actual stuff you want to show
*/
return (
<Main
{...this.props}
/**
* let's forward the
* data as well
*/
data={data}
/>
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withData = require('aurora-core/dist/decorators/with-data');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Aurora
* data fetching
* (optional)
*/
withData({
disableServerLoading: true,
fetchData: require('./services/get-geolocated-data'),
dataProp: 'data',
loadingProp: 'isLoadingData'
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
})
);
/**
* Finally export the module
*/
module.exports = extendWithAuroraFunctionality(DemoModuleWithGeolocation);
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,25 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Main = React.createClass({
propTypes: {},
render() {
const {
data = {}
} = this.props;
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(data)}
</div>
);
}
});
module.exports = Main;
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
@@ -0,0 +1,51 @@
Aurora Module Template
======================
A module template for building Aurora modules that is based on geolocated data.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
#### Include it in the module-map to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,62 @@
/**
* Dependencies
*/
const request = require('axios');
const urlJoin = require('url-join');
/**
* Environment
*/
const { apiUrl } = require('../../../../config');
/**
* Export a function that returns
* a Promise of the data needed for
* the module.
*/
module.exports = function getGeoLocatedData(options) {
/**
* Feature detect the Geolocation API
* (NOTE: this only works client-side!)
*/
if (
typeof navigator === 'undefined' &&
!(geolocation in navigator) // eslint-disable-line no-undef
) {
return Promise.reject(new Error('Need browser to perform geolocation'));
}
/**
* Fetch data from an API/service where you supply
* the geolocation data as part of the input
*
* NOTE: You should only change the end-point here,
* as the rest of the data will be provided by the
* Aurora "framework" using the 'withData' decorator
*
* NOTE: Most often you can just copy/paste this file
* and change the url / API endpoint
*
* NOTE: Using __latitude and __longitude is a convention
* to make things predictable
*/
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, {
maximumAge: 30000,
});
})
.then(({ coords: { latitude, longitude } }) => {
return request
.get(urlJoin(apiUrl, 'data', 'geolocated-data'), {
params: Object.assign({}, options, {
__latitude: latitude,
__longitude: longitude,
}),
})
.then(response => response.data);
})
.catch((error) => {
console.error(error);
return Promise.reject(error);
});
};
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,105 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Loading = require('./components/Loading.jsx');
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModuleWithPersonalization = React.createClass({
render() {
/**
* Handle data loading if you want
* a loading spinner and not "dead" data
*/
const {
isLoadingData,
data
} = this.props;
/**
* Until we have data
* show a loading indicator
*/
if (isLoadingData) {
return (
<Loading />
);
}
/**
* The actual stuff you want to show
*/
return (
<Main
{...this.props}
/**
* let's forward the
* data as well
*/
data={data}
/>
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withData = require('aurora-core/dist/decorators/with-data');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Aurora
* data fetching
* (optional)
*/
withData({
fetchData: require('./services/get-personalized-data'),
dataProp: 'data',
loadingProp: 'isLoadingData'
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
})
);
/**
* Finally export the module
*/
module.exports = extendWithAuroraFunctionality(DemoModuleWithPersonalization);
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,25 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Main = React.createClass({
propTypes: {},
render() {
const {
data = {}
} = this.props;
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(data)}
</div>
);
}
});
module.exports = Main;
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
@@ -0,0 +1,58 @@
Aurora Module Template
======================
A module template for building Aurora modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
When you want to outsource a module to npm see [aurora-module-template](https://github.com/soldotno/aurora-module-template)
#### Include it in your module-map and module-includes to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
// module-includes.js
module.exports = [
'my-module',
...
];
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,27 @@
/**
* Dependencies
*/
const request = require('axios');
const urlJoin = require('url-join');
/**
* Environment
*/
const apiUrl = process.env.API_URL;
/**
* Export a function that returns
* a Promise of the data needed for
* the module.
*/
module.exports = function(options) {
return request
.get(urlJoin(apiUrl, 'data', 'personalized-data'), {
params: options
})
.then(response => response.data)
.catch((error) => {
console.error(error);
return Promise.reject(error);
});
};
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,105 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Loading = require('./components/Loading.jsx');
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModuleWithRandomization = React.createClass({
render() {
/**
* Handle data loading if you want
* a loading spinner and not "dead" data
*/
const {
isLoadingData,
data
} = this.props;
/**
* Until we have data
* show a loading indicator
*/
if (isLoadingData) {
return (
<Loading />
);
}
/**
* The actual stuff you want to show
*/
return (
<Main
{...this.props}
/**
* let's forward the
* data as well
*/
data={data}
/>
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withData = require('aurora-core/dist/decorators/with-data');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Aurora
* data fetching
* (optional)
*/
withData({
fetchData: require('./services/get-randomized-data'),
dataProp: 'data',
loadingProp: 'isLoadingData'
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
})
);
/**
* Finally export the module
*/
module.exports = extendWithAuroraFunctionality(DemoModuleWithRandomization);
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,25 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Main = React.createClass({
propTypes: {},
render() {
const {
data = {}
} = this.props;
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(data)}
</div>
);
}
});
module.exports = Main;
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
@@ -0,0 +1,58 @@
Aurora Module Template
======================
A module template for building Aurora modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
When you want to outsource a module to npm see [aurora-module-template](https://github.com/soldotno/aurora-module-template)
#### Include it in your module-map and module-includes to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
// module-includes.js
module.exports = [
'my-module',
...
];
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,27 @@
/**
* Dependencies
*/
const request = require('axios');
const urlJoin = require('url-join');
/**
* Environment
*/
const { apiUrl } = require('../../../../config');
/**
* Export a function that returns
* a Promise of the data needed for
* the module.
*/
module.exports = function getRandomizedData(options) {
return request
.get(urlJoin(apiUrl, 'data', 'randomized-data'), {
params: options,
})
.then(response => response.data)
.catch((error) => {
console.error(error);
return Promise.reject(error);
});
};
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
@@ -0,0 +1,77 @@
/**
* Dependencies
*/
const React = require('react');
const isBrowser = require('is-client')();
const compose = require('lodash.compose');
/**
* Components for this module
*/
const Main = require('./components/Main.jsx');
/**
* Aurora module React component
*/
const DemoModuleWithRedux = React.createClass({
render() {
return (
<Main {...this.props} />
);
}
});
/**
* Aurora decorators
*/
const withVisibility = require('aurora-core/dist/decorators/with-visibility');
const withStyles = require('aurora-core/dist/decorators/with-styles');
const withRedux = require('aurora-core/dist/decorators/with-redux');
const withScripts = require('aurora-core/dist/decorators/with-scripts');
/**
* Create a function that extends the
* component with all the Aurora specific functionality
*/
const extendWithAuroraFunctionality = compose(
/**
* Wrap the module in Aurora
* visibility resolving
* (required)
*/
withVisibility,
/**
* Wrap the module in Aurora
* style injection
* (required)
*/
withStyles({
serverPath: `${__dirname}/styles/my-module-styles.scss`,
clientStyles: isBrowser && require('./styles/my-module-styles.scss'),
}),
/**
* Wrap the module in Redux state handling
* (optional)
*/
withRedux({
reducer: require('./reducers').default,
initialState: {
error: null,
isLoading: true,
data: {},
}
}),
/**
* Wrap the module in Aurora
* script injection
* (optional)
*/
withScripts({
scripts: require('./injects/scripts'),
}),
);
/**
* Finally export the module extended with Aurora functionality
*/
module.exports = extendWithAuroraFunctionality(DemoModuleWithRedux);
@@ -0,0 +1,80 @@
/**
* Import services we need
* to fetch data from the API
*/
import getData from '../services/get-data';
/**
* Constants for naming
* and referencing action types
*/
export const POPULATE_DATA_PENDING = 'POPULATE_DATA_PENDING';
export const POPULATE_DATA_SUCCESS = 'POPULATE_DATA_SUCCESS';
export const POPULATE_DATA_ERROR = 'POPULATE_DATA_ERROR';
/**
* Pending action for
* populating the data
*/
function populateDataPending() {
return {
type: POPULATE_DATA_PENDING
};
}
/**
* Success action for
* populating the data
*/
function populateDataSuccess(data) {
return {
type: POPULATE_DATA_SUCCESS,
data,
};
}
/**
* Error action for
* populating the data
*/
function populateDataError(error) {
return {
type: POPULATE_DATA_ERROR,
error,
};
}
/**
* Exposed action creator
* for populating the data of our module
*/
export function populateData(options) {
return (dispatch) => {
/**
* Dispatch the pending action for
* retrieving the data
*/
dispatch(populateDataPending());
/**
* Initiate the request for retrieving
* the data for our given input options
*/
getData(options)
.then((result) => {
/**
* Dispatch the success action of retrieving
* the data, with the data as payload
*/
dispatch(populateDataSuccess(result));
})
.catch((err) => {
/**
* Dispatch the error action of retrieving
* the data when something fails,
* with the error as payload
*/
dispatch(populateDataError(err));
});
};
}
@@ -0,0 +1,23 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const ErrorMessage = React.createClass({
propTypes: {
error: React.PropTypes.object.isRequired
},
render() {
const { error } = this.props;
return (
<div>Error: {JSON.stringify(error)}</div>
);
}
});
module.exports = ErrorMessage;
@@ -0,0 +1,17 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Component
*/
const Loading = React.createClass({
render() {
return (
<div>Loading...</div>
);
}
});
module.exports = Loading;
@@ -0,0 +1,115 @@
/**
* Dependencies
*/
const React = require('react');
const { connect } = require('react-redux');
const { bindActionCreators } = require('redux');
/**
* Actions
*/
const { populateData } = require('../actions');
/**
* Sub-components
*/
const Loading = require('./Loading.jsx');
/**
* Component
*/
const Main = React.createClass({
propTypes: {
isLoading: React.PropTypes.bool.isRequired,
error: React.PropTypes.object.isRequired,
data: React.PropTypes.object.isRequired,
actions: React.PropTypes.shape({
populateData: React.PropTypes.func.isRequired,
}),
_dataOptions: React.PropTypes.object
},
getDefaultProps() {
return {
_dataOptions: {}
};
},
componentDidMount() {
const {
actions: { populateData },
_dataOptions
} = this.props;
populateData(_dataOptions);
},
render() {
/**
* Handle data loading if you want
* a loading spinner and not "dead" data
*/
const {
isLoading,
data,
error
} = this.props;
/**
* Show error message
* if there's an error
*/
if (error) {
return (
<ErrorMessage error={error} />
);
}
/**
* Until we have data
* show a loading indicator
*/
if (isLoading) {
return (
<Loading />
);
}
/**
* The actual stuff you want to show
*/
return (
<div style={{ height: '50vh', border: '1px solid red', margin: '10px' }}>
{JSON.stringify(this.props)}
</div>
);
}
});
/**
* A function to map from
* redux state to React props
*/
function mapStateToProps(state) {
return state;
}
/**
* A function to map from
* redux actions to React props
*/
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
populateData,
}, dispatch)
};
}
/**
* Export a redux-"connected" version of the component
*/
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(Main);
@@ -0,0 +1,4 @@
Module Components
=================
Here you put all your React components for the module.
@@ -0,0 +1,8 @@
Module Injects
==============
This module contains globals that should be injected (mostly used for global script dependencies)
__The pre-existing ones are__:
- `scripts` (used to inject script tags)
@@ -0,0 +1,28 @@
/**
* Examples of script injections
*
* Just paste all your snippets here
*/
module.exports = function(context) {
(function(w, d, s, id) {
/**
* Do config and add stuff to
* the global (window) scope
* here
*/
w.myConfig_REPLACE_ME = {
option: 'hello'
};
/**
* The part that injects
* the script with a url
* (only change the REPLACE_ME parts)
*/
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//url-to-script-here_REPLACE_ME.js";
fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'unique-id-for-script-here_REPLACE_ME'));
};
+58
View File
@@ -0,0 +1,58 @@
Aurora Module Template
======================
A module template for building Aurora modules.
__NOTE:__
This readme is for building modules inside of Aurora Frontend
When you want to outsource a module to npm see [aurora-module-template](https://github.com/soldotno/aurora-module-template)
#### Include it in your module-map and module-includes to enable use
```js
// module-map.js
const moduleMap = {
'my-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./MyModule/MyModule.jsx'));
});
},
...
};
// module-includes.js
module.exports = [
'my-module',
...
];
```
#### Document how the JSON-config looks for this module
```js
{
type: 'my-module',
visible: ['mobile', 'tablet', 'desktop'],
options: {
a: '...',
b: '....',
c: '.....'
}
}
```
#### Document the module interface
```js
<MyModule
a={'...'}
b={'....'}
c={'.....'}
/>
```
#### Document the different options and how it works
- `a` - this options does..
- `b` - this options does..
- `c` - this options does..
@@ -0,0 +1,37 @@
/**
* Import all the constants
* we are going to use
*/
import {
POPULATE_DATA_PENDING,
POPULATE_DATA_SUCCESS,
POPULATE_DATA_ERROR
} from '../actions';
/**
* Create and export our state reducer
*/
export default function rootReducer(state, action) {
switch (action.type) {
case POPULATE_DATA_PENDING:
return Object.assign({}, state, {
isLoading: true,
error: null,
});
case POPULATE_DATA_SUCCESS:
return Object.assign({}, state, {
isLoading: false,
data: action.data,
error: null,
});
case POPULATE_DATA_ERROR:
return Object.assign({}, state, {
error: action.error
});
default:
return state;
}
}
@@ -0,0 +1,13 @@
/**
* Dependencies
*/
const request = require('axios');
/**
* Export a function that returns
* a Promise of the data needed for
* the module.
*/
module.exports = function(options) {
return Promise.resolve(JSON.parse(JSON.stringify(options)));
};
@@ -0,0 +1,8 @@
Module Services
===============
Here you'll put all the interfaces that communicates with services and expose them as simple functions
__Example__:
- Communicating with API's
@@ -0,0 +1,23 @@
.awesome {
background-color: whitesmoke;
&.one {
color: yellow
}
&.two {
color: red
}
&.three {
color: blue
}
&.four {
color: hotpink
}
&.five {
color: cyan
}
}
@@ -0,0 +1,4 @@
Module Styles
=============
This folder should contain your styles (sass).
+15
View File
@@ -0,0 +1,15 @@
/**
* Dependencies
*/
const React = require('react');
/**
* Default empty component for graceful failing
*/
const DoesNotExist = React.createClass({
render() {
return null;
}
});
module.exports = DoesNotExist;
+98
View File
@@ -0,0 +1,98 @@
/**
* Dependencies
*/
const debug = require('debug')('aurora-frontend:get-module');
/**
* Shim require.ensure in node.js
* (check the webpack docs - async chunking)
*/
if (typeof require.ensure !== 'function') {
require.ensure = require('isomorphic-ensure')({
dirname: __dirname,
});
}
/**
* The map of modules available to resolve to
*/
const moduleMap = {
'demo-app': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoAppModule/DemoAppModule.jsx'));
});
},
'demo-hom': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoHigherOrderModule/DemoHigherOrderModule.jsx'));
});
},
'demo-module': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModule/DemoModule.jsx'));
});
},
'demo-module-with-data': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModuleWithData/DemoModuleWithData.jsx'));
});
},
'demo-module-with-geolocation': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModuleWithGeolocation/DemoModuleWithGeolocation.jsx'));
});
},
'demo-module-with-personalization': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModuleWithPersonalization/DemoModuleWithPersonalization.jsx'));
});
},
'demo-module-with-randomization': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModuleWithRandomization/DemoModuleWithRandomization.jsx'));
});
},
'demo-module-with-redux': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DemoModuleWithRedux/DemoModuleWithRedux.jsx'));
});
},
'does-not-exist': (callback) => {
require.ensure([], (require) => {
callback(null, require('./DoesNotExist/DoesNotExist.jsx'));
});
},
};
/**
* Export a function that can resolve
* a module from a string representation
* to a React component / Aurora module
* (asynchronously)
*/
module.exports = (type) => {
/**
* Return a Promise of the React component
* resolved from the string type definition
*/
return new Promise((resolve, reject) => {
setImmediate(() => {
if (!moduleMap[type]) {
debug(`You are trying to render a module with type *${type}* which does not exist`);
}
/**
* Pull out the specified component getter function
* (or default gracefully)
*/
const getModule = moduleMap[type] || moduleMap['does-not-exist'];
/**
* Fetch the specified component and the promise to it
*/
getModule((err, module) => {
return err ? reject(err) : resolve(module);
});
});
});
};
+75
View File
@@ -0,0 +1,75 @@
/**
* Dependencies
*/
const debug = require('debug')('aurora-frontend:app'); // eslint-disable-line no-unused-vars
const express = require('express');
const compression = require('compression');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
const useragent = require('express-useragent');
const ms = require('ms');
/**
* Environment
*/
const { port } = require('../config');
/**
* Import the server-rendering function
* from aurora core and create an instance
*/
/* eslint-disable global-require */
const renderServer = require('aurora-core/dist/render/server')({
cacheHTML: {
get: () => Promise.reject(new Error('Cache miss')),
set: function set() {},
},
createHTML: require('./utils/create-html'),
getRoute: require('./services/get-route-config'),
getUserSettings: require('./utils/get-user-settings'),
getPaginationSettings: require('./utils/get-pagination-settings'),
getModule: require('./modules/get-module'),
isVisible: require('./utils/is-visible'),
});
/* eslint-enable global-require */
/**
* Create express app
*/
const app = express();
/**
* Use gzip compression
*/
app.use(compression());
/**
* Add useragent parsing
*/
app.use(useragent.express());
/**
* Parse incoming cookies
*/
app.use(cookieParser());
/**
* Serve favicon
*/
app.use(favicon(`${__dirname}/../public/static/favicon.ico`));
/**
* Serve static files
*/
app.use(express.static(`${__dirname}/../public`, { maxAge: ms('7 days') }));
/**
* Use our server rendering function
* as the main route handler
*/
app.use('/', renderServer);
/**
* Start server
*/
app.listen(port, () => console.log(`Listening on port ${port}`)); // eslint-disable-line no-console
+38
View File
@@ -0,0 +1,38 @@
/**
* Include babel polyfill
*/
require('babel-polyfill');
const { nodeEnv } = require('../config');
/**
* Add a global var to conform
* to webpack config
*/
global.__DEVELOPMENT__ = nodeEnv !== 'production'; // eslint-disable-line no-underscore-dangle
/**
* Run all requires in our server-side
* app through babel, so we can use
* ES2015 everywhere
*/
require('babel-core/register')({
sourceMap: !__DEVELOPMENT__, // eslint-disable-line no-underscore-dangle, no-undef
});
/**
* Use bluebird for as promise library
*/
global.Promise = require('bluebird');
/**
* Handle unhandled promise rejections
*/
process.on('unhandledRejection', (error) => {
throw error;
});
/**
* Run the actual app
*/
require('./server-app.js');
+245
View File
@@ -0,0 +1,245 @@
const { slice, merge } = require('aurora-deep-slice-merge');
const clone = require('stringify-clone');
const deepEqual = require('deep-equal');
const demo = {
pageInfo: {
title: 'Demo Aurora config',
},
app: {
type: 'demo-app',
options: {
modules: [{
type: 'demo-hom',
options: {
modules: [{
type: 'demo-module-with-data',
visibility: ['small'],
options: {
_dataOptions: {
name: 'A',
age: 1
}
}
}, {
type: 'demo-module-with-data',
visibility: ['medium'],
options: {
_dataOptions: {
name: 'B',
age: 2
}
}
}, {
type: 'demo-module-with-data',
visibility: ['large'],
options: {
_dataOptions: {
name: 'C',
age: 3
}
}
}, {
type: 'demo-module-with-data',
options: {
_dataOptions: {
name: 'D',
age: 4
}
}
}, {
type: 'demo-hom',
options: {
modules: [{
type: 'demo-module-with-data',
visibility: ['small'],
options: {
_dataOptions: {
name: 'E',
age: 5
}
}
}, {
type: 'demo-module-with-data',
visibility: ['medium'],
options: {
_dataOptions: {
name: 'F',
age: 6
}
}
}, {
type: 'demo-module-with-data',
visibility: ['large'],
options: {
_dataOptions: {
name: 'G',
age: 7
}
}
}, {
type: 'demo-module-with-data',
options: {
_dataOptions: {
name: 'H',
age: 8
}
}
}]
}
}]
}
}]
}
}
};
const redux = {
pageInfo: {
title: 'Demo Aurora config',
},
app: {
type: 'demo-app',
options: {
modules: [{
type: 'demo-hom',
options: {
modules: [{
type: 'demo-module-with-redux',
visibility: ['small'],
options: {
_dataOptions: {
name: 'AA-redux',
age: 11
}
}
}, {
type: 'demo-module-with-redux',
visibility: ['medium'],
options: {
_dataOptions: {
name: 'BB-redux',
age: 22
}
}
}, {
type: 'demo-module-with-redux',
visibility: ['large'],
options: {
_dataOptions: {
name: 'CC-redux',
age: 33
}
}
}, {
type: 'demo-module-with-redux',
options: {
_dataOptions: {
name: 'DD-redux',
age: 44
}
}
}]
}
}]
}
}
};
const geo = {
pageInfo: {
title: 'Demo Aurora config',
},
app: {
type: 'demo-app',
options: {
modules: [{
type: 'demo-hom',
options: {
modules: [{
type: 'demo-module-with-geolocation',
visibility: ['small'],
options: {
_dataOptions: {
name: 'EE-geo',
age: 55
}
}
}, {
type: 'demo-module-with-geolocation',
visibility: ['medium'],
options: {
_dataOptions: {
name: 'FF-geo',
age: 66
}
}
}, {
type: 'demo-module-with-geolocation',
visibility: ['large'],
options: {
_dataOptions: {
name: 'GG-geo',
age: 77
}
}
}, {
type: 'demo-module-with-geolocation',
options: {
_dataOptions: {
name: 'HH-geo',
age: 88
}
}
}]
}
}]
}
}
};
const routes = {
'/demo': demo,
'/demo/': demo,
'/redux': redux,
'/redux/': redux,
'/geo': geo,
'/geo/': geo,
};
module.exports = function({
path,
query,
skip,
limit,
page,
version,
settings,
}) {
if (!routes[path]) {
return Promise.reject(new Error('Route requested not found'));
}
let config = slice(routes[path], skip, limit);
let hasMore = !deepEqual(
slice(routes[path], skip, limit),
slice(routes[path], skip, limit + 1)
);
return new Promise((resolve) => {
setTimeout(() => {
resolve({
meta: {
pagination: {
hasMore
},
version: 123
},
data: {
config
}
});
}, 1000);
});
};
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff. Show more