First use of React

old
Javi Jimenez Villar 2015-05-28 17:20:28 +02:00
parent b2f48b871a
commit 433355bfde
17 changed files with 728 additions and 26 deletions

29
.gitignore vendored
View File

@ -1,27 +1,4 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
bower_components
dist/assets/**/*.css
dist/assets/**/*.js
node_modules

8
bower.json Normal file
View File

@ -0,0 +1,8 @@
{
"name" : "secrets",
"version" : "0.5.28",
"dependencies" : {
"hamsa" : "*",
"stylmethods" : "*"
}
}

23
dist/index.html vendored Normal file
View File

@ -0,0 +1,23 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Material Console</title>
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width">
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1" media="(device-height: 568px)">
<meta name="apple-mobile-web-app-title" content="Material Console">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<meta name="HandheldFriendly" content="True">
<meta http-equiv="cleartype" content="on">
<link rel="stylesheet" href="./assets/css/material-console.css">
</head>
<body>
<script src="./assets/js/material-console.dependencies.js"></script>
<script src="./assets/js/material-console.js"></script>
</body>
</html>

80
gulpfile.coffee Normal file
View File

@ -0,0 +1,80 @@
"use strict"
# -- DEPENDENCIES --------------------------------------------------------------
gulp = require "gulp"
cjsx = require "gulp-cjsx"
concat = require "gulp-concat"
connect = require "gulp-connect"
header = require "gulp-header"
gutil = require "gulp-util"
uglify = require "gulp-uglify"
stylus = require "gulp-stylus"
pkg = require "./package.json"
# -- BROWSERIFY ----------------------------------------------------------------
browserify = require "browserify"
source = require "vinyl-source-stream"
bundler = browserify "./source/app.cjsx", extensions: [".cjsx", ".coffee"]
bundler.transform require "coffee-reactify"
# -- FILES ---------------------------------------------------------------------
path =
dist : "./dist"
source : [ "source/**/*.cjsx"
"source/**/*.coffee"]
style : [ "bower_components/STYLmethods/vendor.styl"
"source/styles/__constants.styl"
"source/styles/normalize.styl"
"source/styles/app.styl"
"source/styles/components/*.styl"
"source/styles/screens/*.styl"]
dependencies : [ "node_modules/react/dist/react-with-addons.js"
"bower_components/hamsa/dist/hamsa.js"]
# -- BANNER --------------------------------------------------------------------
banner = [
"/**"
" * <%= pkg.name %> - <%= pkg.description %>"
" * @version v<%= pkg.version %>"
" * @link <%= pkg.homepage %>"
" * @author <%= pkg.author.name %> (<%= pkg.author.site %>)"
" * @license <%= pkg.license %>"
" */"
""
].join("\n")
# -- TASKS ---------------------------------------------------------------------
gulp.task "server", ->
connect.server
port : 8000
livereload: true
root : path.dist
gulp.task "source", ->
bundler.bundle()
.on "error", gutil.log.bind(gutil, "Browserify Error")
.pipe source "#{pkg.name}.js"
# .pipe uglify mangle: true
.pipe header banner, pkg: pkg
.pipe gulp.dest "#{path.dist}/assets/js"
.pipe connect.reload()
gulp.task "style", ->
gulp.src path.style
.pipe concat "#{pkg.name}.styl"
.pipe stylus
compress: true
errors : true
.pipe header banner, pkg: pkg
.pipe gulp.dest "#{path.dist}/assets/css"
.pipe connect.reload()
gulp.task "dependencies", ->
gulp.src path.dependencies
.pipe concat "#{pkg.name}.dependencies.js"
.pipe gulp.dest "#{path.dist}/assets/js"
# .pipe uglify mangle: true
.pipe connect.reload()
gulp.task "init", ["source", "style", "dependencies"]
gulp.task "default", ->
gulp.run ["server"]
gulp.watch path.source, ["source"]
gulp.watch path.style, ["style"]

