Commit 1e46bfbb authored by andrew's avatar andrew

Merge branch 'develop' into 'master'

material-ui migration

See merge request sf/cm-frontend-lib!56
parents cf6558ee 08fcc5dc
Pipeline #6147 failed with stage
in 3 minutes and 27 seconds
......@@ -6,11 +6,11 @@ services:
stages:
- test
cache:
paths:
- node_modules/
untracked: true
key: "cm_lib_node_modules"
#cache:
# paths:
# - node_modules/
# untracked: true
# key: "cm_lib_node_modules"
test_async:
......
......@@ -14,7 +14,7 @@ var extentions = ['.js', '.jsx'];
var pattern = /gettext\('(.*?)'\)/gi;
var elasticConfig = {
host: 'https://es.codemaster.by:443',
host: 'http://192.168.1.243:31809',
index: 'localizations',
project: 'cm-lib'
};
......
{
"Yes": "Да",
"No": "Нет",
"No data to display": "Нет данных для отображения",
" of ": " из ",
"Show:": "Показано:",
" of ": " из ",
"Type to search...": "Начните поиск...",
"Loading...": "Загрузка..."
}
\ No newline at end of file
......@@ -3,6 +3,8 @@
"name": "cm-frontend-lib",
"private": true,
"dependencies": {
"@material-ui/core": "^3.3.2",
"@material-ui/lab": "^3.0.0-alpha.23",
"backbone": "^1.3.3",
"jquery": "^2.2.3",
"libphonenumber-js": "^1.2.15",
......
......@@ -15,6 +15,8 @@ import Module from './components/classes/base.module';
import Localization from './components/classes/localization';
import modules from './components/classes/modules';
import routing from './components/classes/routing'
import * as MUILab from '@material-ui/lab';
import * as newMUI from '@material-ui/core';
import * as MUI from 'material-ui';
import { Route } from 'react-router-dom';
......@@ -91,6 +93,8 @@ CM.collections.BaseCollection = BaseCollection;
CM.collections.PaginatedCollection = PaginatedCollection;
CM.UI = UI;
CM.MUI = MUI;
CM.MUILab = MUILab;
CM.newMUI = newMUI;
CM.Route = Route;
......
......@@ -8,12 +8,12 @@ var PaginatedCollection = BaseCollection.extend({
total: 0,
numberOfPages: 0,
perPage: 10,
currentPage: 1,
previousPage: 1,
currentPage: 0,
previousPage: 0,
sortBy: 'id',
sortOrder: 'ASC',
ascendSortOrder: 'ASC',
descendSortOrder: 'DESC',
sortOrder: 'asc',
ascendSortOrder: 'asc',
descendSortOrder: 'desc',
remoteSort: true,
filterProps: {},
filterItems: [],
......@@ -316,10 +316,11 @@ var PaginatedCollection = BaseCollection.extend({
},
getRequestFilter: function () {
var filter = _.extend({}, this.filterProps, {
skip: (this.getCurrentPage() - 1) * this.getPerPage(),
const sortDir = this.getSortDir().toUpperCase();
const filter = _.extend({}, this.filterProps, {
skip: this.getCurrentPage() * this.getPerPage(),
limit: this.getPerPage(),
order: `${this.getSortBy()} ${this.getSortDir()}`,
order: `${this.getSortBy()} ${sortDir}`,
includeCount: true
});
......
......@@ -9,7 +9,7 @@
font-size: 16px;
.rrui__select {
margin-top: 35px;
margin-top: 19px;
.rrui__expandable--overlay {
z-index: 2;
......@@ -41,6 +41,7 @@
.react-phone-number-input__phone {
&.rrui__input-field {
border: none;
height: auto !important;
}
}
}
......
......@@ -13,11 +13,11 @@ import { Box, Item } from './flexbox/flexbox';
import Table from './table/table';
import Message from './notification/message';
import Span from './views/view.span';
import Progress from './progress/progress';
import LinearProgress from './progress/linear.progress';
import {colors} from 'material-ui/styles';
import ColorManipulator from 'material-ui/utils/colorManipulator';
import Spacing from 'material-ui/styles/spacing'
import * as Colors from '@material-ui/core/colors';
//@TODO Table
let UI = {
Form,
View,
......@@ -28,14 +28,13 @@ let UI = {
Message,
Span,
LinearProgress,
Progress,
Flexbox: {
Box: Box,
Item: Item
Box,
Item
},
Styles: {
Colors: colors,
ColorManipulator: ColorManipulator,
Spacing: Spacing
Colors
}
};
......
......@@ -3,14 +3,16 @@
import React from 'react';
import _ from 'underscore';
import TextField from 'material-ui/TextField';
import TextField from '@material-ui/core/TextField';
import withValidation from '../hoc/with.validation';
const FormInput = (props) => {
let {
label,
isValid,
getErrorText,
successText,
helperText,
successStyle,
isEditable,
handleChange,
......@@ -18,28 +20,31 @@ const FormInput = (props) => {
value,
...inputProps
} = props;
const errorText = isValid ? null : getErrorText();
successText = (successText && !errorText) ? successText : null;
successStyle = _.extend({}, styles.successText, successStyle);
inputProps = {
readOnly: !isEditable,
...inputProps
};
return (
<div>
<TextField
readOnly={!isEditable}
error={isValid ? false : true}
label={label}
onChange={handleChange}
onBlur={handleBlur}
errorText={errorText}
{...inputProps}
value={value || ''} />
value={value || ''}
helperText={isValid ? helperText : errorText}
inputProps={inputProps}
/>
<div style={successStyle} className="success-text">{successText}</div>
</div>
);
};
const styles = {
successText: {}
};
function getInputValue(e) {
let value = null;
switch (this.props.type) {
......
......@@ -16,26 +16,22 @@ const FormPhoneInput = (props) => {
handleChange,
handleBlur,
value,
isValid,
getErrorText,
defaultCountry = 'BY',
...rest
...inputProps
} = props;
const errorText = isValid ? null : getErrorText();
return (
<PhoneInput
{...rest}
value={value || ''}
country={defaultCountry}
countries={countries}
onChange={handleChange}
errorText={errorText}
onBlur={handleBlur}
inputComponent={PhoneBasicInput}
smartCaret={false}
metadata={metadata}
{...inputProps}
/>
);
};
......
......@@ -2,7 +2,7 @@
import React, { PureComponent } from 'react'
import { parsePhoneNumberCharacters, formatPhoneNumber } from 'react-phone-number-input/custom';
import TextField from 'material-ui/TextField';
import TextField from '@material-ui/core/TextField';
export default class PhoneBasicInput extends PureComponent {
......@@ -51,24 +51,35 @@ export default class PhoneBasicInput extends PureComponent {
focus() {
this.input.focus()
}
//@TODO fix phone number format
render() {
const {
onChange,
country,
metadata,
disabled,
...rest
value,
helperText,
onBlur,
label,
isValid,
getErrorText,
...inputProps
} = this.props;
const { value } = this.state;
const errorText = isValid ? null : getErrorText();
const { value: inputValue } = this.state;
return (
<TextField
{...rest}
ref={(ref) => this.input = ref}
value={this.formatByCoutry(value)}
error={!isValid}
label={label}
helperText={isValid ? helperText : errorText}
inputProps={inputProps}
inputRef={(ref) => this.input = ref}
value={this.formatByCoutry(inputValue)}
onChange={this.onChange}
onBlur={onBlur}
/>
)
}
......
......@@ -10,8 +10,11 @@ import ProgressComponent from './../progress/progress.jsx';
import DialogComponent from './../dialogs/basic.dialog.jsx';
import MapSubRoutes from './map.module.jsx';
import { HashRouter as Router } from 'react-router-dom';
import { MuiThemeProvider } from 'material-ui';
import theme from './../mui.theme';
export default class ModuleComponent extends React.Component{
constructor(props) {
......@@ -32,10 +35,6 @@ export default class ModuleComponent extends React.Component{
this.showDialog = this.showDialog.bind(this);
}
getChildContext() {
return {muiTheme: theme};
}
showMessage(text, type) {
this.messageComponent.message(text, type);
}
......@@ -109,15 +108,11 @@ export default class ModuleComponent extends React.Component{
}
render() {
let messageComponentProps = this.props.messageComponentProps || {};
return (
<div>
<MuiThemeProvider muiTheme={theme}>
<MessageComponent
ref={this.getMessageRef}
autoHideDuration={messageComponentProps.autoHideDuration}
handleAction={messageComponentProps.handleAction}
styles={messageComponentProps.styles}
/>
{this.getFormWithCustomLoadingTemplate()}
......@@ -133,7 +128,7 @@ export default class ModuleComponent extends React.Component{
hideProgress={this.hideProgress}
/>
</Router>
</div>
</MuiThemeProvider>
);
}
......
......@@ -5,6 +5,7 @@ var getMuiTheme = require('material-ui/styles/getMuiTheme');
var Colors = require('material-ui/styles/colors');
var ColorManipulator = require('material-ui/utils/colorManipulator');
var Spacing = require('material-ui/styles/spacing');
var theme = getMuiTheme.default({
spacing: Spacing,
fontFamily: 'Open Sans, sans-serif',
......@@ -28,5 +29,4 @@ var theme = getMuiTheme.default({
}
});
module.exports = theme;
export default theme;
\ No newline at end of file
import React from 'react';
import SnackbarContent from '@material-ui/core/SnackbarContent';
import { withStyles } from '@material-ui/core/styles';
const styles = theme => ({
info: {
backgroundColor: theme.palette.primary.main
},
error: {
backgroundColor: theme.palette.error.main
},
message: {
height: '100%',
overflow: 'hidden',
}
});
const MessageContent = props => {
const { variant, message, classes, className, ...other } = props;
return (
<SnackbarContent
message={message}
className={classes[variant] + ' ' + className}
{...other}
/>
)
};
export default withStyles(styles)(MessageContent);
......@@ -2,9 +2,10 @@
'use strict';
import React from 'react';
import { Snackbar } from 'material-ui';
import Snackbar from '@material-ui/core/Snackbar';
import MessageContent from './message.content';
export default class MessageComponent extends React.Component {
class MessageComponent extends React.Component {
constructor(){
super();
......@@ -12,16 +13,16 @@ export default class MessageComponent extends React.Component {
this.state = {
open: false,
text: '',
type: 'info'
variant: 'info'
};
this.handleRequestClose = this.handleRequestClose.bind(this);
}
message(message, type) {
message(message, variant) {
this.setState({
text: message,
type: type,
variant: variant,
open: true
});
......@@ -29,64 +30,44 @@ export default class MessageComponent extends React.Component {
getStyles() {
const styles = {
snackbar: {
error: {
backgroundColor: CM.UI.Styles.Colors.red600
},
info: {
backgroundColor: CM.UI.Styles.Colors.lightBlueA500
}
},
bodyStyle: {
height: 'auto',
maxHeight: '96px',
padding: '12px 24px',
lineHeight: '24px',
whiteSpace: 'pre-line'
},
contentStyle: {
height: '100%',
overflow: 'hidden'
}
height: 'auto',
maxHeight: '96px',
padding: '12px 24px',
lineHeight: '24px',
whiteSpace: 'pre-line'
};
return styles;
}
getStyleByType() {
let styles = this.props.styles ? {snackbar: this.props.styles} : this.getStyles(),
style = styles.snackbar[this.state.type];
if (!style) {
CM.error('[CM] supported messaages types are ' + _.keys(styles.snackbar) );
}
return style;
}
handleRequestClose() {
this.setState({
open: false
});
}
render () {
const styles = this.getStyles();
const autoHideDuration = this.props.autoHideDuration || 3000;
const handleAction = this.props.handleAction || function(){};
const bodyStyle = _.extend({}, styles.bodyStyle, this.getStyleByType());
const styles = this.getStyles();
return (
<Snackbar
message={this.state.text}
//@TODO export default withStyles(styles)(MessageComponent)
style={styles}
open={this.state.open}
action={this.state.action}
autoHideDuration={autoHideDuration}
onActionClick={handleAction}
onRequestClose={this.handleRequestClose}
bodyStyle={bodyStyle}
contentStyle={styles.contentStyle}
/>
onClose={this.handleRequestClose}
>
<MessageContent
variant={this.state.variant}
message={this.state.text}
/>
</Snackbar>
);
}
}
\ No newline at end of file
}
export default MessageComponent;
\ No newline at end of file
......@@ -2,7 +2,7 @@
'use strict';
import React from 'react';
import {LinearProgress} from 'material-ui';
import LinearProgress from '@material-ui/core/LinearProgress';
export default class LinearProgressComponent extends React.Component {
......@@ -54,5 +54,5 @@ export default class LinearProgressComponent extends React.Component {
}
LinearProgressComponent.defaultProps = {
mode: 'indeterminate'
variant: 'indeterminate'
};
\ No newline at end of file
......@@ -2,7 +2,7 @@
'use strict';
import React from 'react';
import {CircularProgress} from 'material-ui';
import CircularProgress from '@material-ui/core/CircularProgress';
export default class ProgressComponent extends React.Component{
......@@ -10,7 +10,7 @@ export default class ProgressComponent extends React.Component{
super();
this.state = {
visible: false
visible: false
};
}
......
import React from 'react';
import TableBody from '@material-ui/core/TableBody';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import IconButton from '@material-ui/core/IconButton';
import Icon from '@material-ui/core/Icon';
import Tooltip from '@material-ui/core/Tooltip';
const oneActionButtonWidth = 48;
export default class TableBodyComponent extends React.Component {
getColumnSpan() {
const hasActions = this.props.actions && this.props.actions.length > 0,
colspan = this.props.columns.length + (hasActions ? 1 : 0);
return colspan;
}
getNoDataTemplate() {
const style = this.props.style || '';
return (
<TableBody
displayRowCheckbox={false}
style={style}
>
<TableRow
className={this.props.classes.tableRow}
>
<TableCell
className={this.props.classes.tableColumn}
colSpan={this.getColumnSpan()}
style={{ textAlign: 'center' }}
>
{CM.gettext('No data to display')}
</TableCell>
</TableRow>
</TableBody>
);
}
getTableBody() {
const style = this.props.style || '';
const tableBodyRows = this.props.collection.map(this.getTableBodyRow, this);
return (
<TableBody
hover={this.props.showRowHover}
style={style}
>
{tableBodyRows}
</TableBody>
)
}
getTableBodyRow(model) {
const rowColor = this.props.collection.getRowColor ? this.props.collection.getRowColor(model) : false;
const style = rowColor ? { backgroundColor: rowColor } : {};
const tableBodyColumns = this.props.columns.map(this.getTableBodyRowColumn.bind(this, model, style));
return (
<TableRow
key={`cm-tr-${model.id}`}
className={this.props.classes.tableRow}
selected={model.get('selected')}
style={style}
>
{tableBodyColumns}
{this.getActionsColumnForBody(model)}
</TableRow>
)
}
getTableBodyRowColumn(model, style, column) {
let value = model.get(column.property);
// formatting collection name to necessary format
// or string calling model function or function from collection
if (typeof(column.format) === 'string' && model[column.format]) {
value = model[column.format](column.property);
}
if (typeof(column.format) === 'function') {
value = column.format.call(this.props.collection, model);
}
let cellStyle = _.extend({}, style);
if (column.width) {
cellStyle.width = column.width;
}
if (column.overflow) {