Skip to content
This repository has been archived by the owner on Feb 17, 2021. It is now read-only.

Commit

Permalink
first load
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanflorentin committed Aug 6, 2016
0 parents commit 4cfe41e
Show file tree
Hide file tree
Showing 10 changed files with 388 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
*.*~
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "provide-app-crud",
"version": "1.0.0",
"description": "Application CRUD using Provide, Redux, React and ReactToobox ",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ivan Florentin <[email protected]>",
"license": "ISC",
"dependencies": {
"react": "^15.3.0",
"react-redux-provide": "^6.0.0-rc.56",
"validator": "^5.5.0",
"babel-core": "^6.7.4",
"babel-eslint": "^4.1.5",
"babel-loader": "^6.0.1",
"babel-plugin-react-transform": "^1.1.1",
"babel-plugin-transform-es2015-spread": "^6.6.5",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.1.4",
"babel-preset-stage-2": "^6.5.0",
"babel-polyfill": "^6.7.2"
},
"babel": {
"plugins": [
"transform-object-rest-spread"
]
}

}
13 changes: 13 additions & 0 deletions src/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import editCreator from './edit'
import listCreator from './list'
import displayCreator from './display'

export default function (compDef) {
const componentProperName = compDef.componentName[0].toUpperCase() +
compDef.componentName.substring(1)
const components = {}
components[`edit${componentProperName}`] = editCreator(compDef)
components[`list${componentProperName}`] = listCreator(compDef)
components[`display${componentProperName}`] = displayCreator(compDef)
return components
}
44 changes: 44 additions & 0 deletions src/display.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, {PropTypes} from 'react'
import {Button} from 'react-toolbox'
import {Card, CardTitle, CardText, CardActions} from 'react-toolbox/lib/card'

export default function (compDef) {
const {componentName} = compDef

const ComponentDisplay = (props) => {
const {goBack, pushRoute, routing} = props
const url = routing.locationBeforeTransitions.pathname
const editURL = `${url.slice(0, url.lastIndexOf('/')+1)}edit`
const component = props[`${componentName}`]
let content = []
let cardActions = <div>
<Button icon='add'
floating accent mini onClick={()=>{
pushRoute(editURL)}}/>
<Button icon='undo'
floating accent mini onClick={()=>{
goBack()}}/>
</div>
if (component.index !== undefined) {
for (let field of component) {
if (component[field] && compDef[field]) {
content.push(<p>{compDef[field].label} : {component[field]}</p>)
}
}
}

return <Card>
<CardTitle title={compDef.title}/>
<CardText>{content}</CardText>
<CardActions>{cardActions}</CardActions>
</Card>
}

ComponentDisplay.propTypes = {}
ComponentDisplay.propTypes[`${componentName}`] = PropTypes.object
ComponentDisplay.propTypes.goBack = PropTypes.func
ComponentDisplay.propTypes.pushRoute = PropTypes.func
ComponentDisplay.propTypes.routing = PropTypes.object

return ComponentDisplay
}
48 changes: 48 additions & 0 deletions src/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, {PropTypes} from 'react'
import {ListSubHeader, Button, Input} from 'react-toolbox'

export default function (compDef) {
const {componentName,
fields
} = compDef

const componentProperName = componentName[0].toUpperCase() + componentName.substring(1)
const fieldNames = Object.keys(fields)
const ComponentEdit = (props) =>{
let next = Object.assign({}, props[componentName])
const save = () =>{props[`save${componentProperName}`](next)}
const store = () =>{props[`store${componentProperName}`](next)}
const {goBack} = props
const listCaption = `Ingrese datos de ${componentProperName}`
const listFields = []

for (let fieldName of fieldNames) {
const componentField = compDef.fields[fieldName]
const field = <Input key={fieldName} value={next[fieldName] ||''}
type={componentField.uiType} label={componentField.label} name='name' icon='assignment'
onChange={(e) => {
next[fieldName] = e
save()
}}/>
listFields.push(field)
}

return (
<div>
<ListSubHeader caption={listCaption}/>
{listFields}
<Button icon='done' floating disabled={!next.isValid} accent mini onClick={(e)=>{
store()
goBack()
}}/>
<Button icon='undo' floating accent mini onClick={()=>{goBack()}}/>
</div>
)
}
ComponentEdit.propTypes = {}
ComponentEdit.propTypes[`${componentName}`] = PropTypes.object
ComponentEdit.propTypes[`save${componentProperName}`] = PropTypes.func
ComponentEdit.propTypes[`store${componentProperName}`] = PropTypes.func
ComponentEdit.propTypes.goBack = PropTypes.func
return ComponentEdit
}
30 changes: 30 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {Route} from 'react-router'
import React from 'react'
import componentCreator from './components'
import provideComponentCrud from './providers'
import routeCreator from './routes'
import menuCreator from './menu'

export default function (appDef) {
const components = {}
const providers = {}
const componentRoutes = []
appDef.components.map((compDef) =>{
components[compDef.componentName] = componentCreator(compDef)
providers[compDef.componentName] = provideComponentCrud(compDef)
componentRoutes.push(routeCreator(compDef, components[compDef.componentName]))
})
const menu = menuCreator(appDef)
const MainRoute =
<Route path={appDef.appRoute} component={menu}>
{componentRoutes}
</Route>

const app = {
appDef,
appName: appDef.appName,
components,
providers,
routes: MainRoute}
return app
}
51 changes: 51 additions & 0 deletions src/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, {PropTypes} from 'react'
import {List, ListItem, ListSubHeader, Button} from 'react-toolbox'