32
package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name" : "material-console",
"version" : "0.5.28",
"description" : "",
"homepage" : "http://zetapath.com",
"author" : "Zetapath LTD.",
"dependencies": {
"coffee-script" : "*"
},
"devDependencies": {
"browserify" : "^10.0.0",
"coffee-reactify" : "^3.0.0",
"moment" : "^2.10.2",
"react" : "^0.13.2",
"spa-router" : "^0.5.20",
"vinyl-source-stream" : "^1.1.0",
"gulp" : "*",
"gulp-cjsx" : "*",
"gulp-concat" : "*",
"gulp-connect" : "*",
"gulp-flatten" : "*",
"gulp-header" : "*",
"gulp-stylus" : "*",
"gulp-uglify" : "*",
"gulp-util" : "*",
"gulp-yml" : "*"
},
"scripts": {
"start" : "gulp",
"postinstall" : "bower install"
}
}

41
source/app.cjsx Normal file
View File

@ -0,0 +1,41 @@
"use strict"
SPArouter = require "spa-router"
# -- Models
Session = require "./models/session"
# -- Screens
ScreenSession = require "./screens/session"
ScreenConsole = require "./screens/console"
App = React.createClass
# -- States & Properties
getInitialState: ->
session : null
context : "campaigns"
# -- Lifecycle
componentWillMount: ->
SPArouter.listen
"/session/:id" : (id) =>
@setState session: false, context: id
"/console/:context" : (context) =>
@setState session: true, context: context
# -- Events
onSessionSuccess: (data) ->
@setState session: true
SPArouter.path "console"
# -- Render
render: ->
<app>
{
if @state.session
<ScreenConsole context={@state.context}/>
else
<ScreenSession context={@state.context} onSuccess={@onSessionSuccess} />
}
</app>
React.render <App />, document.body

View File

@ -0,0 +1,38 @@
###
@todo
###
Navigation = require './navigation'
module.exports = React.createClass
# -- States & Properties
propTypes:
title : React.PropTypes.string.required
routes : React.PropTypes.array.required
subroutes : React.PropTypes.array
getDefaultProps: ->
routes : []
title : undefined
subroutes : []
getInitialState: ->
expanded : @props.expanded
# -- Lifecycle
componentDidUpdate: (nextProps) ->
@refs.header.getDOMNode().classList.remove "expanded"
# -- Events
onProfile: (event) ->
event.preventDefault()
@refs.header.getDOMNode().classList.toggle "expanded"
# -- Render
render: ->
<header ref="header" data-component="header">
{ <Navigation routes={@props.routes}/> if @props.routes }
{ <h1>{@props.title}</h1> if @props.title }
{ <Navigation routes={@props.subroutes}/> if @props.subroutes }
</header>

View File

@ -0,0 +1,32 @@
###
@todo
###
module.exports = React.createClass
# -- States & Properties
propTypes:
routes : React.PropTypes.array
getDefaultProps: ->
routes : []
# -- Events
onBack: (event) ->
event.preventDefault()
event.stopPropagation()
window.history.back()
# -- Render
render: ->
<nav>
{
for route, index in @props.routes
method = if route.back is true then @onBack
<a href={"#" + route.route} key={index} onClick={method}>
<span className={"icon " + route.icon}></span>
<strong>{route.label}</strong>
<small>{route.count}</small>
</a>
}
</nav>

View File

@ -0,0 +1,33 @@
###
@todo
###
storage = require "../modules/storage"
module.exports = class Session extends Hamsa
@define
id : type: String
mail : type: String
token : type: String
username : type: String
name : type: String
bio : type: String
image : type: String
wallet : type: Number, default: 0
secrets : type: Array
purchases : type: Array
tips : type: Array
followers : type: Array
following : type: Array
updated_at : type: Date
created_at : type: Date, default: new Date()
@update = ->
promise = new Hope.Promise()
@destroyAll()
@instance = -> @find()[0]

View File

@ -0,0 +1,9 @@
###
@todo
###
module.exports =
STORAGE :
SESSION : "material-console-session"
CONTEXTS = []

View File

@ -0,0 +1,12 @@
###
@todo
###
Header = require "../components/header"
module.exports = React.createClass
render: ->
<article>
<Header title="Welcome" routes={[]} subroutes={[]} />
</article>

View File

