Design TableList component

This commit is contained in:
cyril lopez 2017-08-17 14:39:25 +02:00
parent 262f2e9c86
commit a568c54e5f
12 changed files with 242 additions and 81 deletions

View File

@ -1,46 +0,0 @@
/**
*
* Table
*
*/
import React from 'react';
import { FormattedMessage } from 'react-intl';
import ButtonPrimaryHotline from 'components/Button';
import styles from './styles.scss';
class Table extends React.Component { // eslint-disable-line react/prefer-stateless-function
render() {
return (
<div className={styles.table}>
<div className="container-fluid">
<div className="row">
<div className={styles.headerContainer}>
<div className={styles.titleContainer}>
{this.props.availableNumber}&nbsp;<FormattedMessage {...{ id: this.props.title }} />
</div>
<div className={styles.buttonContainer}>
<ButtonPrimaryHotline
buttonBackground={'secondaryAddType'}
label={this.props.buttonLabel}
handlei18n
addShape
onClick={this.props.handleButtonClick}
/>
</div>
</div>
</div>
</div>
</div>
);
}
}
Table.propTypes = {
availableNumber: React.PropTypes.number.isRequired,
buttonLabel: React.PropTypes.string.isRequired,
handleButtonClick: React.PropTypes.func,
title: React.PropTypes.string.isRequired,
};
export default Table;

View File

@ -1,21 +0,0 @@
.table { /* stylelint-disable */
padding: 2rem 3.2rem 3.2rem 1.8rem;
// background: red;
background: #FFFFFF;
font-family: Lato;
}
.headerContainer {
display: flex;
flex-direction: row;
width: 100%;
justify-content: space-between;
}
.titleContainer {
color: #333740;
font-size: 1.8rem;
font-weight: bold;
line-height: 2.2rem;
}

View File