export default function (compDef) {
const {componentName,
fields,
listName
} = compDef
const componentProperName = componentName[0].toUpperCase() + componentName.substring(1)
const ComponentList = (props) =>{
const url = props.routing.locationBeforeTransitions.pathname
const displayURL = `${url.slice(0, url.lastIndexOf('/')+1)}display`
const editURL = `${url.slice(0, url.lastIndexOf('/')+1)}edit`
const list = props[listName]
const Items = list.map((item, index) =>{
let itemLegend = ''
for (let field in fields) {
if (item[field] && item[field] !== '') {
itemLegend = itemLegend + ` ${fields[field].label}: ${item[field]}`
}
}
return <ListItem key={index} legend={itemLegend} leftIcon='receipt'
onClick={() =>{
props[`select${componentProperName}`](props[listName][index])
props.pushRoute(editURL)
}
}/>
})

return <div>
<List selectable ripple>
<center><ListSubHeader caption={compDef.listTitle} /></center>
{Items}
</List>
<Button icon='add'
floating accent mini onClick={()=>{
props[`deselect${componentProperName}`]()
props.pushRoute(editURL)
}}/>
</div>
}
ComponentList.propTypes = {
pushRoute: PropTypes.func,
goBack: PropTypes.func
}
ComponentList.propTypes[compDef.listName] = PropTypes.array
ComponentList.propTypes[`deselect${componentProperName}`] = PropTypes.func
ComponentList.propTypes[`select${componentProperName}`] = PropTypes.func
ComponentList.propTypes.routing = PropTypes.object
return ComponentList
}
38 changes: 38 additions & 0 deletions src/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, {PropTypes} from 'react'
import Button from 'react-toolbox/lib/button'
import Navigation from 'react-toolbox/lib/navigation'

export default function (appDef) {
const {appRoute,
appTitle
} = appDef
const AppMenu = (props) =>{
const {pushRoute} = props
const buttons = appDef.components.map((component, index) =>{
const {componentName} = component
const componentProperName = componentName[0].toUpperCase() +
componentName.substring(1)
return <Button key={`${componentProperName}${index}`}
label={componentProperName} primary onClick={() =>{
pushRoute(`/${appRoute}/${component.componentName}/list`)
}}/>
})

return (
<div>
<center><h4>{appTitle}</h4></center>
<Navigation type='horizontal'>
{buttons}
</Navigation>
{props.children}
</div>
)
}

AppMenu.propTypes = {}
AppMenu.propTypes.children = PropTypes.object
AppMenu.propTypes.pushRoute = PropTypes.func
AppMenu.propTypes.goBack = PropTypes.func

return AppMenu
}
111 changes: 111 additions & 0 deletions src/providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
export default function (compDef) {
const {componentName,
fields,
listName,
replication
} = compDef
const listProperName = listName[0].toUpperCase() + listName.substring(1)
const listCapitalName = listName.toUpperCase()
const componentProperName = componentName[0].toUpperCase() + componentName.substring(1)
const componentCapitalName = componentName.toUpperCase()

const crudInit = {}
const crudErrorInit = {}
let fieldNames = Object.keys(fields)
if (fieldNames.length > 0) {
for (let fieldName of fieldNames) {
crudInit[fieldName] = fields[fieldName].defaultValue
crudErrorInit[`${fieldName}Error`] = ''
}}

const SELECT = `SELECT_${componentCapitalName}`
const DESELECT = `DESELECT_${componentCapitalName}`
const SAVE = `SAVE_${componentCapitalName}`
const LOAD = `LOAD_${listCapitalName}`
const STORE = `STORE_${componentCapitalName}`
const DELETE = `DELETE_${componentCapitalName}`

const actions = {}
const reducers = {}

actions[`select${componentProperName}`] = (component) =>{
return {type: SELECT, component}
}
actions[`deselect${componentProperName}`] = () =>{
return {type: DESELECT}
}
actions[`save${componentProperName}`] = (component) =>{
return {type: SAVE, component}
}
actions[`load${listProperName}`] = (list) =>{
return {type: LOAD, list}
}
actions[`store${componentProperName}`] = (component) =>{
return {type: STORE, component}
}
actions[`delete${componentProperName}`] = (component) =>{
return {type: DELETE, component}
}

reducers[componentName] = (state = {isValid: false}, action) =>{
switch (action.type) {
case SELECT: {
return action.component
}
case DESELECT: {
return {}
}
case SAVE: {
const next = Object.assign({}, action.component)
next.isValid = true
for (let fieldName of fieldNames) {
const value = String(action.component[fieldName])
const validators = fields[fieldName].validate
if (validators && validators.length > 0) {
for (let validator of validators) {
const valid = validator.func(value, validator.params)
if (!valid) {
next.isValid = false
next[`${fieldName}Error`] = validator.message
}
}
}
}
return next
}
default: return state
}
}

reducers[listName] = (state = [], action) =>{
switch (action.type) {
case LOAD: {
return action.list
}
case STORE: {
if (action.component.index === undefined) {
return [
...state,
Object.assign({}, action.component, {index: state.length})
]
}
const next = [
...state.slice(0, action.component.index),
action.component,
...state.slice(action.component.index +1, state.length)
]
return next
}
default: {
return state
}
}
}

const provider = {
actions,
reducers,
replication
}
return provider
}
19 changes: 19 additions & 0 deletions src/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Route} from 'react-router'
import React from 'react'

export default function (compDef, components) {
const mainPath = compDef.componentName
const componentProperName = compDef.componentName[0].toUpperCase()+
compDef.componentName.substring(1)
const edit = 'edit' + componentProperName
const list = 'list' + componentProperName
const display = 'display' + componentProperName
return (
<Route key={mainPath} path={mainPath}>
<Route path='edit' component={components[edit]}/>
<Route path='list' component={components[list]}/>
<Route path='display' component={components[display]}/>
</Route>
)
}

0 comments on commit 4cfe41e

Please sign in to comment.