Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List #145

Merged
merged 10 commits into from
Jul 24, 2015
Merged

List #145

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./node_modules/.bin/gulp build
6 changes: 1 addition & 5 deletions list/table/line.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ let lineMixin = {
return () => {this.props.onLineClick(data); };
},
render() {
return (
<div onClick={this._onLineClickHandler(this.props.onLineClick)}>
{this.renderLineContent(this.props.data)}
</div>
);
return this.renderLineContent(this.props.data);
}
};

Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"scripts": {
"test": "exit 0",
"example": "node static-server.js",
"build": "gulp browserify",
"build": "sh ./build.sh",
"watch": "gulp watchify",
"prepublish": "gulp build"
"prepublish": "gulp build",
"serve": "sh ./build.sh && node static-server.js"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -192,6 +193,10 @@
"name": "block",
"path": "common/block"
},
{
"name": "list-page",
"path": "page/list"
},
{
"name": "quick-search",
"path": "page/search/quick-search"
Expand Down
1 change: 1 addition & 0 deletions page/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = {
detail: detailMixin,
search: require('./search'),
mixin: require('./mixin'),
list: require('./list'),
/**
* Helper to creates a detail page.
* @param {object} config - The page configuration.
Expand Down
91 changes: 91 additions & 0 deletions page/list/example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Test search-result mixin</title>
<meta name="description" content="Example of the component.">
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- Place favicon.ico in the root directory -->

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"/>
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>

<!-- Material degign-->
<link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap.material-design/0.3.0/css/material-wfont.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap.material-design/0.3.0/css/material.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap.material-design/0.3.0/css/ripples.min.css">
<script src="//cdn.jsdelivr.net/bootstrap.material-design/0.3.0/js/material.min.js"></script>
<script src="//cdn.jsdelivr.net/bootstrap.material-design/0.3.0/js/ripples.min.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone.js"></script>
<!-- Material degign-->

<script src="/focus-components/dist/js/focus.js"></script>
<script src="/focus-components/dist/js/focus-components.js"></script>
<script src="/focus-components/example/js/initFocus.js"></script>
<link rel="stylesheet" href="/focus-components/dist/css/focus-components.css"/>

</head>
<body>
<div id="list-container" style=" width:70%;margin: auto;"></div>

<script type="text/jsx">
var countId = 0;
var service = function (criteria) {
console.log('criteria', criteria);
var fakeData = [];
for(var i = 0; i < 150; i++){
fakeData.push({
id: i,
firstName: 'firstName ' + i,
lastName: 'lastName ' + i,
birthDate: Date.now(),
age : i
})
}
var begin = criteria.urlData.skip;
var end = begin + criteria.urlData.top;
return Promise.resolve(fakeData.slice(begin, end)).then(function(d){
return {dataList: d, totalCount: fakeData.length}
});
};

var Line = React.createClass({
mixins: [FocusComponents.list.table.line.mixin],
definitionPath: "contact",
renderLineContent: function(data){
console.log('line content')
return (
<tr onClick={this.props.onLineClick}>
<td>{this.textFor("firstName", {})}</td>
<td>{this.textFor("lastName", {})}</td>
<td>{this.textFor("birthDate", {})}</td>
</tr>
);
}
});

var listStore = new Focus.store.ListStore({identifier: 'LIST_TEST'});

var listPageProps = {
onLineClick: function onLineClick(line) {
alert('click sur la ligne ' + line.id);
},
lineComponent: Line,
store: listStore,
service: service
};
var ListPage = FocusComponents.page.list.component;

React.render(<ListPage {...listPageProps} />, document.querySelector("#list-container"));
</script>

</body>

</html>
103 changes: 103 additions & 0 deletions page/list/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//The purpose of this module is to deal with autonomous lists.
//If you need lists inside a form please see the listFor helper function in a form.
//The following lists can
//- be loaded from a criteria (or without) (the criteria can be the result of a form)
//- be paginated
//- be displayed in any list container.
let {camelCase, capitalize} = require('lodash/string');
let {types, builder} = require('focus').component;
let actionBuilder = require('focus').list.actionBuilder;
let type = types;
let assign = require('object-assign');

const STORE_NODE = ['criteria', 'groupingKey', 'sortBy', 'sortAsc', 'dataList', 'totalCount'];
const DEFAULT_LIST_COMPONENT = require('../../list/table/list').component;
/**
* Cretes a name for the property listener.
* @param {string} node - Node name.
* @return {string} the built property.
*/
function _listenerProp(node){
return `add${capitalize(camelCase(node))}ChangeListener`;
}
/**
* Mixin to deal the list page.
* @type {Object}
*/
let listPageMixin = {
getDefaultProps(){
return {
ListComponent: DEFAULT_LIST_COMPONENT,
pickProps(props){return props;}
};
},
getInitialState(){
return {};
},
/** @inheritdoc */
propTypes: {
//Store object.
pickProps: type('func'),
service: type('func'),
store: type('object').isRequired
},
/**
* Build the action from.
*/
_buildAction(){
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let {action, service, store} = this.props;

this._action = this.props.action || actionBuilder({
service: this.props.service,
identifier: this.props.store.identifier,
getListOptions: () => {return this.props.store.getValue.call(this.props.store); } // Binding the store in the function call
});
},
/**
* Read the state from the store.
* @return {object} - The object read from the store.
*/
_getStateFromStore(){
let store = this.props.store;
return store.getValue();
},
/**
* Hanlde the list store change.
*/
_handleStoreChanged(){
this.setState(this._getStateFromStore());
},
/**
* Register the store nodes.
*/
_registerStoreNode(){
STORE_NODE.forEach((node)=>{
this.props.store[_listenerProp(node)](this._handleStoreChanged)
});
},
/**
* build the list props.
* @return {object} - the list property.
*/
_buildListProps(){
let {props, state} = this;
let {dataList, totalCount} = state;
dataList = dataList || [];
return assign(props, state, {
data: dataList,
fetchNextPage: this._action.load,
hasMoreData: dataList.length < totalCount
});
},
/** @inheritdoc */
componentWillMount(){
this._registerStoreNode();
this._buildAction();
this._action.load();
},
/** @inheritdoc */
render(){
let listProps = this._buildListProps();
return <this.props.ListComponent {...listProps} />;
}
};

module.exports = builder(listPageMixin);
41 changes: 41 additions & 0 deletions page/list/mixin/store-connector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
let React = require('react');
let isEqual = require('lodash/lang/isEqual');
module.exports = function connectToStores(Component, stores, pickProps, getState) {
return class StoreConnector extends React.Component {
constructor(props) {
super(props);
this.state = this.getStateFromStores(props);
this.handleStoresChanged = this.handleStoresChanged.bind(this);
}

getStateFromStores(props) {
return getState(pickProps(props));
}

componentDidMount() {
stores.forEach(store =>
store.addChangeListener(this.handleStoresChanged)
);
}

componentWillReceiveProps(nextProps) {
if (!isEqual(pickProps(nextProps), pickProps(this.props))) { //isEqual
this.setState(this.getStateFromStores(nextProps));
}
}

componentWillUnmount() {
stores.forEach(store =>
store.removeChangeListener(this.handleStoresChanged)
);
}

handleStoresChanged() {
this.setState(this.getStateFromStores(this.props));
}

render() {
return <Component {...this.props} {...this.state} />;
}
};
}
2 changes: 1 addition & 1 deletion page/search/advanced-search/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let actionBuilder = Focus.search.actionBuilder;
let AdvancedSearch = {
/**
* Component's mixins
* @type {Array}
* @type {Array}
*/
mixins: [CartridgeBehaviour],
/**
Expand Down