@ -0,0 +1,56 @@
###
@todo
###
module.exports = React.createClass
# -- States & Properties
propTypes:
active : React.PropTypes.boolean
context : React.PropTypes.string
onSuccess : React.PropTypes.function
getInitialState: ->
disabled: false
# -- Events
onKeyUp: (event) ->
values = @_getFormValues()
@setState disabled: not(values.mail and values.password)
onSign: (event) ->
event.preventDefault()
button = @refs.button.getDOMNode().classList
button.add "loading"
@props.onSuccess.call @props.onSuccess, token: "1"
componentDidMount: ->
setTimeout =>
@setState active: true
, 450
# -- Render
render: ->
<article data-screen="session" className={@state.active} data-flex="vertical center">
<h1>Welcome...</h1>
<form data-flex="vertical center">
<input ref="mail" type="text" placeholder="mail" onKeyUp={@onKeyUp} className="transparent"/>
<input ref="password" type="password" placeholder="password" onKeyUp={@onKeyUp} className="transparent"/>
<button ref="button" onClick={@onSign} disabled={@state.disabled} className="radius white">
<abbr>{ if @props.context is "login" then "Sign In" else "Sign Up"}</abbr>
</button>
</form>
{
if @props.context is "login"
<a href="#/session/signup">Dont have an account? <strong>Sign Up</strong></a>
else
<a href="#/session/login">You have an account, <strong>Sign In</strong></a>
}
<small>Copyright 2015</small>
</article>
# -- Private methods
_getFormValues: ->
mail : @refs.mail.getDOMNode().value.trim()
password : @refs.password.getDOMNode().value.trim()

View File

@ -0,0 +1,47 @@
@import url("http://fonts.googleapis.com/css?family=Roboto:500,300,700,400")
// -- Colors
COLOR = #222222
BACKGROUND = #ffffff
THEME = #ffc107
// -- Fonts
FONT_FAMILY = "Roboto", "Helvetica Neue", "Helvetica", "sans-serif"
FONT_SIZE = 16px
FONT_SIZE_TINY = 80%
FONT_SIZE_SMALL = 90%
FONT_SIZE_NORMAL = 100%
FONT_SIZE_BIG = 120%
FONT_WEIGHT_THIN = normal
FONT_WEIGHT_NORMAL = normal
FONT_WEIGHT_BOLD = bold
// -- Sizes
UNIT = 4rem
SPACE = (UNIT * 0.29)
MENU_WIDTH = 85vw
HEADER_HEIGHT = 10vh
BUTTON_HEIGHT = (2.5 * SPACE)
BUTTON_HEIGHT = 14vw
BORDER_RADIUS = (SPACE / 2)
UPLOAD_IMAGE_USER = 45vw
H1_SHADOW = (SPACE / 6) (SPACE / 6) rgba(0,0,0,0.2)
LI_AVATAR_SIZE = (UNIT / 1.2)
LI_HEIGHT = 72px
// -- Animations
ANIMATION_DURATION = 450ms
ANIMATION_EASE = cubic-bezier(.55,0,.1,1)
ANIMATION_DELAY = (ANIMATION_DURATION / 5)
delayChild(child, increment)
&:nth-child({child})
transition-delay ((child + increment) * ANIMATION_DELAY)
@keyframes LOADING
0%
transform scale(0.0)
100%
transform scale(1.0)
opacity: 0

95
source/styles/app.styl Normal file
View File

@ -0,0 +1,95 @@
body
font-family : FONT_FAMILY
font-size : FONT_SIZE
color : COLOR
background-color : BACKGROUND
a
color : WHITE
h1
font-size : (1.75 * FONT_SIZE_NORMAL)
h2
font-size : (1.5 * FONT_SIZE_NORMAL)
.scroll
overflow-x : hidden
overflow-y : scroll
-webkit-overflow-scrolling: touch
.type-01 /*stay*/
background : url("/assets/img/bear.png") no-repeat
.type-02 /*drink*/
background : url("/assets/img/dog.png") no-repeat
.type-03 /*eat*/
background : url("/assets/img/pig.png") no-repeat
.type-04 /*listen*/
background : url("/assets/img/rabbit.png") no-repeat
.type-05 /*see*/
background : url("/assets/img/raccoon.png") no-repeat
// -- ANIMATIONS ---------------------------------------------------------------
@keyframes LOADING
0%
transform scale(0.0)
100%
transform scale(1.0)
opacity: 0.1
// -- FLEX ---------------------------------------------------------------------
[data-flex]
display-flex()
body&
position : absolute
left : 0
top : 0
bottom : 0
width : 100%
overflow : hidden
// -- Direction
[data-flex^="horizontal"]
flex-direction row
[data-flex^="vertical"]
flex-direction column
// -- Size
[data-flex*="grow"]
> *:not([data-column]):not([data-flex-grow])
flex-grow 1
[data-flex-grow="min"]
flex-grow 0
[data-flex-grow="max"]
flex-grow 2
// -- Container properties
[data-flex*="wrap"]
flex-wrap wrap
[data-flex*="center"]
justify-content center
align-content center
align-items center
[data-flex-justify="start"]
justify-content flex-start
[data-flex-justify="center"]
justify-content center
[data-flex-justify="end"]
justify-content flex-end
[data-flex-content="start"]
align-content flex-start
[data-flex-content="center"]
align-content center
[data-flex-content="end"]
align-content flex-end
[data-flex-items="center"]
align-items center
[data-flex-items="start"]
align-items flex-start
[data-flex-items="end"]
align-items flex-end
// -- Children properties
[data-flex-order="first"]
order: -1
[data-flex-order="last"]
order: 999999