@ -0,0 +1,103 @@
/**
*
* TableList
*
*/
import React from 'react';
import { map, startCase } from 'lodash';
import { FormattedMessage } from 'react-intl';
import ButtonPrimaryHotline from 'components/Button';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-static-element-interactions */
class TableList extends React.Component { // eslint-disable-line react/prefer-stateless-function
delete = () => {
console.log('will delete');
}
edit = () => {
console.log('edit');
}
goTo = (e) => {
if (e.target.id !== 'edit' && e.target.id !== 'delete') {
console.log('will go to');
}
}
render() {
return (
<div className={styles.tableListContainer}>
<div className="container-fluid">
<div className="row">
<div className={styles.headerContainer}>
<div className={styles.titleContainer}>
{this.props.availableNumber}&nbsp;<FormattedMessage {...{ id: this.props.title }} />
</div>
<div className={styles.buttonContainer}>
<ButtonPrimaryHotline
buttonBackground={'secondaryAddType'}
label={this.props.buttonLabel}
handlei18n
addShape
onClick={this.props.handleButtonClick}
/>
</div>
</div>
</div>
<div className="row">
<div className={styles.ulContainer}>
<ul>
<li>
<div className={`${styles.liHeaderContainer} row`}>
<div className="col-md-1"></div>
<div className="col-md-2"><FormattedMessage {...{ id: 'table.contentType.head.name' }} /></div>
<div className="col-md-5 text-center"><FormattedMessage {...{ id: 'table.contentType.head.description' }} /></div>
<div className="col-md-3 text-center"><FormattedMessage {...{ id: 'table.contentType.head.fields' }} /></div>
<div className="col-md-1"></div>
</div>
</li>
{map(this.props.rowItems, (rowItem, key) => (
<li key={key} onClick={this.goTo}>
<div className={styles.hovered} />
<div className={`${styles.liInnerContainer} row`}>
<div className="col-md-1"><i className={`fa ${rowItem.icon}`} /></div>
<div className="col-md-2">{startCase(rowItem.name)}</div>
<div className="col-md-5 text-center">{rowItem.description}</div>
<div className="col-md-3 text-center">{rowItem.fields}</div>
<div className="col-md-1">
<div className={styles.icoContainer}>
<div>
<i className="fa fa-pencil" id="edit" onClick={this.edit} />
</div>
<div>
<i className="fa fa-trash" id="delete" onClick={this.delete} />
</div>
</div>
</div>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
);
}
}
TableList.propTypes = {
availableNumber: React.PropTypes.number.isRequired,
buttonLabel: React.PropTypes.string.isRequired,
handleButtonClick: React.PropTypes.func,
rowItems: React.PropTypes.array.isRequired,
title: React.PropTypes.string.isRequired,
};
export default TableList;

View File

@ -0,0 +1,122 @@
.tableListContainer { /* stylelint-disable */
padding: 2rem 0 0rem 0;
background: #FFFFFF;
font-family: Lato;
}
.headerContainer {
width: 100%;
padding: 0 1.8rem 0 1.8rem;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.titleContainer {
color: #333740;
font-size: 1.8rem;
font-weight: bold;
line-height: 2.2rem;
}
.ulContainer {
margin-top: 1.6rem;
width: 100%;
> ul {
margin: 0;
padding: 0;
list-style: none;
> li:first-child {
margin-bottom: .5rem;
border-radius: 2px 2px 0 0;
background-color: #F3F3F4;
// background-color: rgba(16,22,34,0.04);
}
> li:not(:first-child) {
position: relative;
margin-bottom: .2rem;
cursor: pointer;
&:hover {
.hovered {
position: absolute;
width: 100%;
height: 5.4rem;
top: -.2rem;
background-color: #F7F8F8;
}
}
}
> li:nth-child(2) {
&:hover {
.hovered {
position: absolute;
width: 100%;
height: 5.6rem;
top: -.5rem;
background-color: #F7F8F8;
}
}
}
> li:last-child {
margin-bottom: 0;
.liInnerContainer {
border-bottom: none;
}
}
}
}
.liHeaderContainer {
height: 3rem;
margin: 0;
padding: 0 4.6rem 0 1.9rem;
font-size: 1.3rem;
line-height: 1.6rem;
font-weight: 600;
> div {
padding: 0;
align-self: center;
}
> div:last-child {
text-align: right;
}
}
.liInnerContainer {
height: 5.2rem;
margin: 0 3.2rem 0 1.9rem ;
padding: 0 1.4rem 0 0rem;
border-bottom: 1px solid rgba(14,22,34,0.04);
color: #333740;
font-size: 1.3rem;
> div {
padding: 0;
align-self: center;
}
> div:first-child{
padding-left: 1.4rem;
}
> div:last-child {
text-align: right;
}
> div:nth-child(2) {
font-weight: 600;
}
}
.icoContainer {
display: flex;
justify-content: flex-end;
> div {
color: #0E1622;
> i {
font-size: 1.1rem;
}
}
> div:last-child {
margin-left: 1.3rem;
}
}

View File

@ -1,10 +1,10 @@
// import Table from '../index';
// import TableList from '../index';
import expect from 'expect';
// import { shallow } from 'enzyme';
// import React from 'react';
describe('<Table />', () => {
describe('<TableList />', () => {
it('Expect to have unit tests specified', () => {
expect(true).toEqual(false);
});

View File

@ -7,14 +7,12 @@
import { MODELS_FETCH, MODELS_FETCH_SUCCEEDED } from './constants';
export function modelsFetch() {
console.log('fetching models');
return {
type: MODELS_FETCH,
};
}
export function modelsFetchSucceeded(models) {
console.log('succeeded');
return {
type: MODELS_FETCH_SUCCEEDED,
models,

View File

@ -24,7 +24,6 @@ define(map(messages, (message, id) => ({
class App extends React.Component {
componentDidMount() {
console.log('did mount');
this.props.modelsFetch();
}

View File

@ -18,7 +18,6 @@ function appReducer(state = initialState, action) {
case MODELS_FETCH:
return state.set('loading', true);
case MODELS_FETCH_SUCCEEDED:
console.log('ok');
return state
.set('loading', false)
.set('models', List(action.models.models));

View File

@ -9,10 +9,10 @@ export function* fetchModels() {
const requestUrl = '/content-type-builder/models';
const data = yield call(request, requestUrl, { method: 'GET' });
console.log('data', data);
yield put(modelsFetchSucceeded(data));
} catch(error) {
// TODO handle i18n
window.Strapi.notification.error('notification.error.message')
}
}

View File

@ -15,7 +15,7 @@ import { makeSelectLoading, makeSelectModels } from 'containers/App/selectors';
// Design
import ContentHeader from 'components/ContentHeader';
import EmptyContentTypeView from 'components/EmptyContentTypeView';
import Table from 'components/Table';
import TableList from 'components/TableList';
import selectHomePage from './selectors';
import styles from './styles.scss';
@ -26,16 +26,17 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
console.log('ici', this.props.homePage);
}
renderTableComponent = () => {
renderTableListComponent = () => {
const availableNumber = size(this.props.models);
const title = availableNumber > 1 ? 'table.contentType.title.plural'
: 'table.contentType.title.singular';
return (
<Table
<TableList
availableNumber={availableNumber}
title={title}
buttonLabel={'button.contentType.add'}
handleButtonClick={this.handleClick}
rowItems={this.props.models}
/>
);
}
@ -46,7 +47,7 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
const component = size(this.props.models) === 0 ?
<EmptyContentTypeView handleClick={this.handleClick} />
: this.renderTableComponent();
: this.renderTableListComponent();
return (
<div className={styles.homePage}>

View File

@ -1,6 +1,6 @@
{
"home.contentTypeBuilder.name": "Content Types",
"home.contentTypeBuilder.description": "Create, update you own content types.",
"home.contentTypeBuilder.description": "Create, update your own content types.",
"home.emptyContentType.title": "There is no Content Type Available",
"home.emptyContentType.description": "Create your first Content Type to be able to retrieve data from your API.",
@ -10,6 +10,9 @@
"notification.error.message": "An error occured",
"table.contentType.title.plural": "Content Types are available",
"table.contentType.title.singular": "Content Type is available"
"table.contentType.title.singular": "Content Type is available",
"table.contentType.head.name": "Name",
"table.contentType.head.description": "Description",
"table.contentType.head.fields": "Fields"
}

View File

@ -10,6 +10,9 @@
"notification.error.message": "Une erreur est survenue",
"table.contentType.title.plural": "Modèles sont disponibles",
"table.contentType.title.singular": "Modèle est disponible"
"table.contentType.title.singular": "Modèle est disponible",
"table.contentType.head.name": "Nom",
"table.contentType.head.description": "Description",
"table.contentType.head.fields": "Champs"
}