View File

@ -0,0 +1,6 @@
header
position : fixed
height : UNIT
width : 100vw
background-color : THEME
color : WHITE

211
source/styles/normalize.styl vendored Normal file
View File

@ -0,0 +1,211 @@
// normalize v3.0.2 | MIT License | git.io/normalize
html
font-family sans-serif
-ms-text-size-adjust 100%
-webkit-text-size-adjust 100%
body
margin 0
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
nav, section, summary
display block
audio, canvas, progress, video
display inline-block
vertical-align baseline
audio
&:not([controls])
display none
height 0
[hidden], template
display none
a
background-color transparent
&:active, &:hover
outline 0
abbr[title]
border-bottom 1px dotted
b, strong
font-weight bold
dfn
font-style italic
h1
font-size 2em
margin 0.67em 0
mark
background #ff0
color #000
small
font-size 80%
sub, sup
font-size 75%
line-height 0
position relative
vertical-align baseline
sup
top -0.5em
sub
bottom -0.25em
img
border 0
svg
&:not(:root)
overflow hidden
figure
margin 1em 40px
hr
-moz-box-sizing content-box
box-sizing content-box
height 0
pre
overflow auto
code, kbd, pre, samp
font-family monospace, monospace
font-size 1em
button, input, optgroup, select, textarea
color inherit
font inherit
margin 0
button
overflow visible
button, select
text-transform none
button, html input[type="button"], input[type="reset"], input[type="submit"]
-webkit-appearance button
cursor pointer
button[disabled], html input[disabled]
cursor default
button::-moz-focus-inner, input::-moz-focus-inner
border 0
padding 0
input
line-height normal
input[type="checkbox"], input[type="radio"]
box-sizing border-box
padding 0
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button
height auto
input[type="search"]
-webkit-appearance textfield
-moz-box-sizing content-box
-webkit-box-sizing content-box
box-sizing content-box
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration
-webkit-appearance none
fieldset
border 1px solid #c0c0c0
margin 0 2px
padding 0.35em 0.625em 0.75em
legend
border 0
padding 0
textarea
overflow auto
optgroup
font-weight bold
table
border-collapse collapse
border-spacing 0
td, th
padding 0
// -- App ----------------------------------------------------------------------
a,abbr,address,article,aside,audio,b,blockquote,body,caption,cite,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video
border: 0
margin: 0
outline: 0
padding: 0
*, *:before, *:after
margin: 0
padding: 0
box-sizing(border-box)
html
position: absolute
height: 100%
width: 100%
margin: 0
padding: 0
overflow: hidden
body
width: 100%
height: 100%
margin: 0
padding: 0
-webkit-touch-callout: none
-webkit-user-select: none
-moz-user-select: moz-none
user-select: none
overflow: hidden
*
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
h1, h2, h3, h4, h5, h6, label, p, button, abbr, a
-webkit-font-smoothing: subpixel-antialiased
font-smoothing: subpixel-antialiased
-webkit-text-size-adjust: 100%
-ms-text-size-adjust: 100%
text-size-adjust: 100%
span
-webkit-font-smoothing: antialiased
font-smoothing: antialiased
a
text-decoration: none
-webkit-tap-highlight-color: rgba(0,0,0,0)
::-webkit-scrollbar
width: 0px
height: 0px
input, button
-webkit-appearance: none
-moz-appearance: none
appearance: none
-webkit-touch-callout: none
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
outline: none

View File

@ -0,0 +1,2 @@
[data-screen="session"]
height : 100vh