input.onChange(value)}
+ />
+);
+
+// validation functions
+const required = value => (value == null ? 'Required' : undefined);
+const email = value => (
+ value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
+ ? 'Invalid email'
+ : undefined
+);
+
+const styles = ({
+ root: {
+ flexGrow: 1,
+ },
+ field: {
+ width: '100%',
+ marginBottom: 20
+ },
+ fieldBasic: {
+ width: '100%',
+ marginBottom: 20,
+ marginTop: 10
+ },
+ inlineWrap: {
+ display: 'flex',
+ flexDirection: 'row'
+ }
+});
+
+class CrudTbFormDemo extends Component {
+ saveRef = ref => {
+ this.ref = ref;
+ return this.ref;
+ };
+
+ render() {
+ const {
+ classes,
+ fetchData,
+ addNew,
+ closeForm,
+ submit,
+ removeRow,
+ editRow,
+ dataTable,
+ openForm,
+ initValues,
+ closeNotif,
+ messageNotif,
+ } = this.props;
+ const trueBool = true;
+ return (
+
+
closeNotif(branch)} message={messageNotif} />
+
+
+ {/* Create Your own form, then arrange or custom it as You like */}
+
+
+
+
+
+
+
+ Choose One Option
+
+ } label="Option 1" />
+ } label="Option 2" />
+
+
+
+
+ Selection
+
+
+
+
+
+
+
+
+
Toggle Input
+
+ } label="On/OF Switch" />
+ } label="Checkbox" />
+
+
+
+
+
+ {/* No need create button or submit, because that already made in this component */}
+
+
+
+ );
+ }
+}
+
+renderRadioGroup.propTypes = {
+ input: PropTypes.object.isRequired,
+};
+
+CrudTbFormDemo.propTypes = {
+ dataTable: PropTypes.object.isRequired,
+ openForm: PropTypes.bool.isRequired,
+ classes: PropTypes.object.isRequired,
+ fetchData: PropTypes.func.isRequired,
+ addNew: PropTypes.func.isRequired,
+ closeForm: PropTypes.func.isRequired,
+ submit: PropTypes.func.isRequired,
+ removeRow: PropTypes.func.isRequired,
+ editRow: PropTypes.func.isRequired,
+ initValues: PropTypes.object.isRequired,
+ closeNotif: PropTypes.func.isRequired,
+ messageNotif: PropTypes.string.isRequired,
+};
+
+
+const mapStateToProps = state => ({
+ force: state, // force state from reducer
+ initValues: state.getIn([branch, 'formValues']),
+ dataTable: state.getIn([branch, 'dataTable']),
+ openForm: state.getIn([branch, 'showFrm']),
+ messageNotif: state.getIn([branch, 'notifMsg']),
+});
+
+const mapDispatchToProps = dispatch => ({
+ fetchData: bindActionCreators(fetchAction, dispatch),
+ addNew: bindActionCreators(addAction, dispatch),
+ closeForm: bindActionCreators(closeAction, dispatch),
+ submit: bindActionCreators(submitAction, dispatch),
+ removeRow: bindActionCreators(removeAction, dispatch),
+ editRow: bindActionCreators(editAction, dispatch),
+ closeNotif: bindActionCreators(closeNotifAction, dispatch),
+});
+
+const CrudTbFormDemoMapped = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(CrudTbFormDemo);
+
+export default withStyles(styles)(CrudTbFormDemoMapped);
diff --git a/front/odiparpack/app/containers/Tables/demos/EmptyTable.js b/front/odiparpack/app/containers/Tables/demos/EmptyTable.js
new file mode 100644
index 0000000..c9517a2
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/EmptyTable.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { EmptyData } from 'ba-components';
+
+import { Toolbar, Typography, Table, TableCell, TableHead, TableRow, Paper } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ table: {
+ minWidth: 700,
+ },
+});
+
+function EmptyTable(props) {
+ const { classes } = props;
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Calories
+ Fat (g)
+ Carbs (g)
+ Protein (g)
+
+
+
+
+
+ );
+}
+
+EmptyTable.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(EmptyTable);
diff --git a/front/odiparpack/app/containers/Tables/demos/HoverTable.js b/front/odiparpack/app/containers/Tables/demos/HoverTable.js
new file mode 100644
index 0000000..48047c6
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/HoverTable.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import tableStyles from 'ba-styles/Table.scss';
+
+import {
+ Toolbar,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Paper,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ table: {
+ minWidth: 700,
+ },
+});
+
+let id = 0;
+function createData(name, calories, fat, carbs, protein) {
+ id += 1;
+ return {
+ id,
+ name,
+ calories,
+ fat,
+ carbs,
+ protein
+ };
+}
+
+const data = [
+ createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
+ createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
+ createData('Eclair', 262, 16.0, 24, 6.0),
+ createData('Cupcake', 305, 3.7, 67, 4.3),
+ createData('Gingerbread', 356, 16.0, 49, 3.9),
+];
+
+function HoverTable(props) {
+ const { classes } = props;
+
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Calories
+ Fat (g)
+ Carbs (g)
+ Protein (g)
+
+
+
+ {data.map(n => ([
+
+ {n.name}
+ {n.calories}
+ {n.fat}
+ {n.carbs}
+ {n.protein}
+
+ ])
+ )}
+
+
+
+ );
+}
+
+HoverTable.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(HoverTable);
diff --git a/front/odiparpack/app/containers/Tables/demos/SimpleTable.js b/front/odiparpack/app/containers/Tables/demos/SimpleTable.js
new file mode 100644
index 0000000..e064d5e
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/SimpleTable.js
@@ -0,0 +1,88 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+
+import {
+ Toolbar,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Paper,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ table: {
+ minWidth: 700,
+ },
+});
+
+let id = 0;
+function createData(name, calories, fat, carbs, protein) {
+ id += 1;
+ return {
+ id,
+ name,
+ calories,
+ fat,
+ carbs,
+ protein
+ };
+}
+
+const data = [
+ createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
+ createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
+ createData('Eclair', 262, 16.0, 24, 6.0),
+ createData('Cupcake', 305, 3.7, 67, 4.3),
+ createData('Gingerbread', 356, 16.0, 49, 3.9),
+];
+
+function SimpleTable(props) {
+ const { classes } = props;
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Calories
+ Fat (g)
+ Carbs (g)
+ Protein (g)
+
+
+
+ {data.map(n => ([
+
+ {n.name}
+ {n.calories}
+ {n.fat}
+ {n.carbs}
+ {n.protein}
+
+ ])
+ )}
+
+
+
+ );
+}
+
+SimpleTable.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimpleTable);
diff --git a/front/odiparpack/app/containers/Tables/demos/StatusColorRow.js b/front/odiparpack/app/containers/Tables/demos/StatusColorRow.js
new file mode 100644
index 0000000..2e21190
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/StatusColorRow.js
@@ -0,0 +1,121 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import messageStyles from 'ba-styles/Messages.scss';
+import progressStyles from 'ba-styles/Progress.scss';
+
+import {
+ Toolbar,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Paper,
+ Chip,
+ LinearProgress,
+} from '@material-ui/core';
+
+const CustomTableCell = withStyles(theme => ({
+ head: {
+ backgroundColor: theme.palette.common.black,
+ color: theme.palette.common.white,
+ },
+ body: {
+ fontSize: 14,
+ },
+}))(TableCell);
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ chip: {
+ margin: theme.spacing(1),
+ fontWeight: 500,
+ color: '#FFF'
+ },
+});
+
+let id = 0;
+function createData(name, progress, status) {
+ id += 1;
+ return {
+ id,
+ name,
+ progress,
+ status,
+ };
+}
+
+const data = [
+ createData('Frozen yoghurt', 24, 'Error'),
+ createData('Ice cream sandwich', 37, 'Warning'),
+ createData('Eclair', 24, 'Info'),
+ createData('Cupcake', 67, 'Default'),
+ createData('Gingerbread', 89, 'Success'),
+];
+
+function StatusLabel(props) {
+ const { classes } = props;
+ const getStatus = status => {
+ switch (status) {
+ case 'Error': return messageStyles.bgError;
+ case 'Warning': return messageStyles.bgWarning;
+ case 'Info': return messageStyles.bgInfo;
+ case 'Success': return messageStyles.bgSuccess;
+ default: return messageStyles.bgDefault;
+ }
+ };
+ const getProgress = status => {
+ switch (status) {
+ case 'Error': return progressStyles.bgError;
+ case 'Warning': return progressStyles.bgWarning;
+ case 'Info': return progressStyles.bgInfo;
+ case 'Success': return progressStyles.bgSuccess;
+ default: return progressStyles.bgDefault;
+ }
+ };
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Progress
+ Status
+
+
+
+ {data.map(n => ([
+
+ {n.name}
+
+
+
+
+
+
+
+ ])
+ )}
+
+
+
+ );
+}
+
+StatusLabel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StatusLabel);
diff --git a/front/odiparpack/app/containers/Tables/demos/StatusLabel.js b/front/odiparpack/app/containers/Tables/demos/StatusLabel.js
new file mode 100644
index 0000000..bf011dd
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/StatusLabel.js
@@ -0,0 +1,112 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import tableStyles from 'ba-styles/Table.scss';
+import messageStyles from 'ba-styles/Messages.scss';
+import progressStyles from 'ba-styles/Progress.scss';
+
+import {
+ Toolbar,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Paper,
+ Chip,
+ LinearProgress,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ chip: {
+ margin: theme.spacing(1),
+ fontWeight: 'bold',
+ color: '#FFF'
+ },
+});
+
+let id = 0;
+function createData(name, progress, status) {
+ id += 1;
+ return {
+ id,
+ name,
+ progress,
+ status,
+ };
+}
+
+const data = [
+ createData('Frozen yoghurt', 24, 'Error'),
+ createData('Ice cream sandwich', 37, 'Warning'),
+ createData('Eclair', 24, 'Info'),
+ createData('Cupcake', 67, 'Default'),
+ createData('Gingerbread', 89, 'Success'),
+];
+
+function StatusLabel(props) {
+ const { classes } = props;
+ const getStatus = status => {
+ switch (status) {
+ case 'Error': return messageStyles.bgError;
+ case 'Warning': return messageStyles.bgWarning;
+ case 'Info': return messageStyles.bgInfo;
+ case 'Success': return messageStyles.bgSuccess;
+ default: return messageStyles.bgDefault;
+ }
+ };
+ const getProgress = status => {
+ switch (status) {
+ case 'Error': return progressStyles.bgError;
+ case 'Warning': return progressStyles.bgWarning;
+ case 'Info': return progressStyles.bgInfo;
+ case 'Success': return progressStyles.bgSuccess;
+ default: return progressStyles.bgDefault;
+ }
+ };
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Progress
+ Status
+
+
+
+ {data.map(n => ([
+
+ {n.name}
+
+
+
+
+
+
+
+ ])
+ )}
+
+
+
+ );
+}
+
+StatusLabel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StatusLabel);
diff --git a/front/odiparpack/app/containers/Tables/demos/StrippedTable.js b/front/odiparpack/app/containers/Tables/demos/StrippedTable.js
new file mode 100644
index 0000000..509bc4a
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/StrippedTable.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import tableStyles from 'ba-styles/Table.scss';
+
+import {
+ Toolbar,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Paper,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+ table: {
+ minWidth: 700,
+ },
+});
+
+let id = 0;
+function createData(name, calories, fat, carbs, protein) {
+ id += 1;
+ return {
+ id,
+ name,
+ calories,
+ fat,
+ carbs,
+ protein
+ };
+}
+
+const data = [
+ createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
+ createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
+ createData('Eclair', 262, 16.0, 24, 6.0),
+ createData('Cupcake', 305, 3.7, 67, 4.3),
+ createData('Gingerbread', 356, 16.0, 49, 3.9),
+];
+
+function StrippedTable(props) {
+ const { classes } = props;
+
+ return (
+
+
+
+ Nutrition
+
+
+
+
+
+ Dessert (100g serving)
+ Calories
+ Fat (g)
+ Carbs (g)
+ Protein (g)
+
+
+
+ {data.map(n => ([
+
+ {n.name}
+ {n.calories}
+ {n.fat}
+ {n.carbs}
+ {n.protein}
+
+ ])
+ )}
+
+
+
+ );
+}
+
+StrippedTable.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StrippedTable);
diff --git a/front/odiparpack/app/containers/Tables/demos/TrackingTable.js b/front/odiparpack/app/containers/Tables/demos/TrackingTable.js
new file mode 100644
index 0000000..0550869
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/TrackingTable.js
@@ -0,0 +1,124 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import messageStyles from 'ba-styles/Messages.scss';
+import progressStyles from 'ba-styles/Progress.scss';
+import avatarApi from 'ba-api/avatars';
+import { PapperBlock } from 'ba-components';
+import styles from 'ba-components/Widget/widget-jss';
+
+import {
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Chip,
+ LinearProgress,
+ Avatar,
+ Icon,
+} from '@material-ui/core';
+
+let id = 0;
+function createData(name, avatar, title, type, taskNumber, taskTitle, progress, status) {
+ id += 1;
+ return {
+ id,
+ name,
+ avatar,
+ title,
+ type,
+ taskNumber,
+ taskTitle,
+ progress,
+ status,
+ };
+}
+
+const data = [
+ createData('John Doe', avatarApi[6], 'Front End Developer', 'bug_report', 2214, 'Vivamus sit amet interdum elit', 30, 'Error'),
+ createData('Jim Doe', avatarApi[8], 'System Analyst', 'flag', 2455, 'Nam sollicitudin dignissim nunc', 70, 'Success'),
+ createData('Jane Doe', avatarApi[2], 'Back End Developer', 'whatshot', 3450, 'Quisque ut metus sit amet augue rutrum', 50, 'Warning'),
+ createData('Jack Doe', avatarApi[9], 'CTO', 'settings', 4905, 'Cras convallis lacus orci', 85, 'Info'),
+ createData('Jessica Doe', avatarApi[5], 'Project Manager', 'book', 4118, 'Aenean sit amet magna vel magna', 33, 'Default'),
+];
+
+function TrackingTable(props) {
+ const { classes } = props;
+ const getStatus = status => {
+ switch (status) {
+ case 'Error': return messageStyles.bgError;
+ case 'Warning': return messageStyles.bgWarning;
+ case 'Info': return messageStyles.bgInfo;
+ case 'Success': return messageStyles.bgSuccess;
+ default: return messageStyles.bgDefault;
+ }
+ };
+ const getProgress = status => {
+ switch (status) {
+ case 'Error': return progressStyles.bgError;
+ case 'Warning': return progressStyles.bgWarning;
+ case 'Info': return progressStyles.bgInfo;
+ case 'Success': return progressStyles.bgSuccess;
+ default: return progressStyles.bgDefault;
+ }
+ };
+ const getType = type => {
+ switch (type) {
+ case 'bug_report': return classes.red;
+ case 'flag': return classes.indigo;
+ case 'whatshot': return classes.orange;
+ case 'settings': return classes.lime;
+ default: return classes.purple;
+ }
+ };
+ return (
+
+
+
+
+
+ Name
+ Task
+
+
+
+ {data.map(n => ([
+
+
+
+
+
+ {n.name}
+ {n.title}
+
+
+
+
+
+
+
+
+ ])
+ )}
+
+
+
+
+ );
+}
+
+TrackingTable.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TrackingTable);
diff --git a/front/odiparpack/app/containers/Tables/demos/TreeTableDemo.js b/front/odiparpack/app/containers/Tables/demos/TreeTableDemo.js
new file mode 100644
index 0000000..4c522e2
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/TreeTableDemo.js
@@ -0,0 +1,68 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import openAction from 'ba-actions/TreeTableActions';
+import { TreeTable } from 'ba-components';
+import { Paper } from '@material-ui/core';
+import data from './dataTreeTable.js';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+});
+
+const branch = 'treeTableArrow';
+
+class TreeTableDemo extends Component {
+ render() {
+ const {
+ arrowMore,
+ treeOpen,
+ classes,
+ toggleTree
+ } = this.props;
+ return (
+
+ );
+ }
+}
+
+TreeTableDemo.propTypes = {
+ classes: PropTypes.object.isRequired,
+ treeOpen: PropTypes.object.isRequired,
+ arrowMore: PropTypes.object.isRequired,
+ toggleTree: PropTypes.func.isRequired,
+};
+
+const mapStateToProps = state => ({
+ force: state, // force state from reducer
+ treeOpen: state.getIn([branch, 'treeOpen']),
+ arrowMore: state.getIn([branch, 'arrowMore']),
+});
+
+const mapDispatchToProps = dispatch => ({
+ toggleTree: bindActionCreators(openAction, dispatch)
+});
+
+const TreeTableDemoMapped = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(TreeTableDemo);
+
+export default withStyles(styles)(TreeTableDemoMapped);
diff --git a/front/odiparpack/app/containers/Tables/demos/TreeTableDemoIcon.js b/front/odiparpack/app/containers/Tables/demos/TreeTableDemoIcon.js
new file mode 100644
index 0000000..d669fae
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/TreeTableDemoIcon.js
@@ -0,0 +1,68 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import openAction from 'ba-actions/TreeTableActions';
+import { TreeTable } from 'ba-components';
+import { Paper } from '@material-ui/core';
+import data from './dataTreeTable.js';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ overflowX: 'auto',
+ },
+});
+
+const branch = 'treeTablePM';
+
+class TreeTableDemoIcon extends Component {
+ render() {
+ const {
+ arrowMore,
+ treeOpen,
+ classes,
+ toggleTree
+ } = this.props;
+ return (
+
+ );
+ }
+}
+
+TreeTableDemoIcon.propTypes = {
+ classes: PropTypes.object.isRequired,
+ treeOpen: PropTypes.object.isRequired,
+ arrowMore: PropTypes.object.isRequired,
+ toggleTree: PropTypes.func.isRequired,
+};
+
+const mapStateToProps = state => ({
+ force: state, // force state from reducer
+ treeOpen: state.getIn([branch, 'treeOpen']),
+ arrowMore: state.getIn([branch, 'arrowMore']),
+});
+
+const mapDispatchToProps = dispatch => ({
+ toggleTree: bindActionCreators(openAction, dispatch)
+});
+
+const TreeTableIconMapped = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(TreeTableDemoIcon);
+
+export default withStyles(styles)(TreeTableIconMapped);
diff --git a/front/odiparpack/app/containers/Tables/demos/dataTreeTable.js b/front/odiparpack/app/containers/Tables/demos/dataTreeTable.js
new file mode 100644
index 0000000..2eba8ab
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/dataTreeTable.js
@@ -0,0 +1,128 @@
+module.exports = {
+ head: [
+ {
+ label: 'KeyId',
+ },
+ {
+ label: 'Dessert (100g serving)',
+ },
+ {
+ label: 'Calories',
+ },
+ {
+ label: 'Fat(g)',
+ }
+ ],
+ body: [
+ {
+ id: '1',
+ name: 'Frozen yoghurt',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '1_1',
+ name: 'Frozen child 1',
+ calories: 159,
+ fat: 24,
+ },
+ {
+ id: '1_2',
+ name: 'Frozen child 2',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '1_2_1',
+ name: 'Frozen grand child 1',
+ calories: 159,
+ fat: 24,
+ },
+ ]
+ },
+ ]
+ },
+ {
+ id: '2',
+ name: 'Eclair',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '2_1',
+ name: 'Eclair Child',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '2_1_1',
+ name: 'Eclair Grand Child 1',
+ calories: 159,
+ fat: 24,
+ },
+ {
+ id: '2_1_2',
+ name: 'Eclair Grand Child 2',
+ calories: 159,
+ fat: 24,
+ }
+ ]
+ },
+ ]
+ },
+ {
+ id: '3',
+ name: 'Cupcake',
+ calories: 159,
+ fat: 24,
+ },
+ {
+ id: '4',
+ name: 'Ginger Bread',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '4_1',
+ name: 'Ginger Bread Child',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '4_1_1',
+ name: 'Ginger Bread Grand Child 1',
+ calories: 159,
+ fat: 24,
+ child: [
+ {
+ id: '4_1_1_1',
+ name: 'Ginger Bread Super Grand Child 1',
+ calories: 159,
+ fat: 24,
+ },
+ {
+ id: '4_1_1_2',
+ name: 'Ginger Bread Super Grand Child 2',
+ calories: 159,
+ fat: 24,
+ },
+ ]
+ },
+ {
+ id: '4_1_2',
+ name: 'Ginger Bread Grand Child 2',
+ calories: 159,
+ fat: 24,
+ },
+ {
+ id: '4_1_3',
+ name: 'Ginger Bread Grand Child 3',
+ calories: 159,
+ fat: 24,
+ }
+ ]
+ },
+ ]
+ }
+ ]
+};
diff --git a/front/odiparpack/app/containers/Tables/demos/index.js b/front/odiparpack/app/containers/Tables/demos/index.js
new file mode 100644
index 0000000..604e828
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/index.js
@@ -0,0 +1,14 @@
+export SimpleTable from './SimpleTable';
+export StrippedTable from './StrippedTable';
+export HoverTable from './HoverTable';
+export BorderedTable from './BorderedTable';
+export TreeTableDemo from './TreeTableDemo';
+export TreeTableDemoIcon from './TreeTableDemoIcon';
+export CrudTableDemo from './CrudTableDemo';
+export CrudTbFormDemo from './CrudTbFormDemo';
+export AdvTableDemo from './AdvTableDemo';
+export AdvFilter from './AdvFilter';
+export StatusLabel from './StatusLabel';
+export StatusColorRow from './StatusColorRow';
+export EmptyTable from './EmptyTable';
+export TrackingTable from './TrackingTable';
diff --git a/front/odiparpack/app/containers/Tables/demos/sampleData.js b/front/odiparpack/app/containers/Tables/demos/sampleData.js
new file mode 100644
index 0000000..d53d8e2
--- /dev/null
+++ b/front/odiparpack/app/containers/Tables/demos/sampleData.js
@@ -0,0 +1,124 @@
+export const anchorTable = [
+ {
+ name: 'id',
+ label: 'Id',
+ initialValue: '',
+ hidden: true
+ }, {
+ name: 'text',
+ label: 'Text Field',
+ initialValue: null,
+ width: 'auto',
+ hidden: false
+ }, {
+ name: 'email',
+ label: 'Email Field',
+ initialValue: null,
+ width: 'auto',
+ hidden: false
+ }, {
+ name: 'radio',
+ label: 'Radio Option',
+ initialValue: 'option1',
+ width: '80',
+ hidden: false
+ }, {
+ name: 'selection',
+ label: 'Selection',
+ initialValue: 'option1',
+ width: '80',
+ hidden: false
+ }, {
+ name: 'onof',
+ label: 'On/Of Input',
+ initialValue: true,
+ width: '80',
+ hidden: false
+ }, {
+ name: 'checkbox',
+ label: 'Checkbox',
+ initialValue: true,
+ width: '80',
+ hidden: false
+ }, {
+ name: 'textarea',
+ label: 'Text Area',
+ initialValue: 'This is default text',
+ width: 'auto',
+ hidden: false
+ }, {
+ name: 'edited',
+ label: '',
+ initialValue: '',
+ hidden: true
+ }, {
+ name: 'action',
+ label: 'Action',
+ initialValue: '',
+ hidden: false
+ },
+];
+
+export const dataApi = [
+ {
+ id: '1',
+ text: 'Just write',
+ email: 'mail@boss.com',
+ radio: 'option2',
+ selection: 'option1',
+ onof: false,
+ checkbox: true,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ }, {
+ id: '2',
+ text: 'Some text',
+ email: 'mail@material.com',
+ radio: 'option2',
+ selection: 'option2',
+ onof: false,
+ checkbox: false,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ }, {
+ id: '3',
+ text: 'Because it is a TextField',
+ email: 'mail@admin.com',
+ radio: 'option1',
+ selection: 'option3',
+ onof: false,
+ checkbox: false,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ }, {
+ id: '4',
+ text: 'And editable',
+ email: 'mail@example.com',
+ radio: 'option1',
+ selection: 'option1',
+ onof: false,
+ checkbox: true,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ }, {
+ id: '5',
+ text: 'You can write',
+ email: 'mail@material.com',
+ radio: 'option2',
+ selection: 'option2',
+ onof: false,
+ checkbox: true,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ }, {
+ id: '6',
+ text: 'Everything You want here',
+ email: 'mail@everything.com',
+ radio: 'option1',
+ selection: 'option3',
+ onof: false,
+ checkbox: false,
+ textarea: 'Lorem ipsum dolor sit amet',
+ edited: false,
+ },
+];
diff --git a/front/odiparpack/app/containers/Templates/Dashboard.js b/front/odiparpack/app/containers/Templates/Dashboard.js
new file mode 100644
index 0000000..5f24777
--- /dev/null
+++ b/front/odiparpack/app/containers/Templates/Dashboard.js
@@ -0,0 +1,114 @@
+import React, { useState, useEffect } from 'react';
+import { PropTypes } from 'prop-types';
+import classNames from 'classnames';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import { withStyles } from '@material-ui/core/styles';
+import { Header, Sidebar, BreadCrumb } from 'ba-components';
+import { toggleAction, openAction, playTransitionAction } from 'ba-actions/UiActions';
+import { Fade } from '@material-ui/core';
+import styles from './appStyles-jss';
+
+function Dashboard(props) {
+ const {
+ classes,
+ children,
+ history,
+ toggleDrawer,
+ sidebarOpen,
+ initialOpen,
+ loadTransition,
+ pageLoaded
+ } = props;
+ const [transform, setTransform] = useState(0);
+
+ const darker = true;
+
+ const handleScroll = () => {
+ const doc = document.documentElement;
+ const scroll = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
+ setTransform(scroll);
+ };
+
+ useEffect(() => {
+ // Scroll content to top
+ window.addEventListener('scroll', handleScroll);
+
+ // Set expanded sidebar menu
+ const currentPath = history.location.pathname;
+ initialOpen(currentPath);
+
+ // Play page transition
+ loadTransition(true);
+
+ // Execute all arguments when page changes
+ const unlisten = history.listen(() => {
+ window.scrollTo(0, 0);
+ setTimeout(() => {
+ loadTransition(true);
+ }, 500);
+ });
+
+ return () => {
+ unlisten();
+ };
+ }, []);
+
+ return (
+
+
30 && darker} margin={sidebarOpen} />
+ 30 && darker}
+ />
+
+
+
+
+
+ );
+}
+
+Dashboard.propTypes = {
+ classes: PropTypes.object.isRequired,
+ history: PropTypes.object.isRequired,
+ children: PropTypes.node.isRequired,
+ initialOpen: PropTypes.func.isRequired,
+ toggleDrawer: PropTypes.func.isRequired,
+ loadTransition: PropTypes.func.isRequired,
+ sidebarOpen: PropTypes.bool.isRequired,
+ pageLoaded: PropTypes.bool.isRequired
+};
+
+const reducer = 'ui';
+const mapStateToProps = state => ({
+ sidebarOpen: state.getIn([reducer, 'sidebarOpen']),
+ pageLoaded: state.getIn([reducer, 'pageLoaded'])
+});
+
+const mapDispatchToProps = dispatch => ({
+ toggleDrawer: () => dispatch(toggleAction),
+ initialOpen: bindActionCreators(openAction, dispatch),
+ loadTransition: bindActionCreators(playTransitionAction, dispatch),
+});
+
+const DashboardMaped = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(Dashboard);
+
+export default (withStyles(styles)(DashboardMaped));
diff --git a/front/odiparpack/app/containers/Templates/Outer.js b/front/odiparpack/app/containers/Templates/Outer.js
new file mode 100644
index 0000000..f6448be
--- /dev/null
+++ b/front/odiparpack/app/containers/Templates/Outer.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { PropTypes } from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import brand from 'ba-api/brand';
+import logo from 'ba-images/logo.svg';
+import { Hidden } from '@material-ui/core';
+import styles from './appStyles-jss';
+
+function Outer(props) {
+ const {
+ classes,
+ children,
+ } = props;
+ return (
+
+
+
+
+

+
{brand.name}
+
+
+ {children}
+
+
+ );
+}
+
+Outer.propTypes = {
+ classes: PropTypes.object.isRequired,
+ children: PropTypes.node.isRequired,
+};
+
+export default (withStyles(styles)(Outer));
diff --git a/front/odiparpack/app/containers/Templates/appStyles-jss.js b/front/odiparpack/app/containers/Templates/appStyles-jss.js
new file mode 100644
index 0000000..f9175eb
--- /dev/null
+++ b/front/odiparpack/app/containers/Templates/appStyles-jss.js
@@ -0,0 +1,144 @@
+import bg from 'ba-images/material_bg.svg';
+import { fade } from '@material-ui/core/styles/colorManipulator';
+
+const appFrame = {
+ display: 'flex',
+ width: '100%',
+ minHeight: '100%',
+ zIndex: 1,
+};
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ minHeight: '100%',
+ marginTop: 0,
+ zIndex: 1,
+ },
+ appFrameInner: {
+ ...appFrame,
+ flexDirection: 'row'
+ },
+ appFrameOuter: {
+ ...appFrame,
+ },
+ content: {
+ backgroundColor: theme.palette.background.default,
+ width: '100%',
+ padding: theme.spacing(1.5),
+ paddingLeft: 0,
+ minHeight: '100%',
+ overflow: 'hidden',
+ },
+ outerContent: {
+ background: `url(${bg}) no-repeat ${theme.palette.primary.main} left bottom`,
+ width: '100%',
+ backgroundSize: 'cover',
+ flexDirection: 'column',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ [theme.breakpoints.down('md')]: {
+ padding: '20px 0'
+ },
+ },
+ bgbar: {
+ backgroundColor: theme.palette.primary.main,
+ width: '100%',
+ position: 'fixed',
+ height: 184,
+ top: 0,
+ left: 0
+ },
+ mainWrap: {
+ position: 'relative',
+ marginTop: theme.spacing(6),
+ marginLeft: theme.spacing(1.5),
+ height: '100%',
+ '& > div': {
+ paddingBottom: theme.spacing(4),
+ willChange: 'inherit !important' // hack for floating form issue whne expaded
+ }
+ },
+ preloader: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ zIndex: 1000,
+ background: 'transparent',
+ height: 3,
+ },
+ materialBg: {
+ position: 'absolute',
+ left: 0,
+ bottom: 0,
+ width: '100%',
+ opacity: 0.5
+ },
+ contentPadding: {
+ paddingLeft: 80
+ },
+ hideApp: {
+ display: 'none'
+ },
+ circularProgress: {
+ position: 'absolute',
+ top: 'calc(50% - 100px)',
+ left: 'calc(50% - 100px)',
+ },
+ brand: {
+ height: 54,
+ display: 'flex',
+ padding: '10px 10px 5px',
+ position: 'relative',
+ alignItems: 'center',
+ justifyContent: 'center',
+ '& img': {
+ width: 20
+ },
+ '& h3': {
+ margin: 0,
+ fontSize: 16,
+ fontWeight: 500,
+ paddingLeft: 10,
+ color: theme.palette.common.white,
+ }
+ },
+ btn: {},
+ icon: {},
+ btnPicker: {
+ position: 'fixed',
+ zIndex: 2000,
+ right: 0,
+ top: 200,
+ background: fade(theme.palette.background.paper, 0.8),
+ borderRadius: '30px 0 0 30px',
+ padding: '4px 8px 4px 4px',
+ overflow: 'hidden',
+ border: `1px solid ${theme.palette.grey[300]}`,
+ '& $btn': {
+ background: theme.palette.secondary.main,
+ borderRadius: 30,
+ padding: 8,
+ boxShadow: theme.shadows[4],
+ display: 'flex',
+ alignItems: 'center',
+ width: 40,
+ height: 40,
+ textCenter: 'cener',
+ overflow: 'hidden',
+ color: 'transparent',
+ transition: 'all 0.3s ease',
+ '& $icon': {
+ color: theme.palette.background.paper,
+ },
+ '&:hover': {
+ color: theme.palette.background.paper,
+ width: 90
+ }
+ }
+ }
+});
+
+export default styles;
diff --git a/front/odiparpack/app/containers/UiElements/Accordion.js b/front/odiparpack/app/containers/UiElements/Accordion.js
new file mode 100644
index 0000000..dd354d3
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Accordion.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { SimpleAccordion, AdvancedAccordion, ControlledAccordion } from './demos';
+
+class Accordion extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Accordion/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Accordion;
diff --git a/front/odiparpack/app/containers/UiElements/Avatars.js b/front/odiparpack/app/containers/UiElements/Avatars.js
new file mode 100644
index 0000000..3ccbaaa
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Avatars.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { AvatarsDemo, AvatarsPractice } from './demos';
+
+class Avatars extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Avatars/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Avatars;
diff --git a/front/odiparpack/app/containers/UiElements/Badges.js b/front/odiparpack/app/containers/UiElements/Badges.js
new file mode 100644
index 0000000..ff4783d
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Badges.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { CommonBadges, VariantBadges } from './demos';
+
+class Badges extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Badges/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Badges;
diff --git a/front/odiparpack/app/containers/UiElements/Breadcrumbs.js b/front/odiparpack/app/containers/UiElements/Breadcrumbs.js
new file mode 100644
index 0000000..daaa24f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Breadcrumbs.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { ClassicBreadcrumbs, PaperBreadcrumbs } from './demos';
+
+class BreadCrumbs extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Breadcrumbs/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default BreadCrumbs;
diff --git a/front/odiparpack/app/containers/UiElements/Cards.js b/front/odiparpack/app/containers/UiElements/Cards.js
new file mode 100644
index 0000000..7865b9d
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Cards.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import {
+ StandardCards,
+ ControlCards,
+ PaperSheet,
+ SocialCards,
+ EcommerceCards
+} from './demos';
+
+class Cards extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Cards/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Cards;
diff --git a/front/odiparpack/app/containers/UiElements/DialogModal.js b/front/odiparpack/app/containers/UiElements/DialogModal.js
new file mode 100644
index 0000000..6e26609
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/DialogModal.js
@@ -0,0 +1,97 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ ModalDemo,
+ AlertDialog,
+ SelectDialog,
+ SelectRadioDialog,
+ FormDialog,
+ FullScreenDialog,
+ ImagePopup,
+ ScrollDialog
+} from './demos';
+
+class DialogModal extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/DialogModal/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default DialogModal;
diff --git a/front/odiparpack/app/containers/UiElements/Dividers.js b/front/odiparpack/app/containers/UiElements/Dividers.js
new file mode 100644
index 0000000..34c66a9
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Dividers.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { CommonDividers, SpecialDividers } from './demos';
+
+class Dividers extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Dividers/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Dividers;
diff --git a/front/odiparpack/app/containers/UiElements/DrawerMenu.js b/front/odiparpack/app/containers/UiElements/DrawerMenu.js
new file mode 100644
index 0000000..dfffbc8
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/DrawerMenu.js
@@ -0,0 +1,104 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ TemporaryDrawer,
+ SwipeDrawer,
+ PermanentDrawer,
+ PersistentDrawer,
+ MiniDrawer,
+ BasicMenu,
+ DropdownMenu,
+ StyledMenu,
+ MenuTransition
+} from './demos';
+
+class DrawerMenu extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/DrawerMenu/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default DrawerMenu;
diff --git a/front/odiparpack/app/containers/UiElements/IconGallery/DetailIcon.js b/front/odiparpack/app/containers/UiElements/IconGallery/DetailIcon.js
new file mode 100644
index 0000000..e19c17a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/IconGallery/DetailIcon.js
@@ -0,0 +1,149 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/prism-light';
+import jsx from 'react-syntax-highlighter/languages/prism/jsx';
+import themeSource from 'react-syntax-highlighter/styles/prism/prism';
+import { withStyles } from '@material-ui/core/styles';
+
+import {
+ Typography,
+ Button,
+ Icon,
+ Divider,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Slide,
+} from '@material-ui/core';
+
+const Transition = React.forwardRef(function Transition(props, ref) { // eslint-disable-line
+ return ;
+});
+
+const humanize = (str, space) => {
+ let string = str;
+ if (str === '3d_rotation') {
+ string = 'three_d_rotation';
+ }
+ const frags = string.split('_');
+ for (let i = 0; i < frags.length; i += 1) {
+ frags[i] = frags[i].charAt(0).toUpperCase() + frags[i].slice(1);
+ }
+
+ if (space) {
+ return frags.join(' ');
+ }
+ return frags.join('');
+};
+
+const styles = theme => ({
+ code: {
+ fontSize: 12,
+ padding: '5px !important'
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ bigIcon: {
+ textAlign: 'center',
+ marginBottom: 30,
+ '& span': {
+ fontSize: 128
+ }
+ },
+ title: {
+ marginBottom: 40,
+ fontSize: 22,
+ paddingBottom: 20,
+ position: 'relative',
+ fontWeight: 500,
+ color: theme.palette.grey[700],
+ textTransform: 'uppercase',
+ '&:after': {
+ content: '""',
+ display: 'block',
+ position: 'absolute',
+ bottom: 0,
+ left: 24,
+ width: 40,
+ borderBottom: `5px solid ${theme.palette.primary.main}`
+ }
+ },
+});
+
+class DetailIcon extends React.Component {
+ render() {
+ registerLanguage('jsx', jsx);
+ const {
+ isOpenDetail,
+ iconName,
+ iconCode,
+ closeDetail
+ } = this.props;
+ const { classes } = this.props;
+ const linkCode = '';
+ const fontCode = '' + iconName + '';
+ const importCode = 'import ' + humanize(iconName, false) + " from '@material-ui/icons/" + humanize(iconName, false) + "';";
+ const importIconCode = "import Icon from '@material-ui/core/Icon';";
+ const svgCode = '<' + humanize(iconName, false) + ' />';
+ return (
+
+ );
+ }
+}
+
+DetailIcon.propTypes = {
+ classes: PropTypes.object.isRequired,
+ isOpenDetail: PropTypes.bool.isRequired,
+ closeDetail: PropTypes.func.isRequired,
+ iconName: PropTypes.string.isRequired,
+ iconCode: PropTypes.string.isRequired,
+};
+
+export default withStyles(styles)(DetailIcon);
diff --git a/front/odiparpack/app/containers/UiElements/IconGallery/SearchIcons.js b/front/odiparpack/app/containers/UiElements/IconGallery/SearchIcons.js
new file mode 100644
index 0000000..c046362
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/IconGallery/SearchIcons.js
@@ -0,0 +1,54 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import SearchIcon from '@material-ui/icons/Search';
+
+import { IconButton, Input, InputAdornment, FormControl } from '@material-ui/core';
+
+const styles = theme => ({
+ search: {
+ display: 'block',
+ background: '#fff',
+ marginBottom: 10,
+ paddingTop: 5,
+ boxShadow: theme.shadows[2],
+ '& > div': {
+ width: '100%',
+ },
+ '& input': {
+ padding: '10px 8px'
+ }
+ }
+});
+
+class SearchIcons extends React.Component {
+ render() {
+ const { filterText, classes, handleSearch } = this.props;
+ return (
+
+
+
+
+
+
+ )}
+ />
+
+ );
+ }
+}
+
+SearchIcons.propTypes = {
+ classes: PropTypes.object.isRequired,
+ filterText: PropTypes.string.isRequired,
+ handleSearch: PropTypes.func.isRequired,
+};
+
+export default withStyles(styles)(SearchIcons);
diff --git a/front/odiparpack/app/containers/UiElements/Icons.js b/front/odiparpack/app/containers/UiElements/Icons.js
new file mode 100644
index 0000000..f207d29
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Icons.js
@@ -0,0 +1,158 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import PropTypes from 'prop-types';
+import Axios from 'axios';
+import { withStyles } from '@material-ui/core/styles';
+import { PapperBlock } from 'ba-components';
+import { Typography, IconButton, Icon, LinearProgress } from '@material-ui/core';
+import DetailIcon from './IconGallery/DetailIcon';
+import SearchIcons from './IconGallery/SearchIcons';
+const url = '/api/icons?src=';
+
+const styles = theme => ({
+ hide: {
+ display: 'none'
+ },
+ iconsList: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ justifyContent: 'space-between',
+ [theme.breakpoints.down('xs')]: {
+ justifyContent: 'center',
+ },
+ overflow: 'auto',
+ maxHeight: 1000,
+ position: 'relative'
+ },
+ iconWrap: {
+ position: 'relative',
+ width: 120,
+ margin: 20,
+ [theme.breakpoints.down('xs')]: {
+ margin: 10,
+ },
+ textAlign: 'center'
+ },
+ btn: {
+ display: 'block',
+ textAlign: 'center',
+ margin: '0 auto',
+ },
+ icon: {
+ fontSize: 48,
+ },
+ preloader: {
+ width: '100%'
+ },
+});
+
+class Icons extends React.Component {
+ state = {
+ raws: [],
+ loading: false,
+ openDetail: false,
+ iconName: '',
+ iconCode: '',
+ filterText: ''
+ };
+
+ componentDidMount = () => {
+ const name = 'material-icon-cheat.txt';
+ this.setState({ loading: true }, () => {
+ Axios.get(url + name)
+ .then(response => response.data.records[0].source)
+ .then(data => {
+ const namesAndCodes = data.split('\n');
+ const icons = namesAndCodes.map(nameAndCode => {
+ const parts = nameAndCode.split(' ');
+ return {
+ name: parts[0],
+ code: parts[1]
+ };
+ });
+ return icons;
+ })
+ .then(icons => {
+ this.setState({
+ raws: icons,
+ loading: false
+ });
+ });
+ });
+ }
+
+ handleOpenDetail = (name, code) => {
+ this.setState({
+ openDetail: true,
+ iconName: name,
+ iconCode: code,
+ });
+ };
+
+ handleCloseDetail = () => {
+ this.setState({ openDetail: false });
+ };
+
+ handleSearch = (event) => {
+ event.persist();
+ // Show result base on keyword
+ this.setState({ filterText: event.target.value.toLowerCase() });
+ }
+
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const {
+ raws,
+ loading,
+ openDetail,
+ iconName,
+ iconCode,
+ filterText
+ } = this.state;
+ const { classes } = this.props;
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+ {loading
+ &&
+ }
+
this.handleSearch(event)} />
+
+ {raws.map((raw, index) => {
+ if (raw.name.toLowerCase().indexOf(filterText) === -1) {
+ return false;
+ }
+ return (
+
+ this.handleOpenDetail(raw.name, raw.code)} className={classes.btn}>
+ {raw.name}
+
+ {raw.name}
+
+ );
+ })}
+
+
+
+
+
+ );
+ }
+}
+
+Icons.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(Icons);
diff --git a/front/odiparpack/app/containers/UiElements/ImageGrid.js b/front/odiparpack/app/containers/UiElements/ImageGrid.js
new file mode 100644
index 0000000..a95fd50
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/ImageGrid.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { ImageGridList, TitlebarGridList, AdvancedGridList, SingleLineGridList } from './demos';
+
+class ImageGrid extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/ImageGrid/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ImageGrid;
diff --git a/front/odiparpack/app/containers/UiElements/List.js b/front/odiparpack/app/containers/UiElements/List.js
new file mode 100644
index 0000000..665cd08
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/List.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import {
+ ListBasic,
+ ListMenu,
+ PinnedList,
+ ListControl,
+ ListInteractive
+} from './demos';
+
+class List extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/List/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default List;
diff --git a/front/odiparpack/app/containers/UiElements/Notification.js b/front/odiparpack/app/containers/UiElements/Notification.js
new file mode 100644
index 0000000..b00f24e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Notification.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import { SimpleNotif, StyledNotif, TransitionNotif, MobileNotif } from './demos';
+
+class Notification extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Notification/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Notification;
diff --git a/front/odiparpack/app/containers/UiElements/Paginations.js b/front/odiparpack/app/containers/UiElements/Paginations.js
new file mode 100644
index 0000000..7f6fa47
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Paginations.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { TbPagination, TbPaginationCustom, GeneralPagination } from './demos';
+
+class Paginations extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Pagination/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Paginations;
diff --git a/front/odiparpack/app/containers/UiElements/PopoverTooltip.js b/front/odiparpack/app/containers/UiElements/PopoverTooltip.js
new file mode 100644
index 0000000..508129b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/PopoverTooltip.js
@@ -0,0 +1,95 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ SimpleTooltips,
+ PositionedTooltips,
+ SimplePopover,
+ PopoverPlayground,
+ DelayTooltips,
+ TransitionsTooltips,
+ TriggersTooltips,
+ CustomizedTooltips
+} from './demos';
+
+class PopoverTooltip extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/PopoverTooltip/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default PopoverTooltip;
diff --git a/front/odiparpack/app/containers/UiElements/Progress.js b/front/odiparpack/app/containers/UiElements/Progress.js
new file mode 100644
index 0000000..669da02
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Progress.js
@@ -0,0 +1,126 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ CircularStatic,
+ CircularIndeterminate,
+ CircularDeterminate,
+ CircularIntegration,
+ LinearStatic,
+ LinearIndeterminate,
+ LinearDeterminate,
+ LinearBuffer,
+ LinearQuery,
+ ProgressDelay
+} from './demos';
+
+const styles = ({
+ root: {
+ flexGrow: 1,
+ }
+});
+
+class Progress extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Progress/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Progress.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(Progress);
diff --git a/front/odiparpack/app/containers/UiElements/SliderCarousel.js b/front/odiparpack/app/containers/UiElements/SliderCarousel.js
new file mode 100644
index 0000000..b624774
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/SliderCarousel.js
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import {
+ SingleCarousel,
+ MultipleCarousel,
+ AutoplayCarousel,
+ ThumbnailCarousel,
+ VerticalCarousel,
+ CustomCarousel,
+ AnimatedSlider
+} from './demos';
+
+class SliderCarousel extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/SliderCaraousel/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default SliderCarousel;
diff --git a/front/odiparpack/app/containers/UiElements/Steppers.js b/front/odiparpack/app/containers/UiElements/Steppers.js
new file mode 100644
index 0000000..358f641
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Steppers.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import {
+ HorizontalLinear,
+ HorizontalNonLinear,
+ StepperError,
+ VerticalStepper,
+ MobileSteppers,
+ StepperCarousel
+} from './demos';
+
+class Steppers extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Steppers/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Steppers;
diff --git a/front/odiparpack/app/containers/UiElements/Tabs.js b/front/odiparpack/app/containers/UiElements/Tabs.js
new file mode 100644
index 0000000..0782462
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Tabs.js
@@ -0,0 +1,120 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { withStyles } from '@material-ui/core/styles';
+import PropTypes from 'prop-types';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ SimpleTabs,
+ LongTextTabs,
+ FixedTabs,
+ CenteredTabs,
+ IconTabs,
+ ScrollTabs,
+ ScrollIconTabs,
+ DisabledTab,
+ CustomTabs,
+ BottomNav
+} from './demos';
+
+const styles = ({
+ root: {
+ flexGrow: 1,
+ }
+});
+
+class Tabs extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const { classes } = this.props;
+ const docSrc = 'containers/UiElements/demos/Tabs/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Tabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(Tabs);
diff --git a/front/odiparpack/app/containers/UiElements/Tags.js b/front/odiparpack/app/containers/UiElements/Tags.js
new file mode 100644
index 0000000..e8a5571
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Tags.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { BasicTags, ArrayTags } from './demos';
+
+class Tags extends React.Component {
+ render() {
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Tags/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Tags;
diff --git a/front/odiparpack/app/containers/UiElements/Typography.js b/front/odiparpack/app/containers/UiElements/Typography.js
new file mode 100644
index 0000000..e1a88ba
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/Typography.js
@@ -0,0 +1,92 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import brand from 'ba-api/brand';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { SourceReader, PapperBlock } from 'ba-components';
+import { Grid } from '@material-ui/core';
+import {
+ GeneralTypo,
+ Heading,
+ ListTypo,
+ AlignTypo,
+ ColouredTypo,
+ QuotesDemo
+} from './demos';
+
+const styles = ({
+ root: {
+ flexGrow: 1,
+ }
+});
+
+class Typography extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const title = brand.name + ' - UI Elements';
+ const description = brand.desc;
+ const docSrc = 'containers/UiElements/demos/Typography/';
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Typography.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(Typography);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Accordion/AdvancedAccordion.js b/front/odiparpack/app/containers/UiElements/demos/Accordion/AdvancedAccordion.js
new file mode 100644
index 0000000..87cd84e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Accordion/AdvancedAccordion.js
@@ -0,0 +1,97 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+
+import {
+ ExpansionPanel,
+ ExpansionPanelDetails,
+ ExpansionPanelSummary,
+ ExpansionPanelActions,
+ Typography,
+ Chip,
+ Button,
+ Divider,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ heading: {
+ fontSize: theme.typography.pxToRem(15),
+ },
+ secondaryHeading: {
+ fontSize: theme.typography.pxToRem(15),
+ color: theme.palette.text.secondary,
+ },
+ icon: {
+ verticalAlign: 'bottom',
+ height: 20,
+ width: 20,
+ },
+ details: {
+ alignItems: 'center',
+ },
+ column: {
+ flexBasis: '33.33%',
+ },
+ helper: {
+ borderLeft: `2px solid ${theme.palette.divider}`,
+ padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`,
+ },
+ link: {
+ color: theme.palette.secondary.main,
+ textDecoration: 'none',
+ '&:hover': {
+ textDecoration: 'underline',
+ },
+ },
+});
+
+function AdvancedAccordion(props) {
+ const { classes } = props;
+ return (
+
+
+ }>
+
+ Location
+
+
+ Select trip destination
+
+
+
+
+
+ {}} />
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+AdvancedAccordion.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AdvancedAccordion);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Accordion/ControlledAccordion.js b/front/odiparpack/app/containers/UiElements/demos/Accordion/ControlledAccordion.js
new file mode 100644
index 0000000..6bcc2c8
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Accordion/ControlledAccordion.js
@@ -0,0 +1,100 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+
+import { ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ heading: {
+ fontSize: theme.typography.pxToRem(15),
+ flexBasis: '33.33%',
+ flexShrink: 0,
+ },
+ secondaryHeading: {
+ fontSize: theme.typography.pxToRem(15),
+ color: theme.palette.text.secondary,
+ },
+});
+
+class ControlledAccordion extends React.Component {
+ state = {
+ expanded: null,
+ };
+
+ handleChange = panel => (event, expanded) => {
+ this.setState({
+ expanded: expanded ? panel : false,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { expanded } = this.state;
+
+ return (
+
+
+ }>
+ General settings
+ I am an expansion panel
+
+
+
+ Nulla facilisi. Phasellus sollicitudin nulla et quam mattis feugiat. Aliquam eget
+ maximus est, id dignissim quam.
+
+
+
+
+ }>
+ Users
+
+ You are currently not an owner
+
+
+
+
+ Donec placerat, lectus sed mattis semper, neque lectus feugiat lectus, varius pulvinar
+ diam eros in elit. Pellentesque convallis laoreet laoreet.
+
+
+
+
+ }>
+ Advanced settings
+
+ Filtering has been entirely disabled for whole web server
+
+
+
+
+ Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas
+ eros, vitae egestas augue. Duis vel est augue.
+
+
+
+
+ }>
+ Personal data
+
+
+
+ Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas
+ eros, vitae egestas augue. Duis vel est augue.
+
+
+
+
+ );
+ }
+}
+
+ControlledAccordion.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ControlledAccordion);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Accordion/SimpleAccordion.js b/front/odiparpack/app/containers/UiElements/demos/Accordion/SimpleAccordion.js
new file mode 100644
index 0000000..a88f772
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Accordion/SimpleAccordion.js
@@ -0,0 +1,57 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+
+import { ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ heading: {
+ fontSize: theme.typography.pxToRem(15),
+ fontWeight: theme.typography.fontWeightRegular,
+ },
+});
+
+function SimpleAccordion(props) {
+ const { classes } = props;
+ return (
+
+
+ }>
+ Expansion Panel 1
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex,
+ sit amet blandit leo lobortis eget.
+
+
+
+
+ }>
+ Expansion Panel 2
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex,
+ sit amet blandit leo lobortis eget.
+
+
+
+
+ }>
+ Disabled Expansion Panel
+
+
+
+ );
+}
+
+SimpleAccordion.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimpleAccordion);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsDemo.js b/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsDemo.js
new file mode 100644
index 0000000..e21391e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsDemo.js
@@ -0,0 +1,112 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import FolderIcon from '@material-ui/icons/Folder';
+import PageviewIcon from '@material-ui/icons/Pageview';
+import AssignmentIcon from '@material-ui/icons/Assignment';
+import avatarApi from 'ba-api/avatars';
+
+import { pink, green, deepOrange, deepPurple } from '@material-ui/core/colors';
+
+import { Typography, Avatar, Grid } from '@material-ui/core';
+
+const styles = ({
+ row: {
+ display: 'flex',
+ justifyContent: 'flex-start',
+ },
+ avatar: {
+ margin: 10,
+ },
+ bigAvatar: {
+ width: 60,
+ height: 60,
+ },
+ pinkAvatar: {
+ margin: 10,
+ color: '#fff',
+ backgroundColor: pink[500],
+ },
+ greenAvatar: {
+ margin: 10,
+ color: '#fff',
+ backgroundColor: green[500],
+ },
+ orangeAvatar: {
+ margin: 10,
+ color: '#fff',
+ backgroundColor: deepOrange[500],
+ },
+ purpleAvatar: {
+ margin: 10,
+ color: '#fff',
+ backgroundColor: deepPurple[500],
+ },
+});
+
+class AvatarsDemo extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Image Avatars
+
+
+
+ Icon Avatars
+
+
+
+ Icon Avatars
+
+
+
+
+ );
+ }
+}
+
+AvatarsDemo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AvatarsDemo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsPractice.js b/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsPractice.js
new file mode 100644
index 0000000..a95b702
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Avatars/AvatarsPractice.js
@@ -0,0 +1,212 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import ImageIcon from '@material-ui/icons/Image';
+import FavoriteIcon from '@material-ui/icons/Favorite';
+import WorkIcon from '@material-ui/icons/Work';
+import BeachAccessIcon from '@material-ui/icons/BeachAccess';
+import ShareIcon from '@material-ui/icons/Share';
+import MoreVertIcon from '@material-ui/icons/MoreVert';
+import FaceIcon from '@material-ui/icons/Face';
+import imgApi from 'ba-api/images';
+
+import { red, green, amber } from '@material-ui/core/colors';
+
+import {
+ Typography,
+ Card,
+ CardHeader,
+ CardMedia,
+ CardContent,
+ CardActions,
+ IconButton,
+ Avatar,
+ List,
+ ListItem,
+ ListItemText,
+ ListItemAvatar,
+ Grid,
+ Chip,
+ Divider,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ row: {
+ display: 'flex',
+ justifyContent: 'flex-start',
+ },
+ chip: {
+ margin: theme.spacing(1),
+ },
+ card: {
+ maxWidth: 400,
+ },
+ media: {
+ height: 0,
+ paddingTop: '56.25%', // 16:9
+ },
+ actions: {
+ display: 'flex',
+ },
+ expand: {
+ transform: 'rotate(0deg)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.shortest,
+ }),
+ marginLeft: 'auto',
+ },
+ expandOpen: {
+ transform: 'rotate(180deg)',
+ },
+ root: {
+ width: '100%',
+ maxWidth: 360,
+ backgroundColor: theme.palette.background.paper,
+ },
+ avatarRed: {
+ backgroundColor: red[500],
+ },
+ avatarGreen: {
+ backgroundColor: green[500],
+ },
+ avatarAmber: {
+ backgroundColor: amber[500],
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+function handleDelete() {
+ alert('You clicked the delete icon.'); // eslint-disable-line no-alert
+}
+
+function handleClick() {
+ alert('You clicked the Chip.'); // eslint-disable-line no-alert
+}
+
+class AvatarsDemo extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Avatars in Tag(Chip)
+
+ MB}
+ label="Clickable Chip"
+ onClick={handleClick}
+ className={classes.chip}
+ />
+ }
+ label="Deletable Chip"
+ onDelete={handleDelete}
+ className={classes.chip}
+ />
+
+
+
+ )}
+ label="Clickable Deletable Chip"
+ onClick={handleClick}
+ onDelete={handleDelete}
+ className={classes.chip}
+ />
+
+
+ Avatars in List Menu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Avatars in Social Media
+
+
+
+ }
+ action={(
+
+
+
+ )}
+ title="Aliquam nec ex aliquet"
+ subheader="September 14, 2018"
+ />
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sed urna in justo euismod condimentum.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+AvatarsDemo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AvatarsDemo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Badges/CommonBadges.js b/front/odiparpack/app/containers/UiElements/demos/Badges/CommonBadges.js
new file mode 100644
index 0000000..b9dca43
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Badges/CommonBadges.js
@@ -0,0 +1,121 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles, MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
+import { pink, teal } from '@material-ui/core/colors';
+
+import { Badge, Typography, Grid, Button } from '@material-ui/core';
+
+const styles = theme => ({
+ demo: {
+ height: 'auto',
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ alone: {
+ position: 'relative',
+ margin: 20
+ },
+ field: {
+ margin: '10px',
+ position: 'relative'
+ },
+ cssRoot: {
+ '& span': {
+ backgroundColor: pink[700],
+ color: theme.palette.getContrastText(pink[500]),
+ },
+ },
+});
+
+const theme = createMuiTheme({
+ palette: {
+ primary: teal,
+ secondary: pink
+ },
+});
+
+class CommonBadges extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Button Badges
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Text Badges
+
+
+
+ Badge Text
+
+
+
+
+ Badges Bold Text
+
+
+
+
+
+
+ );
+ }
+}
+
+CommonBadges.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CommonBadges);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Badges/VariantBadges.js b/front/odiparpack/app/containers/UiElements/demos/Badges/VariantBadges.js
new file mode 100644
index 0000000..8dcc485
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Badges/VariantBadges.js
@@ -0,0 +1,117 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import MailIcon from '@material-ui/icons/Mail';
+import { LimitedBadges } from 'ba-components';
+
+import { Badge, Typography, Grid, IconButton, AppBar, Tabs, Tab } from '@material-ui/core';
+
+const styles = theme => ({
+ demo: {
+ height: 'auto',
+ },
+ divider: {
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ alone: {
+ position: 'relative',
+ margin: 20
+ },
+ field: {
+ margin: '10px',
+ position: 'relative'
+ },
+ margin: {
+ margin: theme.spacing(2),
+ },
+ padding: {
+ padding: `0 ${theme.spacing(2)}px`,
+ },
+ autoscale: {
+ '& span': {
+ width: 'auto',
+ padding: 2
+ }
+ }
+});
+
+class CommonBadges extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Icon Badges
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tab Badges
+
+
+
+ Item One
+
+ )}
+ />
+
+
+
+
+
+
+
+ );
+ }
+}
+
+CommonBadges.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CommonBadges);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/ClassicBreadcrumbs.js b/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/ClassicBreadcrumbs.js
new file mode 100644
index 0000000..786a07b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/ClassicBreadcrumbs.js
@@ -0,0 +1,83 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { BreadCrumb } from 'ba-components';
+
+import { Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ demo: {
+ height: 'auto',
+ },
+ divider: {
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ field: {
+ margin: '10px',
+ position: 'relative'
+ },
+});
+
+class ClassicBreadcrumbs extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ const location = { pathname: '/grand-parent/parent/children' };
+ return (
+
+
+
+ Arrow Separator
+
+
+
+
+
+ Slash Separator
+
+
+
+
+
+ Greater Than Separator
+
+
+
+
+
+
+ );
+ }
+}
+
+ClassicBreadcrumbs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ClassicBreadcrumbs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/PaperBreadcrumbs.js b/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/PaperBreadcrumbs.js
new file mode 100644
index 0000000..70effb0
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Breadcrumbs/PaperBreadcrumbs.js
@@ -0,0 +1,97 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { BreadCrumb } from 'ba-components';
+
+import { Typography, Grid, Paper } from '@material-ui/core';
+
+const styles = theme => ({
+ demo: {
+ height: 'auto',
+ },
+ divider: {
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ alone: {
+ position: 'relative',
+ margin: 20
+ },
+ field: {
+ margin: '10px',
+ position: 'relative'
+ },
+ paper: {
+ padding: '5px 10px 1px',
+ borderRadius: 5
+ }
+});
+
+class ClassicBreadcrumbs extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ const location = { pathname: '/grand-parent/parent/children' };
+ return (
+
+
+
+ Arrow Separator
+
+
+
+ Slash Separator
+
+
+
+ Greater Than Separator
+
+
+
+
+ );
+ }
+}
+
+ClassicBreadcrumbs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ClassicBreadcrumbs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Cards/ControlCards.js b/front/odiparpack/app/containers/UiElements/demos/Cards/ControlCards.js
new file mode 100644
index 0000000..1ddc92b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Cards/ControlCards.js
@@ -0,0 +1,204 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classnames from 'classnames';
+import FavoriteIcon from '@material-ui/icons/Favorite';
+import ShareIcon from '@material-ui/icons/Share';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import MoreVertIcon from '@material-ui/icons/MoreVert';
+import imgApi from 'ba-api/images';
+import { PlayerCard, VideoCard } from 'ba-components';
+import { red } from '@material-ui/core/colors';
+
+import {
+ Typography,
+ Grid,
+ Card,
+ CardHeader,
+ CardMedia,
+ CardContent,
+ CardActions,
+ IconButton,
+ Collapse,
+ Avatar,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ card: {
+ display: 'flex',
+ justifyContent: 'space-between'
+ },
+ details: {
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ content: {
+ flex: '1 0 auto',
+ },
+ cover: {
+ width: 150,
+ height: 150,
+ },
+ controls: {
+ display: 'flex',
+ alignItems: 'center',
+ paddingLeft: theme.spacing(1),
+ paddingBottom: theme.spacing(1),
+ },
+ playIcon: {
+ height: 38,
+ width: 38,
+ },
+ cardSocmed: {
+ maxWidth: 400,
+ },
+ media: {
+ height: 0,
+ paddingTop: '56.25%', // 16:9
+ },
+ actions: {
+ display: 'flex',
+ },
+ expand: {
+ transform: 'rotate(0deg)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.shortest,
+ }),
+ marginLeft: 'auto',
+ },
+ expandOpen: {
+ transform: 'rotate(180deg)',
+ },
+ avatar: {
+ backgroundColor: red[500],
+ },
+});
+
+class ControlCard extends React.Component {
+ state = { expanded: false };
+
+ handleExpandClick = () => {
+ this.setState({ expanded: !this.state.expanded });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+
+ UI Controls
+
+
+
+ Video Thumb
+
+
+
+ Complex Interaction
+
+
+
+ R
+
+ )}
+ action={(
+
+
+
+ )}
+ title="Shrimp and Chorizo Paella"
+ subheader="September 14, 2016"
+ />
+
+
+
+ This impressive paella is a perfect party dish and a fun meal to cook together with
+ your guests. Add 1 cup of frozen peas along with the mussels, if you like.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Method:
+
+
+ Heat 1/2 cup of the broth in a pot until simmering, add saffron and set aside for 10
+ minutes.
+
+
+ Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over medium-high
+ heat. Add chicken, shrimp and chorizo, and cook, stirring occasionally until lightly
+ browned, 6 to 8 minutes. Transfer shrimp to a large plate and set aside, leaving
+ chicken and chorizo in the pan. Add pimentón, bay leaves, garlic, tomatoes, onion,
+ salt and pepper, and cook, stirring often until thickened and fragrant, about 10
+ minutes. Add saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil.
+
+
+ Add rice and stir very gently to distribute. Top with artichokes and peppers, and
+ cook without stirring, until most of the liquid is absorbed, 15 to 18 minutes.
+ Reduce heat to medium-low, add reserved shrimp and mussels, tucking them down into
+ the rice, and cook again without stirring, until mussels have opened and rice is
+ just tender, 5 to 7 minutes more. (Discard any mussels that don’t open.)
+
+
+ Set aside off of the heat to let rest for 10 minutes, and then serve.
+
+
+
+
+
+
+
+ );
+ }
+}
+
+ControlCard.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ControlCard);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Cards/EcommerceCards.js b/front/odiparpack/app/containers/UiElements/demos/Cards/EcommerceCards.js
new file mode 100644
index 0000000..6a5a275
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Cards/EcommerceCards.js
@@ -0,0 +1,92 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgApi from 'ba-api/images';
+import { ProductCard } from 'ba-components';
+
+import { Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+});
+
+class EcommerceCard extends React.Component {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+ Product Card
+
+
+
+ Product with discount
+
+
+
+ Sold Out Product
+
+
+
+ List Mode
+
+
+
+
+
+
+ );
+ }
+}
+
+EcommerceCard.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(EcommerceCard);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Cards/PaperSheet.js b/front/odiparpack/app/containers/UiElements/demos/Cards/PaperSheet.js
new file mode 100644
index 0000000..2867e38
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Cards/PaperSheet.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Paper, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: theme.mixins.gutters({
+ paddingTop: 16,
+ paddingBottom: 16,
+ marginTop: theme.spacing(3),
+ }),
+});
+
+function PaperSheet(props) {
+ const { classes } = props;
+ return (
+
+
+
+ This is a sheet of paper.
+
+
+ Paper can be used to build surface or other elements for your application.
+
+
+
+ );
+}
+
+PaperSheet.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(PaperSheet);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Cards/SocialCards.js b/front/odiparpack/app/containers/UiElements/demos/Cards/SocialCards.js
new file mode 100644
index 0000000..7208926
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Cards/SocialCards.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgApi from 'ba-api/images';
+import avatarApi from 'ba-api/avatars';
+import { ProfileCard, PostCard } from 'ba-components';
+
+import { Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+});
+
+class StandardCard extends React.Component {
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+
+ Profile Card
+
+
+
+ Post Card
+
+
+
+ Post Card (Without Image)
+
+
+
+ );
+ }
+}
+
+StandardCard.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StandardCard);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Cards/StandardCards.js b/front/odiparpack/app/containers/UiElements/demos/Cards/StandardCards.js
new file mode 100644
index 0000000..37fdf39
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Cards/StandardCards.js
@@ -0,0 +1,120 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import dummy from 'ba-api/dummyContents';
+import imgApi from 'ba-api/images';
+import { GeneralCard, NewsCard, Quote, IdentityCard } from 'ba-components';
+
+import { Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ card: {
+ minWidth: 275,
+ },
+ bullet: {
+ display: 'inline-block',
+ margin: '0 2px',
+ transform: 'scale(0.8)',
+ },
+ title: {
+ marginBottom: 16,
+ fontSize: 14,
+ },
+ pos: {
+ marginBottom: 12,
+ },
+ cardMedia: {
+ maxWidth: 345,
+ },
+ media: {
+ height: 0,
+ paddingTop: '56.25%', // 16:9
+ },
+});
+
+class StandardCard extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const bull = •;
+
+ return (
+
+
+ Simple Card
+
+
+
+ Word of the Day
+
+
+ be
+ {bull}
+nev
+ {bull}
+o
+ {bull}
+lent
+
+
+ adjective
+
+
+ well meaning and kindly.
+
+ {'"a benevolent smile"'}
+
+
+
+ Media
+
+
+
+ Lorem ipsum
+
+
+ Aliquam venenatis magna et odio lobortis maximus. Nullam in tortor ligula. Proin maximus risus nunc
+
+
+
+
+
+ Quoted Card
+
+
+
+
+
+
+ Identity Card
+
+
+
+
+ );
+ }
+}
+
+StandardCard.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StandardCard);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/AlertDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/AlertDialog.js
new file mode 100644
index 0000000..68f099a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/AlertDialog.js
@@ -0,0 +1,127 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+ Grid,
+ Typography,
+ Slide,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ title: {
+ display: 'block',
+ margin: `${theme.spacing(4)}px 0 ${theme.spacing(2)}px`,
+ },
+});
+
+const Transition = React.forwardRef(function Transition(props, ref) { // eslint-disable-line
+ return ;
+});
+
+class AlertDialog extends React.Component { // eslint-disable-line
+ state = {
+ open: false,
+ openSlide: false,
+ };
+
+ handleClickOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleClickOpenSlide = () => {
+ this.setState({ openSlide: true });
+ };
+
+ handleCloseSlide = () => {
+ this.setState({ openSlide: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+
+ Fade Transition
+
+
+
+
+
+
+ Slide Transition
+
+
+
+
+
+
+ );
+ }
+}
+
+AlertDialog.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AlertDialog);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/ConfirmationDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ConfirmationDialog.js
new file mode 100644
index 0000000..1f49788
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ConfirmationDialog.js
@@ -0,0 +1,111 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ Button,
+ DialogTitle,
+ DialogContent,
+ DialogActions,
+ Dialog,
+ Radio,
+ RadioGroup,
+ FormControlLabel,
+} from '@material-ui/core';
+
+const options = [
+ 'None',
+ 'Atria',
+ 'Callisto',
+ 'Dione',
+ 'Ganymede',
+ 'Hangouts Call',
+ 'Luna',
+ 'Oberon',
+ 'Phobos',
+ 'Pyxis',
+ 'Sedna',
+ 'Titania',
+ 'Triton',
+ 'Umbriel',
+];
+
+class ConfirmationDialog extends React.Component {
+ constructor(props, context) {
+ super(props, context);
+
+ this.state.value = this.props.value;
+ }
+
+ state = {};
+
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.value !== this.props.value) {
+ this.setState({ value: nextProps.value });
+ }
+ }
+
+ radioGroup = null;
+
+ handleEntering = () => {
+ this.radioGroup.focus();
+ };
+
+ handleCancel = () => {
+ this.props.onClose(this.props.value);
+ };
+
+ handleOk = () => {
+ this.props.onClose(this.state.value);
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { value, ...other } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+ConfirmationDialog.propTypes = {
+ onClose: PropTypes.func.isRequired,
+ value: PropTypes.string.isRequired,
+};
+
+export default ConfirmationDialog;
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/FormDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/FormDialog.js
new file mode 100644
index 0000000..58bf1aa
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/FormDialog.js
@@ -0,0 +1,65 @@
+import React from 'react';
+
+import {
+ Button,
+ TextField,
+ Grid,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+} from '@material-ui/core';
+
+export default class FormDialog extends React.Component {
+ state = {
+ open: false,
+ };
+
+ handleClickOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/FullScreenDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/FullScreenDialog.js
new file mode 100644
index 0000000..935ed4d
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/FullScreenDialog.js
@@ -0,0 +1,134 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import CloseIcon from '@material-ui/icons/Close';
+
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+ List,
+ ListItem,
+ ListItemText,
+ Divider,
+ Grid,
+ AppBar,
+ Toolbar,
+ IconButton,
+ Typography,
+ Slide,
+} from '@material-ui/core';
+
+const styles = {
+ appBar: {
+ position: 'relative',
+ },
+ flex: {
+ flex: 1,
+ },
+};
+
+const Transition = React.forwardRef(function Transition(props, ref) { // eslint-disable-line
+ return ;
+});
+
+class FullScreenDialog extends React.Component { // eslint-disable-line
+ state = {
+ open: false,
+ open2: false,
+ };
+
+ handleClickOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleClickOpen2 = () => {
+ this.setState({ open2: true });
+ };
+
+ handleClose2 = () => {
+ this.setState({ open2: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+FullScreenDialog.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(FullScreenDialog);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/ImagePopup.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ImagePopup.js
new file mode 100644
index 0000000..169c5ec
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ImagePopup.js
@@ -0,0 +1,51 @@
+import React, { Component } from 'react';
+import 'ba-styles/vendors/image-lightbox/image-lightbox.css';
+import images from 'ba-api/imgData';
+import { ImageLightbox } from 'ba-components';
+
+import { Button, Grid } from '@material-ui/core';
+
+export default class ImagePopup extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ photoIndex: 0,
+ isOpen: false,
+ };
+ }
+
+ render() {
+ const { photoIndex, isOpen } = this.state;
+
+ return (
+
+
+
+ {isOpen && (
+ this.setState({ isOpen: false })}
+ onMovePrevRequest={() => this.setState({
+ photoIndex: (photoIndex + (images.length - 1)) % images.length,
+ })
+ }
+ onMoveNextRequest={() => this.setState({
+ photoIndex: (photoIndex + 1) % images.length,
+ })
+ }
+ />
+ )}
+
+ );
+ }
+}
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/ModalDemo.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ModalDemo.js
new file mode 100644
index 0000000..c18a5e1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ModalDemo.js
@@ -0,0 +1,73 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Typography, Modal, Button, Grid } from '@material-ui/core';
+
+function getModalStyle() {
+ return {
+ top: '50%',
+ left: '50%',
+ transform: 'translate(-50%, -50%)',
+ };
+}
+
+const styles = theme => ({
+ paper: {
+ position: 'absolute',
+ width: theme.spacing(50),
+ backgroundColor: theme.palette.background.paper,
+ boxShadow: theme.shadows[5],
+ padding: theme.spacing(4),
+ },
+});
+
+class ModalDemo extends React.Component {
+ state = {
+ open: false,
+ };
+
+ handleOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+ Click to get the full Modal experience!
+
+
+
+
+ Text in a modal
+
+
+ Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
+
+
+
+
+ );
+ }
+}
+
+ModalDemo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ModalDemo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/ScrollDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ScrollDialog.js
new file mode 100644
index 0000000..b7f2b74
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/ScrollDialog.js
@@ -0,0 +1,93 @@
+import React from 'react';
+
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+} from '@material-ui/core';
+
+class ScrollDialog extends React.Component {
+ state = {
+ open: false,
+ scroll: 'paper',
+ };
+
+ handleClickOpen = scroll => () => {
+ this.setState({ open: true, scroll });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ScrollDialog;
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectDialog.js
new file mode 100644
index 0000000..f75b1be
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectDialog.js
@@ -0,0 +1,120 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import PersonIcon from '@material-ui/icons/Person';
+import AddIcon from '@material-ui/icons/Add';
+import { blue } from '@material-ui/core/colors';
+
+import {
+ Button,
+ Avatar,
+ List,
+ ListItem,
+ ListItemText,
+ ListItemAvatar,
+ Dialog,
+ DialogTitle,
+ Typography,
+ Grid,
+} from '@material-ui/core';
+
+const emails = ['username@mail.com', 'user02@mail.com'];
+const styles = ({
+ avatar: {
+ backgroundColor: blue[100],
+ color: blue[600],
+ },
+});
+
+const SimpleDialog = props => {
+ const {
+ classes,
+ onClose,
+ selectedValue,
+ ...other
+ } = props;
+
+ function handleClose() {
+ props.onClose(this.props.selectedValue);
+ }
+
+ function handleListItemClick(value) {
+ props.onClose(value);
+ }
+
+ return (
+
+ );
+};
+
+SimpleDialog.propTypes = {
+ classes: PropTypes.object.isRequired,
+ onClose: PropTypes.func.isRequired,
+ selectedValue: PropTypes.string.isRequired,
+};
+
+const SimpleDialogWrapped = withStyles(styles)(SimpleDialog);
+
+class SelectDialog extends React.Component {
+ state = {
+ open: false,
+ selectedValue: emails[1],
+ };
+
+ handleClickOpen = () => {
+ this.setState({
+ open: true,
+ });
+ };
+
+ handleClose = value => {
+ this.setState({ selectedValue: value, open: false });
+ };
+
+ render() {
+ return (
+
+
+
+Selected:
+ {this.state.selectedValue}
+
+
+
+
+
+
+ );
+ }
+}
+
+
+export default SelectDialog;
diff --git a/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectRadioDialog.js b/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectRadioDialog.js
new file mode 100644
index 0000000..ff30bd4
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DialogModal/SelectRadioDialog.js
@@ -0,0 +1,68 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { List, ListItem, ListItemText } from '@material-ui/core';
+import ConfirmationDialog from './ConfirmationDialog';
+
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ maxWidth: 360,
+ backgroundColor: theme.palette.background.paper,
+ },
+ dialog: {
+ width: '80%',
+ maxHeight: 435,
+ },
+});
+
+class SelectRadioDialog extends React.Component {
+ state = {
+ open: false,
+ value: 'Dione',
+ };
+
+ button = undefined;
+
+ handleClickListItem = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = value => {
+ this.setState({ value, open: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+SelectRadioDialog.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SelectRadioDialog);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Dividers/CommonDividers.js b/front/odiparpack/app/containers/UiElements/demos/Dividers/CommonDividers.js
new file mode 100644
index 0000000..db67c0f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Dividers/CommonDividers.js
@@ -0,0 +1,29 @@
+import React, { Fragment, PureComponent } from 'react';
+import Type from 'ba-styles/Typography.scss';
+import {
+ GradientDivider,
+ DashDivider,
+ ShadowDivider,
+ InsetDivider,
+} from 'ba-components/Divider';
+
+import { Typography } from '@material-ui/core';
+
+class CommonDivider extends PureComponent {
+ render() {
+ return (
+
+ Gradient Divider
+
+ Dash Divider
+
+ Shadow Divider
+
+ Inset Divider
+
+
+ );
+ }
+}
+
+export default CommonDivider;
diff --git a/front/odiparpack/app/containers/UiElements/demos/Dividers/SpecialDividers.js b/front/odiparpack/app/containers/UiElements/demos/Dividers/SpecialDividers.js
new file mode 100644
index 0000000..d857e06
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Dividers/SpecialDividers.js
@@ -0,0 +1,23 @@
+import React, { Fragment, PureComponent } from 'react';
+import Type from 'ba-styles/Typography.scss';
+import {
+ FlairedEdgesDivider,
+ ContentDivider,
+} from 'ba-components/Divider';
+
+import { Typography } from '@material-ui/core';
+
+class CommonDivider extends PureComponent {
+ render() {
+ return (
+
+ Flaired Edges Divider
+
+ Content Text Divider
+
+
+ );
+ }
+}
+
+export default CommonDivider;
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/BasicMenu.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/BasicMenu.js
new file mode 100644
index 0000000..24039db
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/BasicMenu.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+
+import { Button, Menu, MenuItem, MenuList, Grid, Paper } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ },
+ paper: {
+ marginRight: theme.spacing(2),
+ },
+ popperClose: {
+ pointerEvents: 'none',
+ },
+});
+
+class BasicMenu extends React.Component {
+ state = {
+ anchorEl: null,
+ };
+
+ handleClick = event => {
+ this.setState({ anchorEl: event.currentTarget });
+ };
+
+ handleClose = () => {
+ this.setState({ anchorEl: null });
+ };
+
+ render() {
+ const { anchorEl } = this.state;
+ const { classes } = this.props;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+BasicMenu.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(BasicMenu);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/DropdownMenu.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/DropdownMenu.js
new file mode 100644
index 0000000..0e5bce7
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/DropdownMenu.js
@@ -0,0 +1,148 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import MoreVertIcon from '@material-ui/icons/MoreVert';
+
+import { IconButton, List, ListItem, ListItemText, Menu, MenuItem, Grid } from '@material-ui/core';
+
+const styles = {
+ root: {
+ width: '100%',
+ },
+};
+
+const options = [
+ 'Show some love to Material-UI',
+ 'Show all notification content',
+ 'Hide sensitive notification content',
+ 'Hide all notification content',
+];
+
+const optionsOpt = [
+ 'None',
+ 'Atria',
+ 'Callisto',
+ 'Dione',
+ 'Ganymede',
+ 'Hangouts Call',
+ 'Luna',
+ 'Oberon',
+ 'Phobos',
+ 'Pyxis',
+ 'Sedna',
+ 'Titania',
+ 'Triton',
+ 'Umbriel',
+];
+
+const ITEM_HEIGHT = 48;
+
+class DropdownMenu extends React.Component {
+ state = {
+ anchorEl: null,
+ anchorElOpt: null,
+ selectedIndex: 1,
+ };
+
+ button = undefined;
+
+ handleClickListItem = event => {
+ this.setState({ anchorEl: event.currentTarget });
+ };
+
+ handleMenuItemClick = (event, index) => {
+ this.setState({ selectedIndex: index, anchorEl: null });
+ };
+
+ handleClose = () => {
+ this.setState({ anchorEl: null });
+ };
+
+ handleClickOpt = event => {
+ this.setState({ anchorElOpt: event.currentTarget });
+ };
+
+ handleCloseOpt = () => {
+ this.setState({ anchorElOpt: null });
+ };
+
+
+ render() {
+ const { classes } = this.props;
+ const { anchorEl, anchorElOpt } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+DropdownMenu.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(DropdownMenu);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MenuTransition.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MenuTransition.js
new file mode 100644
index 0000000..e8cfbc6
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MenuTransition.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import Button from '@material-ui/core/Button';
+import Menu from '@material-ui/core/Menu';
+import MenuItem from '@material-ui/core/MenuItem';
+import Grow from '@material-ui/core/Grow';
+import Fade from '@material-ui/core/Fade';
+import Zoom from '@material-ui/core/Zoom';
+import Grid from '@material-ui/core/Grid';
+
+
+class MenuTransition extends React.Component {
+ state = {
+ anchorFade: null,
+ anchorGrow: null,
+ anchorCollapse: null,
+ anchorZoom: null,
+ };
+
+ handleClick = (event, type) => {
+ this.setState({ [type]: event.currentTarget });
+ };
+
+ handleClose = type => {
+ this.setState({ [type]: null });
+ };
+
+ handleToggle = type => {
+ // eslint-disable-next-line
+ this.setState({ [type]: !this.state[type] });
+ };
+
+ render() {
+ const {
+ anchorFade,
+ anchorGrow,
+ anchorZoom
+ } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default MenuTransition;
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MiniDrawer.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MiniDrawer.js
new file mode 100644
index 0000000..4a07e14
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/MiniDrawer.js
@@ -0,0 +1,235 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import MenuIcon from '@material-ui/icons/Menu';
+import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
+import ChevronRightIcon from '@material-ui/icons/ChevronRight';
+import {
+ Drawer,
+ AppBar,
+ Toolbar,
+ List,
+ Typography,
+ MenuItem,
+ Divider,
+ TextField,
+ IconButton,
+} from '@material-ui/core';
+import { mailFolderListItems, otherMailFolderListItems } from './menuData';
+
+
+const drawerWidth = 240;
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ },
+ appFrame: {
+ height: 430,
+ zIndex: 1,
+ overflow: 'hidden',
+ position: 'relative',
+ display: 'flex',
+ width: '100%',
+ },
+ appBar: {
+ zIndex: theme.zIndex.drawer + 1,
+ padding: '0 24px',
+ transition: theme.transitions.create(['width', 'margin'], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+ appBarShift: {
+ marginLeft: drawerWidth,
+ width: `calc(100% - ${drawerWidth}px)`,
+ transition: theme.transitions.create(['width', 'margin'], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ 'appBarShift-left': {
+ marginLeft: drawerWidth,
+ },
+ 'appBarShift-right': {
+ marginRight: drawerWidth,
+ },
+ menuButton: {
+ marginLeft: 3,
+ marginRight: 3,
+ },
+ hide: {
+ display: 'none',
+ },
+ drawerPaper: {
+ position: 'relative',
+ whiteSpace: 'nowrap',
+ width: drawerWidth,
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ drawerPaperClose: {
+ overflowX: 'hidden',
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ width: theme.spacing(7),
+ [theme.breakpoints.up('sm')]: {
+ width: theme.spacing(9),
+ },
+ },
+ toolbar: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'flex-end',
+ padding: '0 8px',
+ ...theme.mixins.toolbar,
+ },
+ content: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.default,
+ padding: theme.spacing(3),
+ },
+ 'content-left': {
+ marginLeft: -drawerWidth,
+ },
+ 'content-right': {
+ marginRight: -drawerWidth,
+ },
+ contentShift: {
+ transition: theme.transitions.create('margin', {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ 'contentShift-left': {
+ marginLeft: 0,
+ },
+ 'contentShift-right': {
+ marginRight: 0,
+ },
+ title: {
+ flex: 1,
+ }
+});
+
+class MiniDrawer extends React.Component {
+ state = {
+ open: false,
+ anchor: 'left',
+ };
+
+ handleDrawerOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleDrawerClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleChangeAnchor = event => {
+ this.setState({
+ anchor: event.target.value,
+ });
+ };
+
+ render() {
+ const { classes, theme } = this.props;
+ const { anchor, open } = this.state;
+ const drawer = (
+
+
+
+ {theme.direction === 'rtl' ? : }
+
+
+
+ {mailFolderListItems}
+
+ {otherMailFolderListItems}
+
+ );
+
+ const menuBtn = (
+
+
+
+ );
+
+ let before = null;
+ let after = null;
+ let beforeBtn = null;
+ let afterBtn = null;
+
+ if (anchor === 'left') {
+ before = drawer;
+ beforeBtn = menuBtn;
+ } else {
+ after = drawer;
+ afterBtn = menuBtn;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {beforeBtn}
+
+ Mini variant drawer
+
+ {afterBtn}
+
+
+ {before}
+
+
+
+ {'You think water moves fast? You should see ice.'}
+
+
+ {after}
+
+
+ );
+ }
+}
+
+MiniDrawer.propTypes = {
+ classes: PropTypes.object.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles, { withTheme: true })(MiniDrawer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PermanentDrawer.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PermanentDrawer.js
new file mode 100644
index 0000000..9538873
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PermanentDrawer.js
@@ -0,0 +1,126 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import { Drawer, AppBar, Toolbar, List, MenuItem, TextField, Typography, Divider } from '@material-ui/core';
+import { mailFolderListItems, otherMailFolderListItems } from './menuData';
+
+
+const drawerWidth = 240;
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ },
+ appFrame: {
+ height: 430,
+ zIndex: 1,
+ overflow: 'hidden',
+ position: 'relative',
+ display: 'flex',
+ width: '100%',
+ },
+ appBar: {
+ width: `calc(100% - ${drawerWidth}px)`,
+ },
+ 'appBar-left': {
+ marginLeft: drawerWidth,
+ },
+ 'appBar-right': {
+ marginRight: drawerWidth,
+ },
+ drawerPaper: {
+ position: 'relative',
+ width: drawerWidth,
+ },
+ toolbar: theme.mixins.toolbar,
+ content: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.default,
+ padding: theme.spacing(3),
+ },
+});
+
+class PermanentDrawer extends React.Component {
+ state = {
+ anchor: 'left',
+ };
+
+ handleChange = event => {
+ this.setState({
+ anchor: event.target.value,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { anchor } = this.state;
+
+ const drawer = (
+
+
+
+ {mailFolderListItems}
+
+ {otherMailFolderListItems}
+
+ );
+
+ let before = null;
+ let after = null;
+
+ if (anchor === 'left') {
+ before = drawer;
+ } else {
+ after = drawer;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ Permanent drawer
+
+
+
+ {before}
+
+
+
+ {'You think water moves fast? You should see ice.'}
+
+
+ {after}
+
+
+ );
+ }
+}
+
+PermanentDrawer.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(PermanentDrawer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PersistentDrawer.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PersistentDrawer.js
new file mode 100644
index 0000000..cd529d5
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/PersistentDrawer.js
@@ -0,0 +1,228 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import MenuIcon from '@material-ui/icons/Menu';
+import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
+import ChevronRightIcon from '@material-ui/icons/ChevronRight';
+import {
+ Drawer,
+ AppBar,
+ Toolbar,
+ List,
+ MenuItem,
+ Typography,
+ TextField,
+ Divider,
+ IconButton,
+} from '@material-ui/core';
+import { mailFolderListItems, otherMailFolderListItems } from './menuData';
+
+
+const drawerWidth = 240;
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ },
+ appFrame: {
+ height: 430,
+ zIndex: 1,
+ overflow: 'hidden',
+ position: 'relative',
+ display: 'flex',
+ width: '100%',
+ },
+ appBar: {
+ position: 'absolute',
+ padding: '0 24px',
+ transition: theme.transitions.create(['margin', 'width'], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+ appBarShift: {
+ width: `calc(100% - ${drawerWidth}px)`,
+ transition: theme.transitions.create(['margin', 'width'], {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ 'appBarShift-left': {
+ marginLeft: drawerWidth,
+ },
+ 'appBarShift-right': {
+ marginRight: drawerWidth,
+ },
+ menuButton: {
+ marginLeft: 3,
+ marginRight: 3,
+ },
+ hide: {
+ display: 'none',
+ },
+ drawerPaper: {
+ position: 'relative',
+ width: drawerWidth,
+ },
+ drawerHeader: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'flex-end',
+ padding: '0 8px',
+ ...theme.mixins.toolbar,
+ },
+ content: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.default,
+ padding: theme.spacing(3),
+ transition: theme.transitions.create('margin', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+ 'content-left': {
+ marginLeft: -drawerWidth,
+ },
+ 'content-right': {
+ marginRight: -drawerWidth,
+ },
+ contentShift: {
+ transition: theme.transitions.create('margin', {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ 'contentShift-left': {
+ marginLeft: 0,
+ },
+ 'contentShift-right': {
+ marginRight: 0,
+ },
+ title: {
+ flex: 1,
+ }
+});
+
+class PersistentDrawer extends React.Component {
+ state = {
+ open: false,
+ anchor: 'left',
+ };
+
+ handleDrawerOpen = () => {
+ this.setState({ open: true });
+ };
+
+ handleDrawerClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleChangeAnchor = event => {
+ this.setState({
+ anchor: event.target.value,
+ });
+ };
+
+ render() {
+ const { classes, theme } = this.props;
+ const { anchor, open } = this.state;
+
+ const drawer = (
+
+
+
+ {theme.direction === 'rtl' ? : }
+
+
+
+ {mailFolderListItems}
+
+ {otherMailFolderListItems}
+
+ );
+
+ const menuBtn = (
+
+
+
+ );
+
+ let before = null;
+ let after = null;
+ let beforeBtn = null;
+ let afterBtn = null;
+
+ if (anchor === 'left') {
+ before = drawer;
+ beforeBtn = menuBtn;
+ } else {
+ after = drawer;
+ afterBtn = menuBtn;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {beforeBtn}
+
+ Persistent drawer
+
+ {afterBtn}
+
+
+ {before}
+
+
+
+ {'You think water moves fast? You should see ice.'}
+
+
+ {after}
+
+
+ );
+ }
+}
+
+PersistentDrawer.propTypes = {
+ classes: PropTypes.object.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles, { withTheme: true })(PersistentDrawer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/StyledMenu.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/StyledMenu.js
new file mode 100644
index 0000000..ed6ac4a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/StyledMenu.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import InboxIcon from '@material-ui/icons/MoveToInbox';
+import DraftsIcon from '@material-ui/icons/Drafts';
+import SendIcon from '@material-ui/icons/Send';
+
+import { MenuList, MenuItem, Paper, ListItemIcon, ListItemText } from '@material-ui/core';
+
+const styles = theme => ({
+ menu: {
+ maxWidth: 400,
+ margin: '20 auto'
+ },
+ menuItem: {
+ '&:focus': {
+ backgroundColor: theme.palette.primary.main,
+ '& $primary, & $icon': {
+ color: theme.palette.common.white,
+ },
+ },
+ },
+ primary: {},
+ icon: {},
+});
+
+function StyledMenu(props) {
+ const { classes } = props;
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+StyledMenu.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StyledMenu);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/SwipeDrawer.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/SwipeDrawer.js
new file mode 100644
index 0000000..a91feb5
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/SwipeDrawer.js
@@ -0,0 +1,124 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { SwipeableDrawer, Button, List, Divider, Grid } from '@material-ui/core';
+import { mailFolderListItems, otherMailFolderListItems } from './menuData';
+
+
+const styles = {
+ list: {
+ width: 250,
+ },
+ fullList: {
+ width: 'auto',
+ },
+};
+
+class SwipeDrawer extends React.Component {
+ state = {
+ top: false,
+ left: false,
+ bottom: false,
+ right: false,
+ };
+
+ toggleDrawer = (side, open) => () => {
+ this.setState({
+ [side]: open,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ const sideList = (
+
+
{mailFolderListItems}
+
+
{otherMailFolderListItems}
+
+ );
+
+ const fullList = (
+
+
{mailFolderListItems}
+
+
{otherMailFolderListItems}
+
+ );
+
+ return (
+
+
+
+
+
+
+
+ {sideList}
+
+
+
+
+ {fullList}
+
+
+
+
+ {fullList}
+
+
+
+
+ {sideList}
+
+
+
+ );
+ }
+}
+
+SwipeDrawer.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SwipeDrawer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/TemporaryDrawer.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/TemporaryDrawer.js
new file mode 100644
index 0000000..6af2a24
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/TemporaryDrawer.js
@@ -0,0 +1,109 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Drawer, Button, List, Divider, Grid } from '@material-ui/core';
+import { mailFolderListItems, otherMailFolderListItems } from './menuData';
+
+
+const styles = {
+ list: {
+ width: 250,
+ },
+ fullList: {
+ width: 'auto',
+ },
+};
+
+class TemporaryDrawer extends React.Component {
+ state = {
+ top: false,
+ left: false,
+ bottom: false,
+ right: false,
+ };
+
+ toggleDrawer = (side, open) => () => {
+ this.setState({
+ [side]: open,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ const sideList = (
+
+
{mailFolderListItems}
+
+
{otherMailFolderListItems}
+
+ );
+
+ const fullList = (
+
+
{mailFolderListItems}
+
+
{otherMailFolderListItems}
+
+ );
+
+ return (
+
+
+
+
+
+
+
+ {sideList}
+
+
+
+
+ {fullList}
+
+
+
+
+ {fullList}
+
+
+
+
+ {sideList}
+
+
+
+ );
+ }
+}
+
+TemporaryDrawer.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TemporaryDrawer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/menuData.js b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/menuData.js
new file mode 100644
index 0000000..cd2d653
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/DrawerMenu/menuData.js
@@ -0,0 +1,64 @@
+// This file is shared across the demos.
+
+import React from 'react';
+import InboxIcon from '@material-ui/icons/MoveToInbox';
+import DraftsIcon from '@material-ui/icons/Drafts';
+import StarIcon from '@material-ui/icons/Star';
+import SendIcon from '@material-ui/icons/Send';
+import MailIcon from '@material-ui/icons/Mail';
+import DeleteIcon from '@material-ui/icons/Delete';
+import ReportIcon from '@material-ui/icons/Report';
+
+import { ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
+
+export const mailFolderListItems = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export const otherMailFolderListItems = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
diff --git a/front/odiparpack/app/containers/UiElements/demos/ImageGrid/AdvancedGridList.js b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/AdvancedGridList.js
new file mode 100644
index 0000000..5d11f0d
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/AdvancedGridList.js
@@ -0,0 +1,85 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import StarBorderIcon from '@material-ui/icons/StarBorder';
+import imgData from 'ba-api/imgData';
+
+import { GridList, GridListTile, GridListTileBar, IconButton } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ justifyContent: 'space-around',
+ overflow: 'hidden',
+ backgroundColor: theme.palette.background.paper,
+ },
+ gridList: {
+ width: 500,
+ height: 450,
+ // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS.
+ transform: 'translateZ(0)',
+ },
+ titleBar: {
+ background:
+ 'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, '
+ + 'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)',
+ },
+ icon: {
+ color: 'white',
+ },
+ img: {
+ maxWidth: 'none'
+ }
+});
+
+/**
+ * The example data is structured as follows:
+ *
+ * import image from 'path/to/image.jpg';
+ * [etc...]
+ *
+ * const tileData = [
+ * {
+ * img: image,
+ * title: 'Image',
+ * author: 'author',
+ * featured: true,
+ * },
+ * {
+ * [etc...]
+ * },
+ * ];
+ */
+function AdvancedGridList(props) {
+ const { classes } = props;
+
+ return (
+
+
+ {imgData.map((tile, index) => (
+
+
+
+
+
+ )}
+ actionPosition="left"
+ className={classes.titleBar}
+ />
+
+ ))}
+
+
+ );
+}
+
+AdvancedGridList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AdvancedGridList);
diff --git a/front/odiparpack/app/containers/UiElements/demos/ImageGrid/ImageGridList.js b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/ImageGridList.js
new file mode 100644
index 0000000..ce785ac
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/ImageGridList.js
@@ -0,0 +1,66 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgData from 'ba-api/imgData';
+
+import { GridList, GridListTile } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ justifyContent: 'space-around',
+ overflow: 'hidden',
+ backgroundColor: theme.palette.background.paper,
+ },
+ gridList: {
+ width: 500,
+ height: 450,
+ },
+ subheader: {
+ width: '100%',
+ },
+ img: {
+ maxWidth: 'none'
+ }
+});
+
+/**
+ * The example data is structured as follows:
+ *
+ * import image from 'path/to/image.jpg';
+ * [etc...]
+ *
+ * const tileData = [
+ * {
+ * img: image,
+ * title: 'Image',
+ * author: 'author',
+ * cols: 2,
+ * },
+ * {
+ * [etc...]
+ * },
+ * ];
+ */
+function ImageGridList(props) {
+ const { classes } = props;
+
+ return (
+
+
+ {imgData.map((tile, index) => (
+
+
+
+ ))}
+
+
+ );
+}
+
+ImageGridList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ImageGridList);
diff --git a/front/odiparpack/app/containers/UiElements/demos/ImageGrid/SingleLineGridList.js b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/SingleLineGridList.js
new file mode 100644
index 0000000..ac30e6f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/SingleLineGridList.js
@@ -0,0 +1,83 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import StarBorderIcon from '@material-ui/icons/StarBorder';
+import imgData from 'ba-api/imgData';
+
+import { GridList, GridListTile, GridListTileBar, IconButton } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ justifyContent: 'space-around',
+ overflow: 'hidden',
+ backgroundColor: theme.palette.background.paper,
+ },
+ gridList: {
+ flexWrap: 'nowrap',
+ // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS.
+ transform: 'translateZ(0)',
+ },
+ title: {
+ color: theme.palette.primary.light,
+ },
+ titleBar: {
+ background:
+ 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)',
+ },
+ img: {
+ maxWidth: 'none'
+ }
+});
+
+/**
+ * The example data is structured as follows:
+ *
+ * import image from 'path/to/image.jpg';
+ * [etc...]
+ *
+ * const tileData = [
+ * {
+ * img: image,
+ * title: 'Image',
+ * author: 'author',
+ * },
+ * {
+ * [etc...]
+ * },
+ * ];
+ */
+function SingleLineGridList(props) {
+ const { classes } = props;
+
+ return (
+
+
+ {imgData.map((tile, index) => (
+
+
+
+
+
+ )}
+ />
+
+ ))}
+
+
+ );
+}
+
+SingleLineGridList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SingleLineGridList);
diff --git a/front/odiparpack/app/containers/UiElements/demos/ImageGrid/TitlebarGridList.js b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/TitlebarGridList.js
new file mode 100644
index 0000000..41f8d1a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/ImageGrid/TitlebarGridList.js
@@ -0,0 +1,89 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import InfoIcon from '@material-ui/icons/Info';
+import imgData from 'ba-api/imgData';
+
+import {
+ GridList,
+ GridListTile,
+ GridListTileBar,
+ ListSubheader as Subheader,
+ IconButton,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ justifyContent: 'space-around',
+ overflow: 'hidden',
+ backgroundColor: theme.palette.background.paper,
+ },
+ gridList: {
+ width: 500,
+ height: 450,
+ },
+ icon: {
+ color: 'rgba(255, 255, 255, 0.54)',
+ },
+ img: {
+ maxWidth: 'none'
+ }
+});
+
+/**
+ * The example data is structured as follows:
+ *
+ * import image from 'path/to/image.jpg';
+ * [etc...]
+ *
+ * const tileData = [
+ * {
+ * img: image,
+ * title: 'Image',
+ * author: 'author',
+ * },
+ * {
+ * [etc...]
+ * },
+ * ];
+ */
+function TitlebarGridList(props) {
+ const { classes } = props;
+
+ return (
+
+
+
+ December
+
+ {imgData.map((tile, index) => (
+
+
+
+by:
+ {tile.author}
+
+ )}
+ actionIcon={(
+
+
+
+ )}
+ />
+
+ ))}
+
+
+ );
+}
+
+TitlebarGridList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TitlebarGridList);
diff --git a/front/odiparpack/app/containers/UiElements/demos/List/ListBasic.js b/front/odiparpack/app/containers/UiElements/demos/List/ListBasic.js
new file mode 100644
index 0000000..ba4f13a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/List/ListBasic.js
@@ -0,0 +1,116 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+// import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import ImageIcon from '@material-ui/icons/Image';
+import WorkIcon from '@material-ui/icons/Work';
+import BeachAccessIcon from '@material-ui/icons/BeachAccess';
+
+import { red, green, amber } from '@material-ui/core/colors';
+
+import {
+ Typography, Grid, List,
+ ListItem, ListItemText, ListItemAvatar,
+ Avatar, Divider
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ maxWidth: '360px',
+ backgroundColor: theme.palette.background.paper,
+ margin: 10
+ },
+ avatarRed: {
+ backgroundColor: red[500],
+ },
+ avatarGreen: {
+ backgroundColor: green[500],
+ },
+ avatarAmber: {
+ backgroundColor: amber[500],
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class ListBasic extends PureComponent {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Simple List Divider
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Inset Divider
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+ListBasic.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ListBasic);
diff --git a/front/odiparpack/app/containers/UiElements/demos/List/ListControl.js b/front/odiparpack/app/containers/UiElements/demos/List/ListControl.js
new file mode 100644
index 0000000..2743d4b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/List/ListControl.js
@@ -0,0 +1,159 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import CommentIcon from '@material-ui/icons/Comment';
+import WifiIcon from '@material-ui/icons/Wifi';
+import BluetoothIcon from '@material-ui/icons/Bluetooth';
+
+import {
+ List,
+ ListItem,
+ ListItemIcon,
+ ListItemSecondaryAction,
+ ListItemText,
+ ListSubheader,
+ ListItemAvatar,
+ Checkbox,
+ Switch,
+ IconButton,
+ Grid,
+ Typography,
+ Avatar,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ maxWidth: 360,
+ backgroundColor: theme.palette.background.paper,
+ margin: 10
+ },
+});
+
+class ListControl extends React.Component {
+ state = {
+ checked: [0],
+ checked2: [1],
+ checked3: ['wifi'],
+ };
+
+ handleToggle = value => () => {
+ const { checked } = this.state;
+ const currentIndex = checked.indexOf(value);
+ const newChecked = [...checked];
+
+ if (currentIndex === -1) {
+ newChecked.push(value);
+ } else {
+ newChecked.splice(currentIndex, 1);
+ }
+
+ this.setState({
+ checked: newChecked,
+ checked2: newChecked,
+ checked3: newChecked,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Checkbox
+
+
+ {[0, 1, 2, 3].map(value => (
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ Checkbox
+
+
+ {[0, 1, 2, 3].map(value => (
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ Switch
+
+ Settings}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+ListControl.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ListControl);
diff --git a/front/odiparpack/app/containers/UiElements/demos/List/ListInteractive.js b/front/odiparpack/app/containers/UiElements/demos/List/ListInteractive.js
new file mode 100644
index 0000000..f8d3fa8
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/List/ListInteractive.js
@@ -0,0 +1,183 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import FolderIcon from '@material-ui/icons/Folder';
+import DeleteIcon from '@material-ui/icons/Delete';
+import { cyan } from '@material-ui/core/colors';
+
+import {
+ List,
+ ListItem,
+ ListItemAvatar,
+ ListItemIcon,
+ ListItemSecondaryAction,
+ ListItemText,
+ Avatar,
+ IconButton,
+ FormGroup,
+ FormControlLabel,
+ Checkbox,
+ Grid,
+ Typography,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ maxWidth: 752,
+ },
+ demo: {
+ backgroundColor: theme.palette.background.paper,
+ },
+ title: {
+ margin: `${theme.spacing(4)}px 0 ${theme.spacing(2)}px`,
+ },
+ iconCyan: {
+ color: cyan[300]
+ },
+ avatarCyan: {
+ background: cyan[300]
+ }
+});
+
+function generate(element) {
+ return [0, 1, 2].map(value => React.cloneElement(element, {
+ key: value,
+ }),
+ );
+}
+
+class ListInteractive extends React.Component {
+ state = {
+ dense: false,
+ secondary: false,
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { dense, secondary } = this.state;
+
+ return (
+
+
+ this.setState({ dense: checked })}
+ value="dense"
+ />
+ )}
+ label="Enable dense"
+ />
+ this.setState({ secondary: checked })}
+ value="secondary"
+ />
+ )}
+ label="Enable secondary text"
+ />
+
+
+
+
+ Text only
+
+
+
+ {generate(
+
+
+ ,
+ )}
+
+
+
+
+
+ Icon with text
+
+
+
+ {generate(
+
+
+
+
+
+ ,
+ )}
+
+
+
+
+
+
+
+ Avatar with text
+
+
+
+ {generate(
+
+
+
+
+
+
+
+ ,
+ )}
+
+
+
+
+
+ Avatar with text and icon
+
+
+
+ {generate(
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ )}
+
+
+
+
+
+ );
+ }
+}
+
+ListInteractive.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ListInteractive);
diff --git a/front/odiparpack/app/containers/UiElements/demos/List/ListMenu.js b/front/odiparpack/app/containers/UiElements/demos/List/ListMenu.js
new file mode 100644
index 0000000..f796f76
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/List/ListMenu.js
@@ -0,0 +1,204 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import StarIcon from '@material-ui/icons/Star';
+import ImageIcon from '@material-ui/icons/Image';
+import WorkIcon from '@material-ui/icons/Work';
+import BeachAccessIcon from '@material-ui/icons/BeachAccess';
+import InboxIcon from '@material-ui/icons/Inbox';
+import DraftsIcon from '@material-ui/icons/Drafts';
+import SendIcon from '@material-ui/icons/Send';
+import ExpandLess from '@material-ui/icons/ExpandLess';
+import ExpandMore from '@material-ui/icons/ExpandMore';
+import StarBorder from '@material-ui/icons/StarBorder';
+import { red, green, amber, lightBlue, pink, teal } from '@material-ui/core/colors';
+
+import {
+ Typography,
+ Grid,
+ List,
+ ListItem,
+ ListItemIcon,
+ ListItemText,
+ ListSubheader,
+ ListItemAvatar,
+ Divider,
+ Avatar,
+ Collapse,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ maxWidth: '360px',
+ backgroundColor: theme.palette.background.paper,
+ margin: 10
+ },
+ nested: {
+ paddingLeft: theme.spacing(4),
+ },
+ avatarRed: {
+ backgroundColor: red[500],
+ },
+ avatarGreen: {
+ backgroundColor: green[500],
+ },
+ avatarAmber: {
+ backgroundColor: amber[500],
+ },
+ iconBlue: {
+ color: lightBlue[500]
+ },
+ iconPink: {
+ color: pink[500]
+ },
+ iconAmber: {
+ color: amber[500]
+ },
+ iconTeal: {
+ color: teal[500]
+ },
+});
+
+class ListMenu extends PureComponent {
+ state = { open: true };
+
+ handleClick = () => {
+ this.setState({ open: !this.state.open });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Menu List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Folder List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Inset List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nested List
+
+ Nested List Items}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.state.open ? : }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+ListMenu.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ListMenu);
diff --git a/front/odiparpack/app/containers/UiElements/demos/List/PinnedList.js b/front/odiparpack/app/containers/UiElements/demos/List/PinnedList.js
new file mode 100644
index 0000000..e770fd0
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/List/PinnedList.js
@@ -0,0 +1,62 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Grid, ListSubheader, List, ListItem, ListItemText } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ maxWidth: 360,
+ backgroundColor: theme.palette.background.paper,
+ position: 'relative',
+ overflow: 'auto',
+ maxHeight: 300,
+ },
+ listSection: {
+ backgroundColor: 'inherit',
+ },
+ ul: {
+ backgroundColor: 'inherit',
+ padding: 0,
+ },
+ head: {
+ backgroundColor: theme.palette.secondary.light,
+ lineHeight: '30px',
+ height: 30,
+ textTransform: 'uppercase'
+ }
+});
+
+function PinnedList(props) {
+ const { classes } = props;
+
+ return (
+
+
}>
+ {[0, 1, 2, 3, 4].map(sectionId => (
+
+
+ {`I'm sticky ${sectionId}`}
+ {[0, 1, 2].map(item => (
+
+
+
+ ))}
+
+
+ ))}
+
+
+ );
+}
+
+PinnedList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(PinnedList);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Notification/MobileNotif.js b/front/odiparpack/app/containers/UiElements/demos/Notification/MobileNotif.js
new file mode 100644
index 0000000..60cdbbd
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Notification/MobileNotif.js
@@ -0,0 +1,116 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import MenuIcon from '@material-ui/icons/Menu';
+import AddIcon from '@material-ui/icons/Add';
+import { AppBar, Toolbar, IconButton, Typography, Button, Fab, Snackbar } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ position: 'relative',
+ overflow: 'hidden',
+ },
+ appFrame: {
+ width: '100%',
+ height: 360,
+ backgroundColor: theme.palette.background.paper,
+ },
+ menuButton: {
+ marginLeft: -12,
+ marginRight: 20,
+ },
+ button: {
+ marginBottom: theme.spacing(1),
+ },
+ fab: {
+ position: 'absolute',
+ bottom: theme.spacing(2),
+ right: theme.spacing(2),
+ },
+ fabMoveUp: {
+ transform: 'translate3d(0, -46px, 0)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.enteringScreen,
+ easing: theme.transitions.easing.easeOut,
+ }),
+ },
+ fabMoveDown: {
+ transform: 'translate3d(0, 0, 0)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.leavingScreen,
+ easing: theme.transitions.easing.sharp,
+ }),
+ },
+ snackbar: {
+ position: 'absolute',
+ },
+ snackbarContent: {
+ width: '100%',
+ },
+});
+
+class MobileNotif extends React.Component {
+ state = {
+ open: false,
+ };
+
+ handleClick = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { open } = this.state;
+ const fabClassName = classNames(classes.fab, open ? classes.fabMoveUp : classes.fabMoveDown);
+
+ return (
+
+
+
+
+
+
+
+
+
+ Out of my way!
+
+
+
+
+
+
+
Archived}
+ action={(
+
+ )}
+ className={classes.snackbar}
+ />
+
+
+ );
+ }
+}
+
+MobileNotif.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(MobileNotif);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Notification/SimpleNotif.js b/front/odiparpack/app/containers/UiElements/demos/Notification/SimpleNotif.js
new file mode 100644
index 0000000..0b068b5
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Notification/SimpleNotif.js
@@ -0,0 +1,132 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import CloseIcon from '@material-ui/icons/Close';
+import { Typography, Button, Snackbar, IconButton, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ close: {
+ width: theme.spacing(4)
+ },
+ divider: {
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ button: {
+ margin: theme.spacing(1)
+ }
+});
+
+class SimpleNotif extends React.Component {
+ state = {
+ open: false,
+ open2: false,
+ vertical: 'bottom',
+ horizontal: 'left',
+ };
+
+ handleClick = () => {
+ this.setState({ open: true });
+ };
+
+ handleClose = (event, reason) => {
+ if (reason === 'clickaway') {
+ return;
+ }
+
+ this.setState({ open: false });
+ };
+
+ handleClick2 = state => () => {
+ this.setState({ open2: true, ...state });
+ };
+
+ handleClose2 = () => {
+ this.setState({ open2: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { vertical, horizontal, open2 } = this.state;
+ return (
+
+
+ Simple Notification
+
+
+ Note archived}
+ action={[
+ ,
+
+
+ ,
+ ]}
+ />
+
+
+
+ Positioning
+
+
+
+
+
+
+
+ I love snacks}
+ />
+
+
+
+ );
+ }
+}
+
+SimpleNotif.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimpleNotif);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Notification/StyledNotif.js b/front/odiparpack/app/containers/UiElements/demos/Notification/StyledNotif.js
new file mode 100644
index 0000000..2ad8dba
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Notification/StyledNotif.js
@@ -0,0 +1,198 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import classNames from 'classnames';
+import CheckCircleOutlinedIcon from '@material-ui/icons/CheckCircleOutlined';
+import ErrorOutlineOutlinedIcon from '@material-ui/icons/ErrorOutlineOutlined';
+import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
+import CloseIcon from '@material-ui/icons/Close';
+import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
+import messageStyles from 'ba-styles/Messages.scss';
+
+import { Typography, Button, IconButton, Snackbar, SnackbarContent, Grid } from '@material-ui/core';
+
+const variantIcon = {
+ success: CheckCircleOutlinedIcon,
+ warning: ReportProblemOutlinedIcon,
+ error: ErrorOutlineOutlinedIcon,
+ info: InfoOutlinedIcon,
+};
+
+const styles1 = theme => ({
+ success: {
+ backgroundColor: '#b6f8c4',
+ },
+ error: {
+ backgroundColor: '#faabab',
+ },
+ info: {
+ backgroundColor: '#b2e7f5',
+ },
+ warning: {
+ backgroundColor: '#f5ea9f',
+ },
+ icon: {
+ fontSize: 20,
+ color: 'black'
+ },
+ iconVariant: {
+ opacity: 0.9,
+ marginRight: theme.spacing(1),
+ },
+ message: {
+ display: 'flex',
+ alignItems: 'center',
+ color: 'black'
+ },
+});
+
+function MySnackbarContent(props) {
+ const {
+ classes,
+ className,
+ message,
+ onClose,
+ variant,
+ ...other
+ } = props;
+ const Icon = variantIcon[variant];
+
+ return (
+
+
+ {message}
+
+ )}
+ action={[
+
+
+ ,
+ ]}
+ {...other}
+ />
+ );
+}
+
+MySnackbarContent.propTypes = {
+ classes: PropTypes.object.isRequired,
+ className: PropTypes.string.isRequired,
+ message: PropTypes.node.isRequired,
+ onClose: PropTypes.func,
+ variant: PropTypes.oneOf(['success', 'warning', 'error', 'info']).isRequired,
+};
+
+MySnackbarContent.defaultProps = {
+ onClose: () => {}
+};
+
+const MySnackbarContentWrapper = withStyles(styles1)(MySnackbarContent);
+
+const styles = theme => ({
+ snackbar: {
+ margin: theme.spacing(1),
+ },
+ divider: {
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ margin: {
+ margin: theme.spacing(1)
+ }
+});
+
+const action = (
+
+);
+
+class StyledNotif extends React.Component {
+ state = {
+ openStyle: false,
+ };
+
+ handleClickStyle = () => {
+ this.setState({ openStyle: true });
+ };
+
+ handleCloseStyle = (event, reason) => {
+ if (reason === 'clickaway') {
+ return;
+ }
+ this.setState({ openStyle: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+ Default Styled Notification
+
+
+
+
+
+
+
+
+
+
+ Custom Styled Notification with CSS
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+StyledNotif.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(StyledNotif);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Notification/TransitionNotif.js b/front/odiparpack/app/containers/UiElements/demos/Notification/TransitionNotif.js
new file mode 100644
index 0000000..6ac8df5
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Notification/TransitionNotif.js
@@ -0,0 +1,203 @@
+import React, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import CloseIcon from '@material-ui/icons/Close';
+
+import { Typography, Button, Grid, Snackbar, Slide, Fade, IconButton } from '@material-ui/core';
+
+const styles = theme => ({
+ row: {
+ display: 'flex',
+ justifyContent: 'flex-start',
+ },
+ close: {
+ width: theme.spacing(4)
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ },
+ button: {
+ margin: theme.spacing(1)
+ }
+});
+
+function TransitionLeft(props) {
+ return ;
+}
+
+function TransitionUp(props) {
+ return ;
+}
+
+function TransitionRight(props) {
+ return ;
+}
+
+function TransitionDown(props) {
+ return ;
+}
+
+class TransitionNotif extends PureComponent {
+ state = {
+ open: false,
+ open2: false,
+ open3: false,
+ transition: null,
+ messageInfo: {},
+ };
+
+ queue = [];
+
+ handleClickQueue = message => () => {
+ this.queue.push({
+ message,
+ key: new Date().getTime(),
+ });
+
+ if (this.state.open3) {
+ // immediately begin dismissing current message
+ // to start showing new one
+ this.setState({ open3: false });
+ } else {
+ this.processQueue();
+ }
+ };
+
+ processQueue = () => {
+ if (this.queue.length > 0) {
+ this.setState({
+ messageInfo: this.queue.shift(),
+ open3: true,
+ });
+ }
+ };
+
+ handleCloseQueue = (event, reason) => {
+ if (reason === 'clickaway') {
+ return;
+ }
+ this.setState({ open3: false });
+ };
+
+ handleExited = () => {
+ this.processQueue();
+ };
+
+ handleClick = transition => () => {
+ this.setState({ open: true, transition });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleClick2 = () => {
+ this.setState({ open2: true });
+ };
+
+ handleClose2 = () => {
+ this.setState({ open2: false });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { message, key } = this.state.messageInfo;
+ return (
+
+
+
+ Transition
+
+
+
+
+
+ I love snacks}
+ />
+
+
+
+ Change Transition
+
+
+ I love snacks}
+ />
+
+
+
+ Consecutive Snackbars
+
+
+
+ {message}}
+ action={[
+ ,
+
+
+
+ ]}
+ />
+
+
+
+
+ );
+ }
+}
+
+TransitionNotif.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TransitionNotif);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Pagination/GeneralPagination.js b/front/odiparpack/app/containers/UiElements/demos/Pagination/GeneralPagination.js
new file mode 100644
index 0000000..884be0a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Pagination/GeneralPagination.js
@@ -0,0 +1,136 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Pagination } from 'ba-components';
+import { Paper } from '@material-ui/core';
+
+const styles = theme => ({
+ paper: theme.mixins.gutters({
+ paddingTop: 16,
+ paddingBottom: 16,
+ marginTop: theme.spacing(3),
+ }),
+});
+
+class GeneralPagination extends React.Component {
+ constructor() {
+ super();
+ this.state = {
+ page: 1,
+ content: [
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
+ 'Suspendisse sed urna in justo euismod condimentum',
+ 'Fusce placerat enim et odio molestie sagittis.',
+ 'Vestibulum dignissim orci vitae eros rutrum euismod.',
+ 'Vestibulum tempor, sem et molestie egestas, dui tortor laoreet tellus, id rhoncus mauris neque malesuada augue.',
+ 'Duis tristique metus magna, lobortis aliquam risus euismod sit amet.',
+ 'Suspendisse porttitor velit nisl, feugiat tincidunt nisl mattis ut.',
+ 'Nulla lobortis nunc vitae nisi semper semper.',
+ 'Sed mi neque, convallis at ipsum at, blandit pretium enim.',
+ 'Nunc quis sem quis velit tincidunt congue a sit amet ante.',
+ 'In hac habitasse platea dictumst.',
+ 'In mi nulla, fringilla vestibulum finibus et, vehicula non leo. Vivamus et luctus mauris.',
+ 'Maecenas nisl libero, tincidunt id odio id, feugiat vulputate quam. Vestibulum feugiat rhoncus metus.',
+ 'In non erat et ipsum molestie porta sit amet ut felis.',
+ 'Vestibulum a massa vestibulum, gravida odio id, fringilla ipsum.',
+ 'Ut sed eros finibus, placerat orci id, dapibus mauris.',
+ 'Proin varius, tortor faucibus tempor pharetra, nunc mi consectetur enim, nec posuere ante magna vitae quam.',
+ 'Cras convallis lacus orci, tristique tincidunt magna consequat in.',
+ 'Vestibulum consequat hendrerit lacus. In id nisi id neque venenatis molestie.',
+ 'Quisque lacinia purus ut libero facilisis, at vulputate sem maximus.',
+ 'Pellentesque ac bibendum tortor, vel blandit nulla.',
+ 'Nulla eget lobortis lacus.',
+ 'Aliquam venenatis magna et odio lobortis maximus.',
+ 'Nullam in tortor ligula.',
+ 'Proin maximus risus nunc, eu aliquam nibh tempus a.',
+ 'Interdum et malesuada fames ac ante ipsum primis in faucibus.',
+ ],
+ contentsPerPage: 3
+ };
+ this.onPageChange = this.onPageChange.bind(this);
+ this.onPrev = this.onPrev.bind(this);
+ this.onNext = this.onNext.bind(this);
+ this.onGoFirst = this.onGoFirst.bind(this);
+ this.onGoLast = this.onGoLast.bind(this);
+ }
+
+ onPageChange(page) {
+ this.setState({ page });
+ }
+
+ onPrev() {
+ if (this.state.page > 1) {
+ this.setState({ page: this.state.page -= 1 });
+ } else {
+ this.setState({ page: 1 });
+ }
+ }
+
+ onNext(totalPages) {
+ if (this.state.page < totalPages) {
+ this.setState({ page: this.state.page += 1 });
+ } else {
+ this.setState({ page: totalPages });
+ }
+ }
+
+ onGoFirst() {
+ this.setState({ page: 1 });
+ }
+
+ onGoLast(totalPages) {
+ this.setState({ page: totalPages });
+ }
+
+ render() {
+ const { classes } = this.props;
+ const { page, content, contentsPerPage } = this.state;
+
+ // Logic for displaying current todos
+ const indexOfLastTodo = page * contentsPerPage;
+ const indexOfFirstTodo = indexOfLastTodo - contentsPerPage;
+ const currentContent = content.slice(indexOfFirstTodo, indexOfLastTodo);
+
+ const renderContent = currentContent.map((ctn, index) => (
+ {ctn}
+ ));
+
+ // Logic for displaying page numbers
+ const pageNumbers = [];
+ for (let i = 1; i <= Math.ceil(content.length / contentsPerPage); i += 1) {
+ pageNumbers.push(i);
+ }
+
+ return (
+
+
+
+We are in page
+ {page}
+
+
+ {renderContent}
+
+
+
this.onNext(pageNumbers.length)}
+ onGoFirst={this.onGoFirst}
+ onGoLast={() => this.onGoLast(pageNumbers.length)}
+ />
+
+ );
+ }
+}
+
+GeneralPagination.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(GeneralPagination);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPagination.js b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPagination.js
new file mode 100644
index 0000000..d1a0214
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPagination.js
@@ -0,0 +1,110 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Table, TableBody, TableCell, TableFooter, TablePagination, TableRow, Paper } from '@material-ui/core';
+
+let counter = 0;
+function createData(name, calories, fat) {
+ counter += 1;
+ return {
+ id: counter,
+ name,
+ calories,
+ fat
+ };
+}
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ },
+ table: {
+ minWidth: 500,
+ },
+ tableWrapper: {
+ overflowX: 'auto',
+ },
+});
+
+class TbPagination extends React.Component {
+ constructor(props, context) {
+ super(props, context);
+
+ this.state = {
+ data: [
+ createData('Cupcake', 305, 3.7),
+ createData('Donut', 452, 25.0),
+ createData('Eclair', 262, 16.0),
+ createData('Frozen yoghurt', 159, 6.0),
+ createData('Gingerbread', 356, 16.0),
+ createData('Honeycomb', 408, 3.2),
+ createData('Ice cream sandwich', 237, 9.0),
+ createData('Jelly Bean', 375, 0.0),
+ createData('KitKat', 518, 26.0),
+ createData('Lollipop', 392, 0.2),
+ createData('Marshmallow', 318, 0),
+ createData('Nougat', 360, 19.0),
+ createData('Oreo', 437, 18.0),
+ ].sort((a, b) => (a.calories < b.calories ? -1 : 1)),
+ page: 0,
+ rowsPerPage: 5,
+ };
+ }
+
+ handleChangePage = (event, page) => {
+ this.setState({ page });
+ };
+
+ handleChangeRowsPerPage = event => {
+ this.setState({ rowsPerPage: event.target.value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { data, rowsPerPage, page } = this.state;
+ const emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - (page * rowsPerPage));
+
+ return (
+
+
+
+
+ {data.slice(page * rowsPerPage, (page * rowsPerPage) + rowsPerPage).map(n => (
+
+ {n.name}
+ {n.calories}
+ {n.fat}
+
+ ))}
+ {emptyRows > 0 && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+TbPagination.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TbPagination);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationActions.js b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationActions.js
new file mode 100644
index 0000000..3f56fa0
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationActions.js
@@ -0,0 +1,93 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import FirstPageIcon from '@material-ui/icons/FirstPage';
+import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
+import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
+import LastPageIcon from '@material-ui/icons/LastPage';
+import { IconButton } from '@material-ui/core';
+
+const actionsStyles = theme => ({
+ root: {
+ flexShrink: 0,
+ color: theme.palette.text.secondary,
+ marginLeft: theme.spacing(2.5),
+ },
+});
+
+class TbPaginationActions extends React.Component {
+ handleFirstPageButtonClick = event => {
+ this.props.onChangePage(event, 0);
+ };
+
+ handleBackButtonClick = event => {
+ this.props.onChangePage(event, this.props.page - 1);
+ };
+
+ handleNextButtonClick = event => {
+ this.props.onChangePage(event, this.props.page + 1);
+ };
+
+ handleLastPageButtonClick = event => {
+ this.props.onChangePage(
+ event,
+ Math.max(0, Math.ceil(this.props.count / this.props.rowsPerPage) - 1),
+ );
+ };
+
+ render() {
+ const {
+ classes,
+ count,
+ page,
+ rowsPerPage,
+ theme
+ } = this.props;
+
+ return (
+
+
+ {theme.direction === 'rtl' ? : }
+
+
+ {theme.direction === 'rtl' ? : }
+
+ = Math.ceil(count / rowsPerPage) - 1}
+ aria-label="Next Page"
+ >
+ {theme.direction === 'rtl' ? : }
+
+ = Math.ceil(count / rowsPerPage) - 1}
+ aria-label="Last Page"
+ >
+ {theme.direction === 'rtl' ? : }
+
+
+ );
+ }
+}
+
+TbPaginationActions.propTypes = {
+ classes: PropTypes.object.isRequired,
+ count: PropTypes.number.isRequired,
+ onChangePage: PropTypes.func.isRequired,
+ page: PropTypes.number.isRequired,
+ rowsPerPage: PropTypes.number.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(actionsStyles, { withTheme: true })(
+ TbPaginationActions,
+);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationCustom.js b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationCustom.js
new file mode 100644
index 0000000..49494dc
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Pagination/TbPaginationCustom.js
@@ -0,0 +1,115 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Table, TableBody, TableCell, TablePagination, TableRow, TableFooter, Paper } from '@material-ui/core';
+import TbPaginationActions from './TbPaginationActions';
+
+
+let counter = 0;
+function createData(name, calories, fat) {
+ counter += 1;
+ return {
+ id: counter,
+ name,
+ calories,
+ fat
+ };
+}
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ },
+ table: {
+ minWidth: 500,
+ },
+ tableWrapper: {
+ overflowX: 'auto',
+ },
+});
+
+class TbPaginationCustom extends React.Component {
+ constructor(props, context) {
+ super(props, context);
+
+ this.state = {
+ data: [
+ createData('Cupcake', 305, 3.7),
+ createData('Donut', 452, 25.0),
+ createData('Eclair', 262, 16.0),
+ createData('Frozen yoghurt', 159, 6.0),
+ createData('Gingerbread', 356, 16.0),
+ createData('Honeycomb', 408, 3.2),
+ createData('Ice cream sandwich', 237, 9.0),
+ createData('Jelly Bean', 375, 0.0),
+ createData('KitKat', 518, 26.0),
+ createData('Lollipop', 392, 0.2),
+ createData('Marshmallow', 318, 0),
+ createData('Nougat', 360, 19.0),
+ createData('Oreo', 437, 18.0),
+ ].sort((a, b) => (a.calories < b.calories ? -1 : 1)),
+ page: 0,
+ rowsPerPage: 5,
+ };
+ }
+
+ handleChangePage = (event, page) => {
+ this.setState({ page });
+ };
+
+ handleChangeRowsPerPage = event => {
+ this.setState({ rowsPerPage: event.target.value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { data, rowsPerPage, page } = this.state;
+ const emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - (page * rowsPerPage));
+
+ return (
+
+
+
+
+ {data.slice(page * rowsPerPage, (page * rowsPerPage) + rowsPerPage).map(n => (
+
+
+ {n.name}
+
+ {n.calories}
+ {n.fat}
+
+ ))}
+ {emptyRows > 0 && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+TbPaginationCustom.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(TbPaginationCustom);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/CustomizedTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/CustomizedTooltips.js
new file mode 100644
index 0000000..f0f9111
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/CustomizedTooltips.js
@@ -0,0 +1,125 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Button, Tooltip } from '@material-ui/core';
+
+const styles = theme => ({
+ lightTooltip: {
+ background: theme.palette.common.white,
+ color: theme.palette.text.primary,
+ boxShadow: theme.shadows[1],
+ fontSize: 11,
+ },
+ arrowPopper: {
+ '&[x-placement*="bottom"] $arrowArrow': {
+ top: 0,
+ left: 0,
+ marginTop: '-0.9em',
+ width: '3em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '0 1em 1em 1em',
+ borderColor: `transparent transparent ${theme.palette.grey[700]} transparent`,
+ },
+ },
+ '&[x-placement*="top"] $arrowArrow': {
+ bottom: 0,
+ left: 0,
+ marginBottom: '-0.9em',
+ width: '3em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 0 1em',
+ borderColor: `${theme.palette.grey[700]} transparent transparent transparent`,
+ },
+ },
+ '&[x-placement*="right"] $arrowArrow': {
+ left: 0,
+ marginLeft: '-0.9em',
+ height: '3em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 1em 0',
+ borderColor: `transparent ${theme.palette.grey[700]} transparent transparent`,
+ },
+ },
+ '&[x-placement*="left"] $arrowArrow': {
+ right: 0,
+ marginRight: '-0.9em',
+ height: '3em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 0 1em 1em',
+ borderColor: `transparent transparent transparent ${theme.palette.grey[700]}`,
+ },
+ },
+ },
+ arrowArrow: {
+ position: 'absolute',
+ fontSize: 7,
+ width: '3em',
+ height: '3em',
+ '&::before': {
+ content: '""',
+ margin: 'auto',
+ display: 'block',
+ width: 0,
+ height: 0,
+ borderStyle: 'solid',
+ },
+ },
+});
+
+class CustomizedTooltips extends React.Component {
+ state = {
+ arrowRef: null,
+ };
+
+ handleArrowRef = node => {
+ this.setState({
+ arrowRef: node,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ Add
+
+
+ )}
+ classes={{ popper: classes.arrowPopper }}
+ PopperProps={{
+ popperOptions: {
+ modifiers: {
+ arrow: {
+ enabled: Boolean(this.state.arrowRef),
+ element: this.state.arrowRef,
+ },
+ },
+ },
+ }}
+ >
+
+
+
+ );
+ }
+}
+
+CustomizedTooltips.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CustomizedTooltips);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/DelayTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/DelayTooltips.js
new file mode 100644
index 0000000..786dd4f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/DelayTooltips.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { Button, Tooltip } from '@material-ui/core';
+
+function DelayTooltips() {
+ return (
+
+
+
+ );
+}
+
+export default DelayTooltips;
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PopoverPlayground.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PopoverPlayground.js
new file mode 100644
index 0000000..7878df1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PopoverPlayground.js
@@ -0,0 +1,340 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/prism-light';
+import jsx from 'react-syntax-highlighter/languages/prism/jsx';
+import themeSource from 'react-syntax-highlighter/styles/prism/prism';
+import { green } from '@material-ui/core/colors';
+
+import {
+ FormControl,
+ FormLabel,
+ FormControlLabel,
+ Radio,
+ RadioGroup,
+ Grid,
+ Typography,
+ Button,
+ Popover,
+ Input,
+ InputLabel,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ buttonWrapper: {
+ position: 'relative',
+ marginBottom: theme.spacing(4),
+ },
+ anchor: {
+ backgroundColor: green[500],
+ width: 10,
+ height: 10,
+ borderRadius: '50%',
+ position: 'absolute',
+ },
+ radioAnchor: {
+ color: green[600],
+ '&$checked': {
+ color: green[500],
+ },
+ },
+ checked: {},
+ typography: {
+ margin: theme.spacing(2),
+ },
+});
+
+const inlineStyles = {
+ anchorVertical: {
+ top: {
+ top: -5,
+ },
+ center: {
+ top: 'calc(50% - 5px)',
+ },
+ bottom: {
+ bottom: -5,
+ },
+ },
+ anchorHorizontal: {
+ left: {
+ left: -5,
+ },
+ center: {
+ left: 'calc(50% - 5px)',
+ },
+ right: {
+ right: -5,
+ },
+ },
+};
+
+class PopoverPlayground extends React.Component {
+ state = {
+ open: false,
+ anchorOriginVertical: 'top',
+ anchorOriginHorizontal: 'left',
+ transformOriginVertical: 'top',
+ transformOriginHorizontal: 'left',
+ positionTop: 200, // Just so the popover can be spotted more easily
+ positionLeft: 400, // Same as above
+ anchorReference: 'anchorEl',
+ };
+
+ handleChange = key => (event, value) => {
+ this.setState({
+ [key]: value,
+ });
+ };
+
+ handleNumberInputChange = key => event => {
+ this.setState({
+ [key]: parseInt(event.target.value, 10),
+ });
+ };
+
+ handleClickButton = () => {
+ this.setState({
+ open: true,
+ });
+ };
+
+ handleClose = () => {
+ this.setState({
+ open: false,
+ });
+ };
+
+ anchorEl = null;
+
+ render() {
+ const { classes } = this.props;
+ registerLanguage('jsx', jsx);
+ const {
+ open,
+ anchorOriginVertical,
+ anchorOriginHorizontal,
+ transformOriginVertical,
+ transformOriginHorizontal,
+ positionTop,
+ positionLeft,
+ anchorReference,
+ } = this.state;
+
+ let mode = '';
+
+ if (anchorReference === 'anchorPosition') {
+ mode = `
+ anchorReference="${anchorReference}"
+ anchorPosition={{ top: ${positionTop}, left: ${positionLeft} }}`;
+ }
+
+ const code = `
+
+`;
+
+ const radioAnchorClasses = { root: classes.radioAnchor, checked: classes.checked };
+
+ return (
+
+
+
+
+ {anchorReference === 'anchorEl' && (
+
+ )}
+
+
+
+ The content of the Popover.
+
+
+
+
+ anchorReference
+
+ } label="anchorEl" />
+ }
+ label="anchorPosition"
+ />
+
+
+
+
+
+ anchorPosition.top
+
+
+
+
+ anchorPosition.left
+
+
+
+
+
+ anchorOrigin.vertical
+
+ }
+ label="Top"
+ />
+ }
+ label="Center"
+ />
+ }
+ label="Bottom"
+ />
+
+
+
+
+
+ transformOrigin.vertical
+
+ } label="Top" />
+ }
+ label="Center"
+ />
+ }
+ label="Bottom"
+ />
+
+
+
+
+
+ anchorOrigin.horizontal
+
+ }
+ label="Left"
+ />
+ }
+ label="Center"
+ />
+ }
+ label="Right"
+ />
+
+
+
+
+
+ transformOrigin.horizontal
+
+ } label="Left" />
+ }
+ label="Center"
+ />
+ } label="Right" />
+
+
+
+
+
+ {code}
+
+
+ );
+ }
+}
+
+PopoverPlayground.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(PopoverPlayground);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PositionedTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PositionedTooltips.js
new file mode 100644
index 0000000..336d932
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/PositionedTooltips.js
@@ -0,0 +1,83 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Grid, Button, Tooltip } from '@material-ui/core';
+
+const styles = {
+ root: {
+ width: 500,
+ margin: '0 auto'
+ },
+};
+
+function PositionedTooltips(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+PositionedTooltips.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(PositionedTooltips);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimplePopover.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimplePopover.js
new file mode 100644
index 0000000..23d2462
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimplePopover.js
@@ -0,0 +1,79 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Button, Popover, Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ typography: {
+ margin: theme.spacing(2),
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ textAlign: 'center'
+ },
+ button: {
+ margin: theme.spacing(1),
+ },
+});
+
+class SimplePopover extends React.Component {
+ state = {
+ anchorEl: null,
+ };
+
+ handleClick = event => {
+ this.setState({
+ anchorEl: event.currentTarget,
+ });
+ };
+
+ handleClose = () => {
+ this.setState({
+ anchorEl: null,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { anchorEl } = this.state;
+ return (
+
+
+
+
+
+ The content of the Popover.
+
+
+
+
+ );
+ }
+}
+
+SimplePopover.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimplePopover);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimpleTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimpleTooltips.js
new file mode 100644
index 0000000..0714e6c
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/SimpleTooltips.js
@@ -0,0 +1,116 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import AddIcon from '@material-ui/icons/Add';
+import DeleteIcon from '@material-ui/icons/Delete';
+import { Fab, IconButton, Tooltip, Typography, Grid } from '@material-ui/core';
+
+const styles = theme => ({
+ fab: {
+ margin: theme.spacing(2),
+ },
+ fixed: {
+ position: 'fixed',
+ bottom: theme.spacing(2),
+ right: theme.spacing(3),
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ textAlign: 'center'
+ },
+});
+
+class SimpleTooltips extends React.Component {
+ state = {
+ open: false,
+ };
+
+ handleTooltipClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleTooltipOpen = () => {
+ this.setState({ open: true });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+ Simple Tooltips
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Delayed Tooltips
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+SimpleTooltips.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimpleTooltips);
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TransitionsTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TransitionsTooltips.js
new file mode 100644
index 0000000..7b8adc1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TransitionsTooltips.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import { Button, Tooltip, Fade, Zoom } from '@material-ui/core';
+
+function TransitionsTooltips() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default TransitionsTooltips;
diff --git a/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TriggersTooltips.js b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TriggersTooltips.js
new file mode 100644
index 0000000..bd4db5b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/PopoverTooltip/TriggersTooltips.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import { Grid, Button, Tooltip, ClickAwayListener } from '@material-ui/core';
+
+class TriggersTooltips extends React.Component {
+ state = {
+ open: false,
+ };
+
+ handleTooltipClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleTooltipOpen = () => {
+ this.setState({ open: true });
+ };
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default TriggersTooltips;
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/CircularDeterminate.js b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularDeterminate.js
new file mode 100644
index 0000000..0b1312b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularDeterminate.js
@@ -0,0 +1,69 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { CircularProgress } from '@material-ui/core';
+
+const styles = theme => ({
+ progress: {
+ margin: theme.spacing(2),
+ },
+});
+
+class CircularDeterminate extends React.Component {
+ state = {
+ completed: 0,
+ };
+
+ componentDidMount() {
+ this.timer = setInterval(this.progress, 20);
+ }
+
+ componentWillUnmount() {
+ clearInterval(this.timer);
+ }
+
+ timer;
+
+ progress = () => {
+ const { completed } = this.state;
+ this.setState({ completed: completed === 100 ? 0 : completed + 1 });
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+CircularDeterminate.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CircularDeterminate);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIndeterminate.js b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIndeterminate.js
new file mode 100644
index 0000000..cc37de8
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIndeterminate.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { purple } from '@material-ui/core/colors';
+import { CircularProgress } from '@material-ui/core';
+
+const styles = theme => ({
+ progress: {
+ margin: theme.spacing(2),
+ },
+});
+
+function CircularIndeterminate(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+
+ );
+}
+
+CircularIndeterminate.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CircularIndeterminate);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIntegration.js b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIntegration.js
new file mode 100644
index 0000000..ff19f5c
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularIntegration.js
@@ -0,0 +1,114 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import CheckIcon from '@material-ui/icons/Check';
+import SaveIcon from '@material-ui/icons/Save';
+import { green } from '@material-ui/core/colors';
+
+import { CircularProgress, Button, Fab } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ alignItems: 'center',
+ },
+ wrapper: {
+ margin: theme.spacing(1),
+ position: 'relative',
+ },
+ buttonSuccess: {
+ backgroundColor: green[500],
+ '&:hover': {
+ backgroundColor: green[700],
+ },
+ },
+ fabProgress: {
+ color: green[500],
+ position: 'absolute',
+ top: -6,
+ left: -6,
+ zIndex: 1,
+ },
+ buttonProgress: {
+ color: green[500],
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ marginTop: -12,
+ marginLeft: -12,
+ },
+});
+
+class CircularIntegration extends React.Component {
+ state = {
+ loading: false,
+ success: false,
+ };
+
+ componentWillUnmount() {
+ clearTimeout(this.timer);
+ }
+
+ handleButtonClick = () => {
+ if (!this.state.loading) {
+ this.setState(
+ {
+ success: false,
+ loading: true,
+ },
+ () => {
+ this.timer = setTimeout(() => {
+ this.setState({
+ loading: false,
+ success: true,
+ });
+ }, 2000);
+ },
+ );
+ }
+ };
+
+ timer = undefined;
+
+ render() {
+ const { loading, success } = this.state;
+ const { classes } = this.props;
+ const buttonClassname = classNames({
+ [classes.buttonSuccess]: success,
+ });
+
+ return (
+
+
+
+ {success ? : }
+
+ {loading && }
+
+
+
+ {loading && }
+
+
+ );
+ }
+}
+
+CircularIntegration.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CircularIntegration);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/CircularStatic.js b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularStatic.js
new file mode 100644
index 0000000..bfa931a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/CircularStatic.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { CircularProgress } from '@material-ui/core';
+
+const styles = theme => ({
+ progress: {
+ margin: theme.spacing(2),
+ },
+});
+
+function CircularStatic(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+CircularStatic.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CircularStatic);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/LinearBuffer.js b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearBuffer.js
new file mode 100644
index 0000000..44bca71
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearBuffer.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { LinearProgress } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+class LinearBuffer extends React.Component {
+ state = {
+ completed: 0,
+ buffer: 10,
+ };
+
+ componentDidMount() {
+ this.timer = setInterval(this.progress, 500);
+ }
+
+ componentWillUnmount() {
+ clearInterval(this.timer);
+ }
+
+ timer = null;
+
+ progress = () => {
+ const { completed } = this.state;
+ if (completed > 100) {
+ this.setState({ completed: 0, buffer: 10 });
+ } else {
+ const diff = Math.random() * 10;
+ const diff2 = Math.random() * 10;
+ this.setState({ completed: completed + diff, buffer: completed + diff + diff2 });
+ }
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { completed, buffer } = this.state;
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+LinearBuffer.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LinearBuffer);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/LinearDeterminate.js b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearDeterminate.js
new file mode 100644
index 0000000..08c718d
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearDeterminate.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { LinearProgress } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+class LinearDeterminate extends React.Component {
+ state = {
+ completed: 0,
+ };
+
+ componentDidMount() {
+ this.timer = setInterval(this.progress, 500);
+ }
+
+ componentWillUnmount() {
+ clearInterval(this.timer);
+ }
+
+ timer = null;
+
+ progress = () => {
+ const { completed } = this.state;
+ if (completed === 100) {
+ this.setState({ completed: 0 });
+ } else {
+ const diff = Math.random() * 10;
+ this.setState({ completed: Math.min(completed + diff, 100) });
+ }
+ };
+
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+LinearDeterminate.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LinearDeterminate);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/LinearIndeterminate.js b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearIndeterminate.js
new file mode 100644
index 0000000..de5071a
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearIndeterminate.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { LinearProgress } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+function LinearIndeterminate(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+ );
+}
+
+LinearIndeterminate.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LinearIndeterminate);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/LinearQuery.js b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearQuery.js
new file mode 100644
index 0000000..6e51da7
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearQuery.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { LinearProgress } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+function LinearQuery(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+ );
+}
+
+LinearQuery.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LinearQuery);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/LinearStatic.js b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearStatic.js
new file mode 100644
index 0000000..55ad2a1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/LinearStatic.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { LinearProgress } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+function LinearIndeterminate(props) {
+ const { classes } = props;
+ return (
+
+
+
+
+
+ );
+}
+
+LinearIndeterminate.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LinearIndeterminate);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Progress/ProgressDelay.js b/front/odiparpack/app/containers/UiElements/demos/Progress/ProgressDelay.js
new file mode 100644
index 0000000..6417795
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Progress/ProgressDelay.js
@@ -0,0 +1,105 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Fade, Button, CircularProgress, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ },
+ button: {
+ margin: theme.spacing(2),
+ },
+ placeholder: {
+ height: 40,
+ },
+});
+
+class ProgressDelay extends React.Component {
+ state = {
+ loading: false,
+ query: 'idle',
+ };
+
+ componentWillUnmount() {
+ clearTimeout(this.timer);
+ }
+
+ timer = null;
+
+ handleClickLoading = () => {
+ this.setState({
+ loading: !this.state.loading,
+ });
+ };
+
+ handleClickQuery = () => {
+ clearTimeout(this.timer);
+
+ if (this.state.query !== 'idle') {
+ this.setState({
+ query: 'idle',
+ });
+ return;
+ }
+
+ this.setState({
+ query: 'progress',
+ });
+ this.timer = setTimeout(() => {
+ this.setState({
+ query: 'success',
+ });
+ }, 2e3);
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { loading, query } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+ {query === 'success' ? (
+ Success!
+ ) : (
+
+
+
+ )}
+
+
+
+ );
+ }
+}
+
+ProgressDelay.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ProgressDelay);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AnimatedSlider.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AnimatedSlider.js
new file mode 100644
index 0000000..57fb5e4
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AnimatedSlider.js
@@ -0,0 +1,72 @@
+import React from 'react';
+import Type from 'ba-styles/Typography.scss';
+import Slider from 'react-animated-slider';
+import imgApi from 'ba-api/images';
+import avatarApi from 'ba-api/avatars';
+import 'ba-styles/vendors/react-animated-slider/react-animated-slider.css';
+
+import { Button, Typography, Hidden } from '@material-ui/core';
+
+const content = [
+ {
+ title: 'Vulputate Mollis Ultricies Fermentum Parturient',
+ description:
+ 'Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras justo odio, dapibus ac facilisis.',
+ button: 'Read More',
+ image: imgApi[38],
+ user: 'Luanda Gjokaj',
+ userProfile: avatarApi[1]
+ },
+ {
+ title: 'Tortor Dapibus Commodo Aenean Quam',
+ description:
+ 'Nullam id dolor id nibh ultricies vehicula ut id elit. Cras mattis consectetur purus sit amet fermentum. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Donec sed odio dui.',
+ button: 'Discover',
+ image: imgApi[2],
+ user: 'Erich Behrens',
+ userProfile: avatarApi[8]
+ },
+ {
+ title: 'Phasellus volutpat metus',
+ description:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula.',
+ button: 'Buy now',
+ image: imgApi[28],
+ user: 'Bruno Vizovskyy',
+ userProfile: avatarApi[10]
+ }
+];
+
+const AnimatedSlider = () => (
+
+
+ {content.map((item, index) => (
+
+
+
{item.title}
+
+ {item.description}
+
+
+
+
+
+
+ Posted by
+ {' '}
+ {item.user}
+
+
+
+ ))}
+
+
+);
+
+export default AnimatedSlider;
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AutoplayCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AutoplayCarousel.js
new file mode 100644
index 0000000..59c11ef
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/AutoplayCarousel.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgData from 'ba-api/imgData';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+
+const styles = ({
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+class AutoplayCarousel extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const settings = {
+ dots: true,
+ infinite: true,
+ centerMode: false,
+ speed: 500,
+ autoplaySpeed: 2000,
+ pauseOnHover: true,
+ autoplay: true,
+ slidesToShow: 3,
+ slidesToScroll: 1,
+ cssEase: 'ease-out'
+ };
+ return (
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+ );
+ }
+}
+
+AutoplayCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AutoplayCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/CustomCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/CustomCarousel.js
new file mode 100644
index 0000000..a558d8e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/CustomCarousel.js
@@ -0,0 +1,93 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import ArrowForward from '@material-ui/icons/ArrowForward';
+import ArrowBack from '@material-ui/icons/ArrowBack';
+import imgData from 'ba-api/imgData';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+import { IconButton } from '@material-ui/core';
+
+function SampleNextArrow(props) {
+ const { onClick } = props;
+ return (
+
+
+
+ );
+}
+
+SampleNextArrow.propTypes = {
+ onClick: PropTypes.func,
+};
+
+SampleNextArrow.defaultProps = {
+ onClick: undefined,
+};
+
+function SamplePrevArrow(props) {
+ const { onClick } = props;
+ return (
+
+
+
+ );
+}
+
+SamplePrevArrow.propTypes = {
+ onClick: PropTypes.func,
+};
+
+SamplePrevArrow.defaultProps = {
+ onClick: undefined,
+};
+
+const styles = ({
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+class CustomCarousel extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const settings = {
+ dots: true,
+ infinite: true,
+ centerMode: true,
+ speed: 500,
+ slidesToShow: 3,
+ slidesToScroll: 1,
+ nextArrow: ,
+ prevArrow:
+ };
+ return (
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+ );
+ }
+}
+
+CustomCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CustomCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/MultipleCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/MultipleCarousel.js
new file mode 100644
index 0000000..c8ff743
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/MultipleCarousel.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgData from 'ba-api/imgData';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+
+const styles = ({
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+class MultipleCarousel extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const settings = {
+ dots: true,
+ infinite: true,
+ centerMode: true,
+ speed: 500,
+ slidesToShow: 3,
+ slidesToScroll: 1
+ };
+ return (
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+ );
+ }
+}
+
+MultipleCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(MultipleCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/SingleCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/SingleCarousel.js
new file mode 100644
index 0000000..76158f7
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/SingleCarousel.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgData from 'ba-api/imgData';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+
+import { FormControl, MenuItem, InputLabel, Select } from '@material-ui/core';
+
+const styles = ({
+ root: {
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center'
+ },
+ formControl: {
+ width: '50%',
+ margin: '0 auto'
+ },
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+class SingleCarousel extends React.Component {
+ state = {
+ transition: 'slide'
+ }
+
+ handleChange = event => {
+ this.setState({ [event.target.name]: event.target.value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { transition } = this.state;
+ const settings = {
+ dots: true,
+ fade: this.state.transition === 'fade',
+ };
+ return (
+
+
+ Carousel Transition
+
+
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+
+ );
+ }
+}
+
+SingleCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SingleCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/ThumbnailCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/ThumbnailCarousel.js
new file mode 100644
index 0000000..9860b55
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/ThumbnailCarousel.js
@@ -0,0 +1,90 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+import imgData from 'ba-api/imgData';
+
+import { FormControl, MenuItem, InputLabel, Select } from '@material-ui/core';
+
+const styles = ({
+ root: {
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center'
+ },
+ formControl: {
+ width: '50%',
+ margin: '0 auto'
+ },
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+const getThumb = imgData.map(a => a.thumb);
+
+class ThumbnailCarousel extends React.Component {
+ state = {
+ transition: 'slide'
+ }
+
+ handleChange = event => {
+ this.setState({ [event.target.name]: event.target.value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { transition } = this.state;
+ const settings = {
+ customPaging: (i) => (
+
+
+
+ ),
+ infinite: true,
+ dots: true,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ fade: this.state.transition === 'fade',
+ };
+ return (
+
+
+ Carousel Transition
+
+
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+
+ );
+ }
+}
+
+ThumbnailCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ThumbnailCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/VerticalCarousel.js b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/VerticalCarousel.js
new file mode 100644
index 0000000..36dd7c3
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/SliderCaraousel/VerticalCarousel.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import Slider from 'react-slick';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import imgData from 'ba-api/imgData';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+
+const styles = ({
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ }
+});
+
+class VerticalCarousel extends React.Component {
+ render() {
+ const { classes } = this.props;
+ const settings = {
+ infinite: true,
+ slidesToShow: 2,
+ slidesToScroll: 1,
+ vertical: true,
+ verticalSwiping: true,
+ swipeToSlide: true,
+ };
+ return (
+
+
+ {imgData.map((item, index) => (
+
+

+
+ ))}
+
+
+ );
+ }
+}
+
+VerticalCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(VerticalCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalLinear.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalLinear.js
new file mode 100644
index 0000000..db47ee1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalLinear.js
@@ -0,0 +1,196 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import Type from 'ba-styles/Typography.scss';
+
+import {
+ Stepper,
+ Step,
+ StepLabel,
+ Button,
+ Typography,
+ FormGroup,
+ FormControlLabel,
+ Switch,
+ Divider,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ button: {
+ marginRight: theme.spacing(1),
+ },
+ instructions: {
+ marginTop: theme.spacing(1),
+ marginBottom: theme.spacing(1),
+ },
+});
+
+function getSteps() {
+ return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
+}
+
+function getStepContent(step) {
+ switch (step) {
+ case 0:
+ return 'Select campaign settings...';
+ case 1:
+ return 'What is an ad group anyways?';
+ case 2:
+ return 'This is the bit I really care about!';
+ default:
+ return 'Unknown step';
+ }
+}
+
+class HorizontalLinear extends React.Component {
+ static propTypes = {
+ classes: PropTypes.object.isRequired,
+ };
+
+ state = {
+ activeStep: 0,
+ altLabel: false,
+ skipped: new Set(),
+ };
+
+ isStepOptional = step => (step === 1);
+
+ isStepSkipped(step) {
+ return this.state.skipped.has(step);
+ }
+
+ handleNext = () => {
+ const { activeStep } = this.state;
+ let { skipped } = this.state;
+ if (this.isStepSkipped(activeStep)) {
+ skipped = new Set(skipped.values());
+ skipped.delete(activeStep);
+ }
+ this.setState({
+ activeStep: activeStep + 1,
+ skipped,
+ });
+ };
+
+ handleBack = () => {
+ const { activeStep } = this.state;
+ this.setState({
+ activeStep: activeStep - 1,
+ });
+ };
+
+ handleSkip = () => {
+ const { activeStep } = this.state;
+ if (!this.isStepOptional(activeStep)) {
+ // You probably want to guard against something like this,
+ // it should never occur unless someone's actively trying to break something.
+ throw new Error("You can't skip a step that isn't optional.");
+ }
+ const skipped = new Set(this.state.skipped.values());
+ skipped.add(activeStep);
+ this.setState({
+ activeStep: this.state.activeStep + 1,
+ skipped,
+ });
+ };
+
+ handleReset = () => {
+ this.setState({
+ activeStep: 0,
+ });
+ };
+
+ handleChange = name => event => {
+ this.setState({ [name]: event.target.checked });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const steps = getSteps();
+ const { activeStep, altLabel } = this.state;
+
+ return (
+
+
+
+ )}
+ label="Alternative Design"
+ />
+
+
+
+ {steps.map((label, index) => {
+ const props = {};
+ const labelProps = {};
+ if (this.isStepOptional(index)) {
+ labelProps.optional = Optional;
+ }
+ if (this.isStepSkipped(index)) {
+ props.completed = false;
+ }
+ return (
+
+ {label}
+
+ );
+ })}
+
+
+
+ {activeStep === steps.length ? (
+
+
+ All steps completed - you"re finished
+
+
+
+ ) : (
+
+
{getStepContent(activeStep)}
+
+
+ {this.isStepOptional(activeStep) && (
+
+ )}
+
+
+
+ )}
+
+
+ );
+ }
+}
+
+export default withStyles(styles)(HorizontalLinear);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalNonLinear.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalNonLinear.js
new file mode 100644
index 0000000..3c72df3
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/HorizontalNonLinear.js
@@ -0,0 +1,213 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+
+import {
+ Stepper,
+ Step,
+ StepButton,
+ Button,
+ Divider,
+ FormGroup,
+ FormControlLabel,
+ Switch,
+ Typography,
+} from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ button: {
+ marginRight: theme.spacing(1),
+ },
+ completed: {
+ display: 'inline-block',
+ },
+ instructions: {
+ marginTop: theme.spacing(1),
+ marginBottom: theme.spacing(1),
+ },
+ stepItem: {
+ whiteSpace: 'inherit'
+ }
+});
+
+function getSteps() {
+ return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
+}
+
+function getStepContent(step) {
+ switch (step) {
+ case 0:
+ return 'Step 1: Select campaign settings...';
+ case 1:
+ return 'Step 2: What is an ad group anyways?';
+ case 2:
+ return 'Step 3: This is the bit I really care about!';
+ default:
+ return 'Unknown step';
+ }
+}
+
+class HorizontalNonLinear extends React.Component {
+ state = {
+ activeStep: 0,
+ altLabel: false,
+ completed: {},
+ };
+
+ completedSteps() {
+ return Object.keys(this.state.completed).length;
+ }
+
+ totalSteps = () => (
+ getSteps().length
+ );
+
+ isLastStep() {
+ return this.state.activeStep === this.totalSteps() - 1;
+ }
+
+ allStepsCompleted() {
+ return this.completedSteps() === this.totalSteps();
+ }
+
+ handleNext = () => {
+ let activeStep;
+
+ if (this.isLastStep() && !this.allStepsCompleted()) {
+ // It's the last step, but not all steps have been completed,
+ // find the first step that has been completed
+ const steps = getSteps();
+ activeStep = steps.findIndex((step, i) => !(i in this.state.completed));
+ } else {
+ activeStep = this.state.activeStep + 1;
+ }
+ this.setState({
+ activeStep,
+ });
+ };
+
+ handleBack = () => {
+ const { activeStep } = this.state;
+ this.setState({
+ activeStep: activeStep - 1,
+ });
+ };
+
+ handleStep = step => () => {
+ this.setState({
+ activeStep: step,
+ });
+ };
+
+ handleComplete = () => {
+ const { completed } = this.state;
+ completed[this.state.activeStep] = true;
+ this.setState({
+ completed,
+ });
+ this.handleNext();
+ };
+
+ handleReset = () => {
+ this.setState({
+ activeStep: 0,
+ completed: {},
+ });
+ };
+
+ handleChange = name => event => {
+ this.setState({ [name]: event.target.checked });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const steps = getSteps();
+ const { activeStep, altLabel } = this.state;
+
+ return (
+
+
+
+ )}
+ label="Alternative Design"
+ />
+
+
+
+ {steps.map((label, index) => (
+
+
+ {label}
+
+
+ ))}
+
+
+
+ {this.allStepsCompleted() ? (
+
+
+ All steps completed - you"re finished
+
+
+
+ ) : (
+
+
{getStepContent(activeStep)}
+
+
+
+ {activeStep !== steps.length
+ && (this.state.completed[this.state.activeStep] ? (
+
+ Step
+ {' '}
+ {activeStep + 1}
+ {' '}
+already completed
+
+ ) : (
+
+ ))}
+
+
+ )}
+
+
+ );
+ }
+}
+
+HorizontalNonLinear.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(HorizontalNonLinear);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/MobileSteppers.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/MobileSteppers.js
new file mode 100644
index 0000000..c9d7cf1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/MobileSteppers.js
@@ -0,0 +1,116 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
+import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
+
+import { MobileStepper, Button, Grid, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ [theme.breakpoints.up('sm')]: {
+ width: 400,
+ margin: '0 auto'
+ },
+ flexGrow: 1,
+ },
+ title: {
+ textAlign: 'center',
+ margin: `${theme.spacing(4)}px 0 ${theme.spacing(2)}px`,
+ },
+});
+
+class MobileSteppers extends React.Component {
+ state = {
+ activeStepDots: 0,
+ activeStepLine: 0,
+ };
+
+ handleNextDots = () => {
+ this.setState({
+ activeStepDots: this.state.activeStepDots + 1,
+ });
+ };
+
+ handleBackDots = () => {
+ this.setState({
+ activeStepDots: this.state.activeStepDots - 1,
+ });
+ };
+
+ handleNextLine = () => {
+ this.setState({
+ activeStepLine: this.state.activeStepLine + 1,
+ });
+ };
+
+ handleBackLine = () => {
+ this.setState({
+ activeStepLine: this.state.activeStepLine - 1,
+ });
+ };
+
+ render() {
+ const { classes, theme } = this.props;
+
+ return (
+
+
+
+ Mobile Stepper - Dots
+
+
+ Next
+ {theme.direction === 'rtl' ? : }
+
+ )}
+ backButton={(
+
+ )}
+ />
+
+
+
+ Mobile Stepper - Progress
+
+
+ Next
+ {theme.direction === 'rtl' ? : }
+
+ )}
+ backButton={(
+
+ )}
+ />
+
+
+ );
+ }
+}
+
+MobileSteppers.propTypes = {
+ classes: PropTypes.object.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles, { withTheme: true })(MobileSteppers);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperCarousel.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperCarousel.js
new file mode 100644
index 0000000..0f127b3
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperCarousel.js
@@ -0,0 +1,187 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
+import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
+import SwipeableViews from 'react-swipeable-views';
+import imgApi from 'ba-api/images';
+
+import { MobileStepper, Paper, Typography, Button, Grid } from '@material-ui/core';
+
+const tutorialSteps = [
+ {
+ label: 'How to be happy :)',
+ imgPath: imgApi[45],
+ },
+ {
+ label: '1. Work with something that you like, like…',
+ imgPath: imgApi[33],
+ },
+ {
+ label: '2. Keep your friends close to you and hangout with them',
+ imgPath: imgApi[14],
+ },
+ {
+ label: '3. Travel everytime that you have a chance',
+ imgPath: imgApi[9],
+ },
+ {
+ label: '4. And contribute to Material-UI :D',
+ imgPath: imgApi[44],
+ },
+];
+
+const styles = theme => ({
+ root: {
+ [theme.breakpoints.up('sm')]: {
+ width: 400,
+ },
+ flexGrow: 1,
+ },
+ header: {
+ textAlign: 'center',
+ height: 50,
+ paddingLeft: theme.spacing(4),
+ marginBottom: 20,
+ backgroundColor: theme.palette.background.default,
+ },
+ img: {
+ height: 255,
+ maxWidth: 400,
+ overflow: 'hidden',
+ width: '100%',
+ margin: '0 auto'
+ },
+ figure: {
+ maxWidth: 400,
+ overflow: 'hidden',
+ margin: '0 auto'
+ },
+ mobileStepper: {
+ [theme.breakpoints.up('sm')]: {
+ width: 400,
+ },
+ margin: '0 auto',
+ textAlign: 'center'
+ }
+});
+
+class StepperCarousel extends React.Component {
+ state = {
+ activeStep: 0,
+ activeStepSwipe: 0,
+ };
+
+ handleNext = () => {
+ this.setState(prevState => ({
+ activeStep: prevState.activeStep + 1,
+ }));
+ };
+
+ handleBack = () => {
+ this.setState(prevState => ({
+ activeStep: prevState.activeStep - 1,
+ }));
+ };
+
+ handleNextSwipe = () => {
+ this.setState(prevState => ({
+ activeStepSwipe: prevState.activeStepSwipe + 1,
+ }));
+ };
+
+ handleBackSwipe = () => {
+ this.setState(prevState => ({
+ activeStepSwipe: prevState.activeStepSwipe - 1,
+ }));
+ };
+
+ handleStepChangeSwipe = activeStepSwipe => {
+ this.setState({ activeStepSwipe });
+ };
+
+ render() {
+ const { classes, theme } = this.props;
+ const { activeStep, activeStepSwipe } = this.state;
+
+ const maxSteps = tutorialSteps.length;
+ const maxStepsSwipe = tutorialSteps.length;
+
+ return (
+
+
+
+ {tutorialSteps[activeStep].label}
+
+
+
+ Next
+ {theme.direction === 'rtl' ? : }
+
+ )}
+ backButton={(
+
+ )}
+ />
+
+
+
+ {tutorialSteps[activeStepSwipe].label}
+
+
+ {tutorialSteps.map((step, index) => (
+
+

+
+ ))}
+
+
+ Next
+ {theme.direction === 'rtl' ? : }
+
+ )}
+ backButton={(
+
+ )}
+ />
+
+
+ );
+ }
+}
+
+StepperCarousel.propTypes = {
+ classes: PropTypes.object.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles, { withTheme: true })(StepperCarousel);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperError.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperError.js
new file mode 100644
index 0000000..85630a1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/StepperError.js
@@ -0,0 +1,178 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Stepper, Step, StepLabel, Button, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '100%',
+ },
+ button: {
+ marginRight: theme.spacing(1),
+ },
+ instructions: {
+ marginTop: theme.spacing(1),
+ marginBottom: theme.spacing(1),
+ },
+});
+
+function getSteps() {
+ return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
+}
+
+function getStepContent(step) {
+ switch (step) {
+ case 0:
+ return 'Select campaign settings...';
+ case 1:
+ return 'What is an ad group anyways?';
+ case 2:
+ return 'This is the bit I really care about!';
+ default:
+ return 'Unknown step';
+ }
+}
+
+class StepperError extends React.Component {
+ static propTypes = {
+ classes: PropTypes.object.isRequired,
+ };
+
+ state = {
+ activeStep: 0,
+ skipped: new Set(),
+ };
+
+ isStepOptional = step => (
+ step === 1
+ );
+
+ isStepSkipped(step) {
+ return this.state.skipped.has(step);
+ }
+
+ isStepFailed = step => (
+ step === 1
+ );
+
+ handleNext = () => {
+ const { activeStep } = this.state;
+ let { skipped } = this.state;
+ if (this.isStepSkipped(activeStep)) {
+ skipped = new Set(skipped.values());
+ skipped.delete(activeStep);
+ }
+ this.setState({
+ activeStep: activeStep + 1,
+ skipped,
+ });
+ };
+
+ handleBack = () => {
+ const { activeStep } = this.state;
+ this.setState({
+ activeStep: activeStep - 1,
+ });
+ };
+
+ handleSkip = () => {
+ const { activeStep } = this.state;
+ if (!this.isStepOptional(activeStep)) {
+ // You probably want to guard against something like this,
+ // it should never occur unless someone's actively trying to break something.
+ throw new Error("You can't skip a step that isn't optional.");
+ }
+ const skipped = new Set(this.state.skipped.values());
+ skipped.add(activeStep);
+ this.setState({
+ activeStep: this.state.activeStep + 1,
+ skipped,
+ });
+ };
+
+ handleReset = () => {
+ this.setState({
+ activeStep: 0,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const steps = getSteps();
+ const { activeStep } = this.state;
+
+ return (
+
+
+ {steps.map((label, index) => {
+ const props = {};
+ const labelProps = {};
+ if (this.isStepOptional(index)) {
+ labelProps.optional = (
+
+ Alert message
+
+ );
+ }
+ if (this.isStepFailed(index)) {
+ labelProps.error = true;
+ }
+ if (this.isStepSkipped(index)) {
+ props.completed = false;
+ }
+ return (
+
+ {label}
+
+ );
+ })}
+
+
+ {activeStep === steps.length ? (
+
+
+ All steps completed - you"re finished
+
+
+
+ ) : (
+
+
{getStepContent(activeStep)}
+
+
+ {this.isStepOptional(activeStep) && (
+
+ )}
+
+
+
+ )}
+
+
+ );
+ }
+}
+
+export default withStyles(styles)(StepperError);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Steppers/VerticalStepper.js b/front/odiparpack/app/containers/UiElements/demos/Steppers/VerticalStepper.js
new file mode 100644
index 0000000..5a2314b
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Steppers/VerticalStepper.js
@@ -0,0 +1,120 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Stepper, Step, StepLabel, StepContent, Button, Paper, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: '90%',
+ },
+ button: {
+ marginTop: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ },
+ actionsContainer: {
+ marginBottom: theme.spacing(2),
+ },
+ resetContainer: {
+ padding: theme.spacing(3),
+ },
+});
+
+function getSteps() {
+ return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
+}
+
+function getStepContent(step) {
+ switch (step) {
+ case 0:
+ return `For each ad campaign that you create, you can control how much
+ you're willing to spend on clicks and conversions, which networks
+ and geographical locations you want your ads to show on, and more.`;
+ case 1:
+ return 'An ad group contains one or more ads which target a shared set of keywords.';
+ case 2:
+ return `Try out different ad text to see what brings in the most customers,
+ and learn how to enhance your ads using features like ad extensions.
+ If you run into any problems with your ads, find out how to tell if
+ they're running and how to resolve approval issues.`;
+ default:
+ return 'Unknown step';
+ }
+}
+
+class VerticalStepper extends React.Component {
+ state = {
+ activeStep: 0,
+ };
+
+ handleNext = () => {
+ this.setState({
+ activeStep: this.state.activeStep + 1,
+ });
+ };
+
+ handleBack = () => {
+ this.setState({
+ activeStep: this.state.activeStep - 1,
+ });
+ };
+
+ handleReset = () => {
+ this.setState({
+ activeStep: 0,
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const steps = getSteps();
+ const { activeStep } = this.state;
+
+ return (
+
+
+ {steps.map((label, index) => (
+
+ {label}
+
+ {getStepContent(index)}
+
+
+
+
+
+
+
+
+ ))}
+
+ {activeStep === steps.length && (
+
+ All steps completed - you"re finished
+
+
+ )}
+
+ );
+ }
+}
+
+VerticalStepper.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(VerticalStepper);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/BottomNav.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/BottomNav.js
new file mode 100644
index 0000000..f3aa033
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/BottomNav.js
@@ -0,0 +1,82 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import RestoreIcon from '@material-ui/icons/Restore';
+import FavoriteIcon from '@material-ui/icons/Favorite';
+import LocationOnIcon from '@material-ui/icons/LocationOn';
+
+import { Typography, Grid, BottomNavigation, BottomNavigationAction, Icon } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ width: 'auto',
+ },
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class BottomNav extends React.Component {
+ state = {
+ value: 0,
+ value2: 'recents',
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ handleChange2 = (event, value2) => {
+ this.setState({ value2 });
+ };
+
+
+ render() {
+ const { classes } = this.props;
+ const { value, value2 } = this.state;
+
+ return (
+
+
+ With Label
+
+
+ } />
+ } />
+ } />
+
+
+
+
+ Without Label
+
+
+ } />
+ } />
+ } />
+ folder} />
+
+
+
+
+ );
+ }
+}
+
+BottomNav.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(BottomNav);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/CenteredTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/CenteredTabs.js
new file mode 100644
index 0000000..00a285e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/CenteredTabs.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Paper, Tabs, Tab } from '@material-ui/core';
+
+const styles = {
+ root: {
+ flexGrow: 1,
+ },
+};
+
+class CenteredTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}
+
+CenteredTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CenteredTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/CustomTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/CustomTabs.js
new file mode 100644
index 0000000..96fd136
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/CustomTabs.js
@@ -0,0 +1,101 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Tabs, Tab, Typography } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.paper,
+ },
+ tabsRoot: {
+ borderBottom: '1px solid #e8e8e8',
+ },
+ tabsIndicator: {
+ backgroundColor: '#1890ff',
+ },
+ tabRoot: {
+ textTransform: 'initial',
+ minWidth: 64,
+ [theme.breakpoints.up('sm')]: {
+ minWidth: 72,
+ },
+ fontWeight: theme.typography.fontWeightRegular,
+ marginRight: theme.spacing(4),
+ fontFamily: [
+ '-apple-system',
+ 'BlinkMacSystemFont',
+ '"Segoe UI"',
+ 'Roboto',
+ '"Helvetica Neue"',
+ 'Arial',
+ 'sans-serif',
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ ].join(','),
+ '&:hover': {
+ color: '#40a9ff',
+ opacity: 1,
+ },
+ '&$tabSelected': {
+ color: '#1890ff',
+ fontWeight: theme.typography.fontWeightMedium,
+ },
+ '&:focus': {
+ color: '#40a9ff',
+ },
+ },
+ tabSelected: {},
+ typography: {
+ padding: theme.spacing(3),
+ },
+});
+
+class CustomTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { value } = this.state;
+
+ return (
+
+
+
+
+
+
+ powered by Material-UI
+
+ );
+ }
+}
+
+CustomTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CustomTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/DisabledTab.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/DisabledTab.js
new file mode 100644
index 0000000..17808a1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/DisabledTab.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Paper, Tabs, Tab } from '@material-ui/core';
+
+class DisabledTab extends React.Component {
+ state = {
+ value: 2,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default DisabledTab;
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/FixedTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/FixedTabs.js
new file mode 100644
index 0000000..f64240f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/FixedTabs.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import SwipeableViews from 'react-swipeable-views';
+import { AppBar, Tabs, Tab, Typography } from '@material-ui/core';
+
+function TabContainer({ children, dir }) {
+ return (
+
+ {children}
+
+ );
+}
+
+TabContainer.propTypes = {
+ children: PropTypes.node.isRequired,
+ dir: PropTypes.string.isRequired,
+};
+
+const styles = theme => ({
+ root: {
+ backgroundColor: theme.palette.background.paper,
+ [theme.breakpoints.up('sm')]: {
+ width: 500,
+ },
+ margin: '10px auto'
+ },
+});
+
+class FixedTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ handleChangeIndex = index => {
+ this.setState({ value: index });
+ };
+
+ render() {
+ const { classes, theme } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+
+ Item One
+ Item Two
+ Item Three
+
+
+ );
+ }
+}
+
+FixedTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles, { withTheme: true })(FixedTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/IconTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/IconTabs.js
new file mode 100644
index 0000000..ff97d16
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/IconTabs.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import PhoneIcon from '@material-ui/icons/Phone';
+import FavoriteIcon from '@material-ui/icons/Favorite';
+import PersonPinIcon from '@material-ui/icons/PersonPin';
+import { Paper, Grid, Tabs, Tab, Typography } from '@material-ui/core';
+
+export default class IconTabs extends React.Component {
+ state = {
+ value: 0,
+ value2: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ handleChange2 = (event, value2) => {
+ this.setState({ value2 });
+ };
+
+ render() {
+ return (
+
+
+
+ Without Text
+
+
+ } />
+ } />
+ } />
+
+
+
+
+ With Text
+
+
+ } label="RECENTS" />
+ } label="FAVORITES" />
+ } label="NEARBY" />
+
+
+
+
+
+ );
+ }
+}
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/LongTextTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/LongTextTabs.js
new file mode 100644
index 0000000..724ac03
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/LongTextTabs.js
@@ -0,0 +1,59 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { AppBar, Tabs, Tab, Typography } from '@material-ui/core';
+
+function TabContainer(props) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+TabContainer.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.paper,
+ },
+});
+
+class LongTextTabs extends React.Component {
+ state = {
+ value: 'one',
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { value } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+ {value === 'one' &&
Item One}
+ {value === 'two' &&
Item Two}
+ {value === 'three' &&
Item Three}
+
+ );
+ }
+}
+
+LongTextTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(LongTextTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollIconTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollIconTabs.js
new file mode 100644
index 0000000..98f52d2
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollIconTabs.js
@@ -0,0 +1,82 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import PhoneIcon from '@material-ui/icons/Phone';
+import FavoriteIcon from '@material-ui/icons/Favorite';
+import PersonPinIcon from '@material-ui/icons/PersonPin';
+import HelpIcon from '@material-ui/icons/Help';
+import ShoppingBasket from '@material-ui/icons/ShoppingBasket';
+import ThumbDown from '@material-ui/icons/ThumbDown';
+import ThumbUp from '@material-ui/icons/ThumbUp';
+import { AppBar, Tabs, Tab, Typography } from '@material-ui/core';
+
+function TabContainer(props) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+TabContainer.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ width: '100%',
+ backgroundColor: theme.palette.background.paper,
+ },
+});
+
+class ScrollIconTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { value } = this.state;
+
+ return (
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+ {value === 0 &&
Item One}
+ {value === 1 &&
Item Two}
+ {value === 2 &&
Item Three}
+ {value === 3 &&
Item Four}
+ {value === 4 &&
Item Five}
+ {value === 5 &&
Item Six}
+ {value === 6 &&
Item Seven}
+
+ );
+ }
+}
+
+ScrollIconTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ScrollIconTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollTabs.js
new file mode 100644
index 0000000..f7f9477
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/ScrollTabs.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { AppBar, Tabs, Tab, Typography } from '@material-ui/core';
+
+function TabContainer(props) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+TabContainer.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ width: '100%',
+ backgroundColor: theme.palette.background.paper,
+ },
+});
+
+class ScrollTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { value } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {value === 0 &&
Item One}
+ {value === 1 &&
Item Two}
+ {value === 2 &&
Item Three}
+ {value === 3 &&
Item Four}
+ {value === 4 &&
Item Five}
+ {value === 5 &&
Item Six}
+ {value === 6 &&
Item Seven}
+
+ );
+ }
+}
+
+ScrollTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ScrollTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tabs/SimpleTabs.js b/front/odiparpack/app/containers/UiElements/demos/Tabs/SimpleTabs.js
new file mode 100644
index 0000000..fd791cc
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tabs/SimpleTabs.js
@@ -0,0 +1,59 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { AppBar, Tabs, Tab, Typography } from '@material-ui/core';
+
+function TabContainer(props) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+TabContainer.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ backgroundColor: theme.palette.background.paper,
+ },
+});
+
+class SimpleTabs extends React.Component {
+ state = {
+ value: 0,
+ };
+
+ handleChange = (event, value) => {
+ this.setState({ value });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { value } = this.state;
+
+ return (
+
+
+
+
+
+
+
+
+ {value === 0 &&
Item One}
+ {value === 1 &&
Item Two}
+ {value === 2 &&
Item Three}
+
+ );
+ }
+}
+
+SimpleTabs.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(SimpleTabs);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tags/ArrayTags.js b/front/odiparpack/app/containers/UiElements/demos/Tags/ArrayTags.js
new file mode 100644
index 0000000..921a668
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tags/ArrayTags.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import TagFacesIcon from '@material-ui/icons/TagFaces';
+
+import { Avatar, Chip, Paper } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ justifyContent: 'center',
+ flexWrap: 'wrap',
+ padding: theme.spacing(0.5),
+ },
+ chip: {
+ margin: theme.spacing(0.5),
+ },
+});
+
+class ArrayTags extends React.Component {
+ state = {
+ chipData: [
+ { key: 0, label: 'Angular' },
+ { key: 1, label: 'jQuery' },
+ { key: 2, label: 'Polymer' },
+ { key: 3, label: 'React' },
+ { key: 4, label: 'Vue.js' },
+ ],
+ };
+
+ handleDelete = data => () => {
+ if (data.label === 'React') {
+ alert('Why would you want to delete React?! :)'); // eslint-disable-line no-alert
+ return;
+ }
+
+ const chipData = [...this.state.chipData];
+ const chipToDelete = chipData.indexOf(data);
+ chipData.splice(chipToDelete, 1);
+ this.setState({ chipData });
+ };
+
+ render() {
+ const { classes } = this.props;
+
+ return (
+
+ {this.state.chipData.map(data => {
+ let avatar = null;
+
+ if (data.label === 'React') {
+ avatar = (
+
+
+
+ );
+ }
+
+ return (
+
+ );
+ })}
+
+ );
+ }
+}
+
+ArrayTags.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ArrayTags);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Tags/BasicTags.js b/front/odiparpack/app/containers/UiElements/demos/Tags/BasicTags.js
new file mode 100644
index 0000000..f2e3693
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Tags/BasicTags.js
@@ -0,0 +1,72 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import FaceIcon from '@material-ui/icons/Face';
+import DoneIcon from '@material-ui/icons/Done';
+
+import { Avatar, Chip } from '@material-ui/core';
+
+const styles = theme => ({
+ root: {
+ display: 'flex',
+ justifyContent: 'center',
+ flexWrap: 'wrap',
+ },
+ chip: {
+ margin: theme.spacing(1),
+ },
+});
+
+function handleDelete() {
+ alert('You clicked the delete icon.'); // eslint-disable-line no-alert
+}
+
+function handleClick() {
+ alert('You clicked the Chip.'); // eslint-disable-line no-alert
+}
+
+function BasicTags(props) {
+ const { classes } = props;
+ return (
+
+
+ MB}
+ label="Clickable Tag"
+ onClick={handleClick}
+ className={classes.chip}
+ color="primary"
+ />
+ }
+ label="Deletable Tag"
+ onDelete={handleDelete}
+ className={classes.chip}
+ />
+
+
+
+ )}
+ label="Clickable Deletable Tag"
+ onClick={handleClick}
+ onDelete={handleDelete}
+ className={classes.chip}
+ />
+ }
+ />
+
+ );
+}
+
+BasicTags.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(BasicTags);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/AlignTypo.js b/front/odiparpack/app/containers/UiElements/demos/Typography/AlignTypo.js
new file mode 100644
index 0000000..38088a9
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/AlignTypo.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import Type from 'ba-styles/Typography.scss';
+import { Typography, Divider } from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class AlignTypo extends React.Component {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+ Align center: Nullam in
+ tortor
+ ligula
+
+
+
+ Align Left
+
+
+ Align Right
+
+
+
Justify Align
+
+ Vestibulum faucibus eget erat eget pretium. Donec commodo convallis ligula, eget suscipit orci. Suspendisse potenti.
+ Nulla eget lobortis lacus. Aliquam venenatis magna et odio lobortis maximus. Nullam in tortor ligula. Proin maximus risus nunc, eu aliquam nibh tempus a. Interdum et malesuada fames ac ante ipsum primis in faucibus.
+
+
+ );
+ }
+}
+
+AlignTypo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(AlignTypo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/ColouredTypo.js b/front/odiparpack/app/containers/UiElements/demos/Typography/ColouredTypo.js
new file mode 100644
index 0000000..b7b1516
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/ColouredTypo.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import Type from 'ba-styles/Typography.scss';
+import { Typography } from '@material-ui/core';
+
+class ColouredTypo extends React.Component {
+ render() {
+ return (
+
+
+ Ut sed eros finibus
+
+
+ Nulla eget lobortis lacus. Aliquam venenatis magna et odio lobortis maximus.
+
+
+ Aliquam nec ex aliquet
+
+
+ Aenean facilisis vitae purus facilisis semper
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sed urna in justo euismod condimentum.
+
+
+ Vivamus et luctus mauris. Maecenas nisl libero, tincidunt id odio id, feugiat vulputate quam.
+
+
+ Curabitur egestas consequat lorem, vel fermentum augue porta id.
+
+
+ );
+ }
+}
+
+export default ColouredTypo;
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/GeneralTypo.js b/front/odiparpack/app/containers/UiElements/demos/Typography/GeneralTypo.js
new file mode 100644
index 0000000..6a1079f
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/GeneralTypo.js
@@ -0,0 +1,139 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { withStyles } from '@material-ui/core/styles';
+import Type from 'ba-styles/Typography.scss';
+import { Typography, Divider } from '@material-ui/core';
+
+const background = {
+ width: '100%',
+ maxWidth: 500,
+ background:
+ 'transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAICAYAAAA4GpVBAAAMKGlDQ1BJQ0MgUHJvZmlsZQAASMetl3dUU8kex+eWJCQktEAoUkJvovQqNbQIAlIFGyEJJJQYEoKKHRUVWAsqFqzoqoiiawFkURELtkWx9wUVFGVdLNhQeZME0PW998c75805c+dzfvc3v/n+7p2ZewcA9RiOWJyNagCQI8qTxIYFMSckpzBJHYACMKAFrIANhysVB8bERAJYhtp/lve3ACJvrzvIY4H/rWjy+FIuAEgM5DSelJsD+QgAuDtXLMkDgNAD7ebT88SQiVAl0JZAgZAt5JyhZE85pyk5UuETH8uCnAqACpXDkWQAoCbXxcznZsA4aqWQHUU8oQhyI2Q/roDDg/wF8sicnGmQ1W0g26T9ECfjHzHThmNyOBnDrMxFUVSChVJxNmcm+H+XnGzZ0BjmsFIFkvBYec7y55Y1LULOVMjnRWlR0ZC1IN8Q8hT+cu4SyMITBv0/cqUs+MwAAwCUyuMER0A2hGwmy0oIHGQ/jkTRF/qjKQWC+CRlfFQkmRY7GB8tEGVHRQ7GKRXw2UNcyZeGxA35pAtD2ZDhO0TrhXns+MGY5/OFiVGQ1SA/kGbFRQz2fVEgYEUNjyWLlWuG7xwDOdKhXDCLdElorNIfcxcI2VGD9sg8QXy4si82hctRaNCDnMmXTogc0sPjB4co9WCFfFHCoE6sTJwXFDvov1OcHTPojzXys8PkdjPIrdL8uKG+vXlwsilzwUEmZ2yMclxcW5wXE6/UhjNBJGCBYMAEMljTwDSQCYStPXU9YOhOKOAACcgAfOAwaBnqkaS4I4LXOFAA/oLEB9LhfkGKu3yQD+1fh63KqwNIV9zNV/TIAl2Qc3AD3A/3wSPhNQBWZ9wT9xrqx1QfGpUYQgwmhhNDibZThYWSn+IyARdmkA2rBETAlg+zkmsQDWn/HofQRWgjPCbcJLQT7oJE8BT6Cf8tw+/RhMO2caAdRg0dzC7tx+xwK6jaDQ/CfaF+qB1n4AbAAXeFmQTi/jA3N2j9/tT+k3bZkGqyIxkl65IDyDY/+6nZqbkN95Hn9qNOpa604UxYw3d+Ho31Q2482Eb87IktxQ5jLdgp7ALWiNUBJnYSq8cuY8flPDw3nirmxtBosQo9WTCOcMjHsdqx2/HLT2NzBseXKN4/yOPPyJMvHNY08UyJMEOQxwyEuzWfyRZxR41kOjs6eQAg3/uVW8tbhmJPRxgXv9sK3wHgyxsYGGj8bouEa/LIYgAoXd9t1ifgctYF4HwJVybJV9pw+YUAvyrqcKXoA2O4d9nAjJyBO/ABASAEjAXRIB4kgynwOQtADlQ9HcwGC0ARKAErwVqwEWwFO8AesB8cAnWgEZwC58AlcBXcBPfhXOkEL0EveA/6EQQhITSEjugjJoglYo84I56IHxKCRCKxSDKSimQgIkSGzEYWIiVIGbIR2Y5UIb8hx5BTyAWkDbmLdCDdyBvkM4qhVFQbNUKt0NGoJxqIRqDx6GQ0A81FC9BF6HJ0PVqJ7kNr0VPoJfQm2o6+RPswgKliDMwUc8A8MRYWjaVg6ZgEm4sVY+VYJVaDNcA3fR1rx3qwTzgRp+NM3AHO13A8AefiufhcvBTfiO/Ba/Ez+HW8A+/FvxFoBEOCPcGbwCZMIGQQphOKCOWEXYSjhLNwTXUS3hOJRAbRmugB12oyMZM4i1hK3Ew8QGwithGfEPtIJJI+yZ7kS4omcUh5pCLSBtI+0knSNVIn6aOKqoqJirNKqEqKikilUKVcZa/KCZVrKs9U+skaZEuyNzmazCPPJK8g7yQ3kK+QO8n9FE2KNcWXEk/JpCygrKfUUM5SHlDeqqqqmql6qY5XFarOV12velD1vGqH6ieqFtWOyqJOosqoy6m7qU3Uu9S3NBrNihZAS6Hl0ZbTqminaY9oH9XoaqPU2Go8tXlqFWq1atfUXqmT1S3VA9WnqBeol6sfVr+i3qNB1rDSYGlwNOZqVGgc07it0adJ13TSjNbM0SzV3Kt5QfO5FknLSitEi6e1SGuH1mmtJ3SMbk5n0bn0hfSd9LP0Tm2itrU2WztTu0R7v3ardq+Olo6rTqLODJ0KneM67QyMYcVgM7IZKxiHGLcYn3WNdAN1+brLdGt0r+l+0BuhF6DH1yvWO6B3U++zPlM/RD9Lf5V+nf5DA9zAzmC8wXSDLQZnDXpGaI/wGcEdUTzi0Ih7hqihnWGs4SzDHYaXDfuMjI3CjMRGG4xOG/UYM4wDjDON1xifMO42oZv4mQhN1picNHnB1GEGMrOZ65lnmL2mhqbhpjLT7aatpv1m1mYJZoVmB8wemlPMPc3TzdeYN5v3WphYjLOYbVFtcc+SbOlpKbBcZ9li+cHK2irJaolVndVzaz1rtnWBdbX1Axuajb9Nrk2lzQ1boq2nbZbtZturdqidm53ArsLuij1q724vtN9s3zaSMNJrpGhk5cjbDlSHQId8h2qHjlGMUZGjCkfVjXo12mJ0yuhVo1tGf3N0c8x23Ol430nLaaxToVOD0xtnO2euc4XzDReaS6jLPJd6l9eu9q581y2ud9zobuPclrg1u31193CXuNe4d3tYeKR6bPK47antGeNZ6nnei+AV5DXPq9Hrk7e7d573Ie+/fRx8snz2+jwfYz2GP2bnmCe+Zr4c3+2+7X5Mv1S/bX7t/qb+HP9K/8cB5gG8gF0BzwJtAzMD9wW+CnIMkgQdDfrA8mbNYTUFY8FhwcXBrSFaIQkhG0MehZqFZoRWh/aGuYXNCmsKJ4RHhK8Kv802YnPZVezesR5j54w9E0GNiIvYGPE40i5SEtkwDh03dtzqcQ+iLKNEUXXRIJodvTr6YYx1TG7M7+OJ42PGV4zvinWKnR3bEkePmxq3N+59fFD8ivj7CTYJsoTmRPXESYlViR+SgpPKktonjJ4wZ8KlZINkYXJ9CiklMWVXSt/EkIlrJ3ZOcptUNOnWZOvJMyZfmGIwJXvK8anqUzlTD6cSUpNS96Z+4URzKjl9aey0TWm9XBZ3HfclL4C3htfN9+WX8Z+l+6aXpT/P8M1YndEt8BeUC3qELOFG4evM8MytmR+yorN2Zw1kJ2UfyFHJSc05JtISZYnOTDOeNmNam9heXCRuz/XOXZvbK4mQ7JIi0snS+jxt+JN9WWYjWyzryPfLr8j/OD1x+uEZmjNEMy7PtJu5bOazgtCCX2fhs7izmmebzl4wu2NO4Jztc5G5aXOb55nPWzSvc37Y/D0LKAuyFvxR6FhYVvhuYdLChkVGi+YverI4bHF1kVqRpOj2Ep8lW5fiS4VLW5e5LNuw7Fsxr/hiiWNJecmXUm7pxV+cfln/y8Dy9OWtK9xXbFlJXClaeWuV/6o9ZZplBWVPVo9bXbuGuaZ4zbu1U9deKHct37qOsk62rn195Pr6DRYbVm74slGw8WZFUMWBTYablm36sJm3+dqWgC01W422lmz9vE247c72sO21lVaV5TuIO/J3dO1M3Nnyq+evVbsMdpXs+rpbtLt9T+yeM1UeVVV7DfeuqEarZdXd+ybtu7o/eH99jUPN9gOMAyUHwUHZwRe/pf5261DEoebDnodrjlge2XSUfrS4FqmdWdtbJ6hrr0+ubzs29lhzg0/D0d9H/b670bSx4rjO8RUnKCcWnRg4WXCyr0nc1HMq49ST5qnN909POH3jzPgzrWcjzp4/F3rudEtgy8nzvucbL3hfOHbR82LdJfdLtZfdLh/9w+2Po63urbVXPK7UX/W62tA2pu3ENf9rp64HXz93g33j0s2om223Em7duT3pdvsd3p3nd7Pvvr6Xf6///vwHhAfFDzUelj8yfFT5p+2fB9rd2493BHdcfhz3+P4T7pOXT6VPv3Qu6qJ1lT8zeVb13Pl5Y3do99UXE190vhS/7O8p+kvzr02vbF4d+Tvg78u9E3o7X0teD7wpfav/dvc713fNfTF9j97nvO//UPxR/+OeT56fWj4nfX7WP/0L6cv6r7ZfG75FfHswkDMwIOZIOIpfAQxWND0dgDe7AaAlA0C/Cv8fJirPZoqCKM+TCgL/jZXnN0VxB6AGNvLfcFYTAAdhtZoPYwcAIP8djw8AqIvLcB0s0nQXZ2UsKjzhED4ODLw1AoDUAMBXycBA/+aBga87odi7ADTlKs+E8iI/g25zldM1Rvb2n89m/wJHBnEU5n9PrQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAAd0SU1FB+EKBRI2IMFyTLcAAAAaSURBVAjXY/h++dF/hl+/fv1nYmBgYMBJAAAKEQellAoQBwAAAABJRU5ErkJggg==)', // eslint-disable-line max-len
+};
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class GeneralTypo extends React.Component {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
+ Lorem ipsum dolor
+ {' '}
+ sit amet
+
+
+ Duis tristique metus magna, lobortis aliquam risus euismod sit amet.
+
+
+ Nullam in
+ tortor
+ ligula
+
+
+
+ Bolder
+
+ Bold
+
+ Medium
+
+
+ Regular
+
+ Light
+
+ Lighter
+
+
+
+ Duis tristique metus magna, lobortis aliquam risus euismod sit amet. Suspendisse porttitor velit nisl, feugiat tincidunt nisl mattis ut. Nulla lobortis nunc vitae nisi semper semper.
+ {' '}
+
+ Nulla eget lobortis lacus. Aliquam venenatis magna et odio lobortis maximus. Nullam in tortor ligula. Proin maximus risus nunc, eu aliquam nibh tempus a. Interdum et malesuada fames ac ante ipsum primis in faucibus.
+
+
+
+ Vestibulum nec mi
+ {' '}
+ suscipit
+
+
+ Bolder
+
+ Bold
+
+ Medium
+
+ Regular
+
+ Light
+
+ Lighter
+
+
+
+ Vestibulum faucibus eget erat eget pretium. Donec commodo convallis ligula, eget suscipit orci. Suspendisse potenti.
+
+ Curabitur egestas consequat lorem, vel fermentum augue porta id. Aliquam lobortis magna neque, gravida consequat velit venenatis at. Duis sed augue leo. Phasellus ante massa, aliquam non ante at, suscipit ornare ipsum. Quisque a consequat ante, at volutpat enim.
+
+
+
+ Numbers
+ {' '}
+looks great! 1234
+ 56
+7890
+
+
+ Let your Creativity Flow
+ {' '}
+
+123
+ $
+
+
+
+ Numerics
+ {' '}
+
+123
+ 00
+
+
+
+
+ Body 2
+
+
+ Body 1
+
+
+ Caption
+
+
+ {`
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ `}
+
+
+ Button
+
+
+ );
+ }
+}
+
+GeneralTypo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(GeneralTypo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/Heading.js b/front/odiparpack/app/containers/UiElements/demos/Typography/Heading.js
new file mode 100644
index 0000000..cf97396
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/Heading.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import { Typography } from '@material-ui/core';
+
+class Heading extends React.Component {
+ render() {
+ return (
+
+ {/*
+ Disp 4
+
+
+ Display 3
+
+
+ Display 2
+
+
+ Display 1
+
+
+ Headline
+
+
+ Title
+
+
+ Subheading
+
+
+ {`
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ `}
+ */}
+
+ {`h4 Título`}
+
+
+
+ {`h5 Subtítulos`}
+
+
+
+ {`h6 Título de tablas`}
+
+
+
+ {` Cuerpo de texto `}
+
+
+
+ );
+ }
+}
+
+export default Heading;
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/ListTypo.js b/front/odiparpack/app/containers/UiElements/demos/Typography/ListTypo.js
new file mode 100644
index 0000000..2f76ff1
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/ListTypo.js
@@ -0,0 +1,71 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import Type from 'ba-styles/Typography.scss';
+import { Typography, Divider } from '@material-ui/core';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class ListTypo extends React.Component {
+ render() {
+ const { classes } = this.props;
+ return (
+
+
Unordered List
+
+
+ - Lorem ipsum dolor sit amet
+ - Consectetur adipiscing elit
+ - Integer molestie lorem at massa
+ - Facilisis in pretium nisl aliquet
+ -
+Nulla volutpat aliquam velit
+
+ - Phasellus iaculis neque
+ - Purus sodales ultricies
+ - Vestibulum laoreet porttitor sem
+ - Ac tristique libero volutpat at
+
+
+ - Faucibus porta lacus fringilla vel
+ - Aenean sit amet erat nunc
+ - Eget porttitor lorem
+
+
+
+
Ordered List
+
+
+ - Lorem ipsum dolor sit amet
+ - Consectetur adipiscing elit
+ - Integer molestie lorem at massa
+ - Facilisis in pretium nisl aliquet
+ -
+Nulla volutpat aliquam velit
+
+ - Phasellus iaculis neque
+ - Purus sodales ultricies
+ - Vestibulum laoreet porttitor sem
+ - Ac tristique libero volutpat at
+
+
+ - Faucibus porta lacus fringilla vel
+ - Aenean sit amet erat nunc
+ - Eget porttitor lorem
+
+
+
+ );
+ }
+}
+
+ListTypo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ListTypo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/Typography/QuotesDemo.js b/front/odiparpack/app/containers/UiElements/demos/Typography/QuotesDemo.js
new file mode 100644
index 0000000..afd9197
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/Typography/QuotesDemo.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import { Quote } from 'ba-components';
+
+const styles = theme => ({
+ divider: {
+ display: 'block',
+ margin: `${theme.spacing(3)}px 0`,
+ }
+});
+
+class QuotesDemo extends React.Component {
+ render() {
+ const { classes } = this.props;
+ return (
+
+ );
+ }
+}
+
+QuotesDemo.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(QuotesDemo);
diff --git a/front/odiparpack/app/containers/UiElements/demos/index.js b/front/odiparpack/app/containers/UiElements/demos/index.js
new file mode 100644
index 0000000..311d50e
--- /dev/null
+++ b/front/odiparpack/app/containers/UiElements/demos/index.js
@@ -0,0 +1,117 @@
+// Badges
+export CommonBadges from './Badges/CommonBadges';
+export VariantBadges from './Badges/VariantBadges';
+// Avatars
+export AvatarsDemo from './Avatars/AvatarsDemo';
+export AvatarsPractice from './Avatars/AvatarsPractice';
+// Accordion
+export SimpleAccordion from './Accordion/SimpleAccordion';
+export AdvancedAccordion from './Accordion/AdvancedAccordion';
+export ControlledAccordion from './Accordion/ControlledAccordion';
+// List
+export ListBasic from './List/ListBasic';
+export ListControl from './List/ListControl';
+export ListMenu from './List/ListMenu';
+export ListInteractive from './List/ListInteractive';
+export PinnedList from './List/PinnedList';
+// Popover & Tooltip
+export SimpleTooltips from './PopoverTooltip/SimpleTooltips';
+export PositionedTooltips from './PopoverTooltip/PositionedTooltips';
+export SimplePopover from './PopoverTooltip/SimplePopover';
+export PopoverPlayground from './PopoverTooltip/PopoverPlayground';
+export DelayTooltips from './PopoverTooltip/DelayTooltips';
+export TransitionsTooltips from './PopoverTooltip/TransitionsTooltips';
+export TriggersTooltips from './PopoverTooltip/TriggersTooltips';
+export CustomizedTooltips from './PopoverTooltip/CustomizedTooltips';
+// Notification
+export SimpleNotif from './Notification/SimpleNotif';
+export StyledNotif from './Notification/StyledNotif';
+export TransitionNotif from './Notification/TransitionNotif';
+export MobileNotif from './Notification/MobileNotif';
+// Typography
+export GeneralTypo from './Typography/GeneralTypo';
+export Heading from './Typography/Heading';
+export ListTypo from './Typography/ListTypo';
+export ColouredTypo from './Typography/ColouredTypo';
+export QuotesDemo from './Typography/QuotesDemo';
+export AlignTypo from './Typography/AlignTypo';
+// Tabs
+export SimpleTabs from './Tabs/SimpleTabs';
+export LongTextTabs from './Tabs/LongTextTabs';
+export FixedTabs from './Tabs/FixedTabs';
+export CenteredTabs from './Tabs/CenteredTabs';
+export IconTabs from './Tabs/IconTabs';
+export ScrollTabs from './Tabs/ScrollTabs';
+export ScrollIconTabs from './Tabs/ScrollIconTabs';
+export DisabledTab from './Tabs/DisabledTab';
+export CustomTabs from './Tabs/CustomTabs';
+export BottomNav from './Tabs/BottomNav';
+// Card
+export StandardCards from './Cards/StandardCards';
+export ControlCards from './Cards/ControlCards';
+export PaperSheet from './Cards/PaperSheet';
+export SocialCards from './Cards/SocialCards';
+export EcommerceCards from './Cards/EcommerceCards';
+// Image Grid
+export ImageGridList from './ImageGrid/ImageGridList';
+export TitlebarGridList from './ImageGrid/TitlebarGridList';
+export AdvancedGridList from './ImageGrid/AdvancedGridList';
+export SingleLineGridList from './ImageGrid/SingleLineGridList';
+// Progress
+export CircularIndeterminate from './Progress/CircularIndeterminate';
+export CircularIntegration from './Progress/CircularIntegration';
+export CircularDeterminate from './Progress/CircularDeterminate';
+export CircularStatic from './Progress/CircularStatic';
+export LinearIndeterminate from './Progress/LinearIndeterminate';
+export LinearDeterminate from './Progress/LinearDeterminate';
+export LinearBuffer from './Progress/LinearBuffer';
+export LinearQuery from './Progress/LinearQuery';
+export LinearStatic from './Progress/LinearStatic';
+export ProgressDelay from './Progress/ProgressDelay';
+// Dialog
+export ModalDemo from './DialogModal/ModalDemo';
+export AlertDialog from './DialogModal/AlertDialog';
+export SelectDialog from './DialogModal/SelectDialog';
+export SelectRadioDialog from './DialogModal/SelectRadioDialog';
+export FormDialog from './DialogModal/FormDialog';
+export FullScreenDialog from './DialogModal/FullScreenDialog';
+export ImagePopup from './DialogModal/ImagePopup';
+export ScrollDialog from './DialogModal/ScrollDialog';
+// Steppers
+export HorizontalLinear from './Steppers/HorizontalLinear';
+export HorizontalNonLinear from './Steppers/HorizontalNonLinear';
+export StepperError from './Steppers/StepperError';
+export VerticalStepper from './Steppers/VerticalStepper';
+export MobileSteppers from './Steppers/MobileSteppers';
+export StepperCarousel from './Steppers/StepperCarousel';
+// Menu and Drawer
+export TemporaryDrawer from './DrawerMenu/TemporaryDrawer';
+export PermanentDrawer from './DrawerMenu/PermanentDrawer';
+export PersistentDrawer from './DrawerMenu/PersistentDrawer';
+export SwipeDrawer from './DrawerMenu/SwipeDrawer';
+export MiniDrawer from './DrawerMenu/MiniDrawer';
+export BasicMenu from './DrawerMenu/BasicMenu';
+export DropdownMenu from './DrawerMenu/DropdownMenu';
+export MenuTransition from './DrawerMenu/MenuTransition';
+export StyledMenu from './DrawerMenu/StyledMenu';
+// Pagination
+export TbPagination from './Pagination/TbPagination';
+export TbPaginationCustom from './Pagination/TbPaginationCustom';
+export GeneralPagination from './Pagination/GeneralPagination';
+// Breadcrumb
+export ClassicBreadcrumbs from './Breadcrumbs/ClassicBreadcrumbs';
+export PaperBreadcrumbs from './Breadcrumbs/PaperBreadcrumbs';
+// Slider Carousel
+export SingleCarousel from './SliderCaraousel/SingleCarousel';
+export MultipleCarousel from './SliderCaraousel/MultipleCarousel';
+export AutoplayCarousel from './SliderCaraousel/AutoplayCarousel';
+export ThumbnailCarousel from './SliderCaraousel/ThumbnailCarousel';
+export VerticalCarousel from './SliderCaraousel/VerticalCarousel';
+export CustomCarousel from './SliderCaraousel/CustomCarousel';
+export AnimatedSlider from './SliderCaraousel/AnimatedSlider';
+// Tags
+export BasicTags from './Tags/BasicTags';
+export ArrayTags from './Tags/ArrayTags';
+// Dividers
+export CommonDividers from './Dividers/CommonDividers';
+export SpecialDividers from './Dividers/SpecialDividers';
diff --git a/front/odiparpack/app/containers/pageListAsync.js b/front/odiparpack/app/containers/pageListAsync.js
new file mode 100644
index 0000000..feff750
--- /dev/null
+++ b/front/odiparpack/app/containers/pageListAsync.js
@@ -0,0 +1,324 @@
+import Loadable from 'react-loadable';
+import Loading from 'ba-components/Loading';
+
+// Dashboard
+export const DashboardV1 = Loadable({
+ loader: () => import('./Dashboard/Dashboard'),
+ loading: Loading,
+});
+export const DashboardV2 = Loadable({
+ loader: () => import('./Dashboard/DashboardV2'),
+ loading: Loading,
+});
+
+// Layouts
+export const AppLayout = Loadable({
+ loader: () => import('./Layouts/AppLayout'),
+ loading: Loading,
+});
+export const Responsive = Loadable({
+ loader: () => import('./Layouts/Responsive'),
+ loading: Loading,
+});
+export const Grid = Loadable({
+ loader: () => import('./Layouts/Grid'),
+ loading: Loading,
+});
+
+// Tables
+export const SimpleTable = Loadable({
+ loader: () => import('./Tables/BasicTable'),
+ loading: Loading,
+});
+export const AdvancedTable = Loadable({
+ loader: () => import('./Tables/AdvancedTable'),
+ loading: Loading,
+});
+export const TreeTable = Loadable({
+ loader: () => import('./Tables/TreeTable'),
+ loading: Loading,
+});
+export const CrudTable = Loadable({
+ loader: () => import('./Tables/CrudTable'),
+ loading: Loading,
+});
+export const TablePlayground = Loadable({
+ loader: () => import('./Tables/TablePlayground'),
+ loading: Loading,
+});
+
+// Forms
+export const ReduxForm = Loadable({
+ loader: () => import('./Forms/ReduxForm'),
+ loading: Loading,
+});
+export const DateTimePicker = Loadable({
+ loader: () => import('./Forms/DateTimePicker'),
+ loading: Loading,
+});
+export const CheckboxRadio = Loadable({
+ loader: () => import('./Forms/CheckboxRadio'),
+ loading: Loading,
+});
+export const Switches = Loadable({
+ loader: () => import('./Forms/Switches'),
+ loading: Loading,
+});
+export const Selectbox = Loadable({
+ loader: () => import('./Forms/Selectbox'),
+ loading: Loading,
+});
+export const Rating = Loadable({
+ loader: () => import('./Forms/Rating'),
+ loading: Loading,
+});
+export const SliderRange = Loadable({
+ loader: () => import('./Forms/SliderRange'),
+ loading: Loading,
+});
+export const Buttons = Loadable({
+ loader: () => import('./Forms/Buttons'),
+ loading: Loading,
+});
+export const Textbox = Loadable({
+ loader: () => import('./Forms/Textbox'),
+ loading: Loading,
+});
+export const Autocomplete = Loadable({
+ loader: () => import('./Forms/Autocomplete'),
+ loading: Loading,
+});
+export const TextEditor = Loadable({
+ loader: () => import('./Forms/TextEditor'),
+ loading: Loading,
+});
+export const Upload = Loadable({
+ loader: () => import('./Forms/Upload'),
+ loading: Loading,
+});
+
+// UI Components
+export const Badges = Loadable({
+ loader: () => import('./UiElements/Badges'),
+ loading: Loading,
+});
+export const Avatars = Loadable({
+ loader: () => import('./UiElements/Avatars'),
+ loading: Loading,
+});
+export const Accordion = Loadable({
+ loader: () => import('./UiElements/Accordion'),
+ loading: Loading,
+});
+export const List = Loadable({
+ loader: () => import('./UiElements/List'),
+ loading: Loading,
+});
+export const PopoverTooltip = Loadable({
+ loader: () => import('./UiElements/PopoverTooltip'),
+ loading: Loading,
+});
+export const Notification = Loadable({
+ loader: () => import('./UiElements/Notification'),
+ loading: Loading,
+});
+export const Typography = Loadable({
+ loader: () => import('./UiElements/Typography'),
+ loading: Loading,
+});
+export const Tabs = Loadable({
+ loader: () => import('./UiElements/Tabs'),
+ loading: Loading,
+});
+export const Cards = Loadable({
+ loader: () => import('./UiElements/Cards'),
+ loading: Loading,
+});
+export const ImageGrid = Loadable({
+ loader: () => import('./UiElements/ImageGrid'),
+ loading: Loading,
+});
+export const Progress = Loadable({
+ loader: () => import('./UiElements/Progress'),
+ loading: Loading,
+});
+export const DialogModal = Loadable({
+ loader: () => import('./UiElements/DialogModal'),
+ loading: Loading,
+});
+export const Steppers = Loadable({
+ loader: () => import('./UiElements/Steppers'),
+ loading: Loading,
+});
+export const DrawerMenu = Loadable({
+ loader: () => import('./UiElements/DrawerMenu'),
+ loading: Loading,
+});
+export const Paginations = Loadable({
+ loader: () => import('./UiElements/Paginations'),
+ loading: Loading,
+});
+export const Breadcrumbs = Loadable({
+ loader: () => import('./UiElements/Breadcrumbs'),
+ loading: Loading,
+});
+export const Icons = Loadable({
+ loader: () => import('./UiElements/Icons'),
+ loading: Loading,
+});
+export const SliderCarousel = Loadable({
+ loader: () => import('./UiElements/SliderCarousel'),
+ loading: Loading,
+});
+export const Tags = Loadable({
+ loader: () => import('./UiElements/Tags'),
+ loading: Loading,
+});
+export const Dividers = Loadable({
+ loader: () => import('./UiElements/Dividers'),
+ loading: Loading,
+});
+
+// Chart
+export const LineCharts = Loadable({
+ loader: () => import('./Charts/LineCharts'),
+ loading: Loading,
+});
+export const BarCharts = Loadable({
+ loader: () => import('./Charts/BarCharts'),
+ loading: Loading,
+});
+export const AreaCharts = Loadable({
+ loader: () => import('./Charts/AreaCharts'),
+ loading: Loading,
+});
+export const PieCharts = Loadable({
+ loader: () => import('./Charts/PieCharts'),
+ loading: Loading,
+});
+export const RadarCharts = Loadable({
+ loader: () => import('./Charts/RadarCharts'),
+ loading: Loading,
+});
+export const ScatterCharts = Loadable({
+ loader: () => import('./Charts/ScatterCharts'),
+ loading: Loading,
+});
+export const CompossedCharts = Loadable({
+ loader: () => import('./Charts/CompossedCharts'),
+ loading: Loading,
+});
+export const ResponsiveCharts = Loadable({
+ loader: () => import('./Charts/ResponsiveCharts'),
+ loading: Loading,
+});
+
+// Pages
+export const Login = Loadable({
+ loader: () => import('./Pages/Users/Login'),
+ loading: Loading,
+});
+export const Register = Loadable({
+ loader: () => import('./Pages/Users/Register'),
+ loading: Loading,
+});
+export const Profile = Loadable({
+ loader: () => import('./Pages/UserProfile'),
+ loading: Loading,
+});
+export const SocialMedia = Loadable({
+ loader: () => import('./Pages/SocialMedia'),
+ loading: Loading,
+});
+export const BlankPage = Loadable({
+ loader: () => import('./Pages/BlankPage'),
+ loading: Loading,
+});
+export const Ecommerce = Loadable({
+ loader: () => import('./Pages/Ecommerce'),
+ loading: Loading,
+});
+export const Contact = Loadable({
+ loader: () => import('./Pages/Contact'),
+ loading: Loading,
+});
+export const ResetPassword = Loadable({
+ loader: () => import('./Pages/Users/ResetPassword'),
+ loading: Loading,
+});
+export const LockScreen = Loadable({
+ loader: () => import('./Pages/Users/LockScreen'),
+ loading: Loading,
+});
+export const Chat = Loadable({
+ loader: () => import('./Pages/Chat'),
+ loading: Loading,
+});
+export const Email = Loadable({
+ loader: () => import('./Pages/Email'),
+ loading: Loading,
+});
+export const Photos = Loadable({
+ loader: () => import('./Pages/Photos'),
+ loading: Loading,
+});
+export const Calendar = Loadable({
+ loader: () => import('./Pages/Calendar'),
+ loading: Loading,
+});
+export const LoginDedicated = Loadable({
+ loader: () => import('./Pages/Standalone/LoginDedicated'),
+ loading: Loading,
+});
+
+// Maps
+export const MapMarker = Loadable({
+ loader: () => import('./Maps/MapMarker'),
+ loading: Loading,
+});
+export const MapDirection = Loadable({
+ loader: () => import('./Maps/MapDirection'),
+ loading: Loading,
+});
+export const SearchMap = Loadable({
+ loader: () => import('./Maps/SearchMap'),
+ loading: Loading,
+});
+export const TrafficIndicator = Loadable({
+ loader: () => import('./Maps/TrafficIndicator'),
+ loading: Loading,
+});
+export const StreetViewMap = Loadable({
+ loader: () => import('./Maps/StreetViewMap'),
+ loading: Loading,
+});
+
+// Other
+export const NotFound = Loadable({
+ loader: () => import('./NotFound/NotFound'),
+ loading: Loading,
+});
+export const NotFoundDedicated = Loadable({
+ loader: () => import('./Pages/Standalone/NotFoundDedicated'),
+ loading: Loading,
+});
+export const Error = Loadable({
+ loader: () => import('./Pages/Error'),
+ loading: Loading,
+});
+export const Maintenance = Loadable({
+ loader: () => import('./Pages/Maintenance'),
+ loading: Loading,
+});
+export const Parent = Loadable({
+ loader: () => import('./Parent'),
+ loading: Loading,
+});
+export const Settings = Loadable({
+ loader: () => import('./Pages/Settings'),
+ loading: Loading,
+});
+export const HelpSupport = Loadable({
+ loader: () => import('./Pages/HelpSupport'),
+ loading: Loading,
+});
diff --git a/front/odiparpack/app/i18n.js b/front/odiparpack/app/i18n.js
new file mode 100644
index 0000000..cac434f
--- /dev/null
+++ b/front/odiparpack/app/i18n.js
@@ -0,0 +1,46 @@
+/**
+ * i18n.js
+ *
+ * This will setup the i18n language files and locale data for your app.
+ *
+ * IMPORTANT: This file is used by the internal build
+ * script `extract-intl`, and must use CommonJS module syntax
+ * You CANNOT use import/export in this file.
+ */
+const addLocaleData = require('react-intl').addLocaleData; //eslint-disable-line
+const enLocaleData = require('react-intl/locale-data/en');
+
+const enTranslationMessages = require('./translations/en.json');
+
+addLocaleData(enLocaleData);
+
+const DEFAULT_LOCALE = 'en';
+
+// prettier-ignore
+const appLocales = [
+ 'en',
+];
+
+const formatTranslationMessages = (locale, messages) => {
+ const defaultFormattedMessages =
+ locale !== DEFAULT_LOCALE
+ ? formatTranslationMessages(DEFAULT_LOCALE, enTranslationMessages)
+ : {};
+ const flattenFormattedMessages = (formattedMessages, key) => {
+ const formattedMessage =
+ !messages[key] && locale !== DEFAULT_LOCALE
+ ? defaultFormattedMessages[key]
+ : messages[key];
+ return Object.assign(formattedMessages, { [key]: formattedMessage });
+ };
+ return Object.keys(messages).reduce(flattenFormattedMessages, {});
+};
+
+const translationMessages = {
+ en: formatTranslationMessages('en', enTranslationMessages),
+};
+
+exports.appLocales = appLocales;
+exports.formatTranslationMessages = formatTranslationMessages;
+exports.translationMessages = translationMessages;
+exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
diff --git a/front/odiparpack/app/index.html b/front/odiparpack/app/index.html
new file mode 100644
index 0000000..74ddd5a
--- /dev/null
+++ b/front/odiparpack/app/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+ Boss Ultimate - React Admin Template Material Design
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
diff --git a/front/odiparpack/app/redux/.DS_Store b/front/odiparpack/app/redux/.DS_Store
new file mode 100644
index 0000000..bef93f9
Binary files /dev/null and b/front/odiparpack/app/redux/.DS_Store differ
diff --git a/front/odiparpack/app/redux/configureStore.js b/front/odiparpack/app/redux/configureStore.js
new file mode 100644
index 0000000..49a6b7b
--- /dev/null
+++ b/front/odiparpack/app/redux/configureStore.js
@@ -0,0 +1,53 @@
+/**
+ * Create the store with dynamic reducers
+ */
+
+import { createStore, applyMiddleware, compose } from 'redux';
+import { fromJS } from 'immutable';
+import { routerMiddleware } from 'connected-react-router/immutable';
+import createSagaMiddleware from 'redux-saga';
+import createReducer from './reducers';
+
+const sagaMiddleware = createSagaMiddleware();
+
+export default function configureStore(initialState = {}, history) {
+ // Create the store with two middlewares
+ // 1. sagaMiddleware: Makes redux-sagas work
+ // 2. routerMiddleware: Syncs the location/URL path to the state
+ const middlewares = [sagaMiddleware, routerMiddleware(history)];
+
+ const enhancers = [applyMiddleware(...middlewares)];
+
+ // If Redux DevTools Extension is installed use it, otherwise use Redux compose
+ /* eslint-disable no-underscore-dangle, indent */
+ const composeEnhancers = process.env.NODE_ENV !== 'production'
+ && typeof window === 'object'
+ && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+ // TODO Try to remove when `react-router-redux` is out of beta, LOCATION_CHANGE should not be fired more than once after hot reloading
+ // Prevent recomputing reducers for `replaceReducer`
+ shouldHotReload: false,
+ })
+ : compose;
+ /* eslint-enable */
+ const store = createStore(
+ createReducer(),
+ fromJS(initialState),
+ composeEnhancers(...enhancers),
+ );
+
+ // Extensions
+ store.runSaga = sagaMiddleware.run;
+ store.injectedReducers = {}; // Reducer registry
+ store.injectedSagas = {}; // Saga registry
+
+ // Make reducers hot reloadable, see http://mxs.is/googmo
+ /* istanbul ignore next */
+ if (module.hot) {
+ module.hot.accept('./reducers', () => {
+ store.replaceReducer(createReducer(store.injectedReducers));
+ });
+ }
+
+ return store;
+}
diff --git a/front/odiparpack/app/redux/helpers/dateTimeHelper.js b/front/odiparpack/app/redux/helpers/dateTimeHelper.js
new file mode 100644
index 0000000..e91c981
--- /dev/null
+++ b/front/odiparpack/app/redux/helpers/dateTimeHelper.js
@@ -0,0 +1,35 @@
+export function getDate() {
+ let today = new Date();
+ let dd = today.getDate();
+ const monthNames = [
+ 'January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December'
+ ];
+ const mm = monthNames[today.getMonth()]; // January is 0!
+ const yyyy = today.getFullYear();
+
+ if (dd < 10) {
+ dd = '0' + dd;
+ }
+
+ today = mm + ', ' + dd + ' ' + yyyy;
+
+ return today;
+}
+
+export function getTime() {
+ let now = new Date();
+ let h = now.getHours();
+ let m = now.getMinutes();
+
+ if (h < 10) {
+ h = '0' + h;
+ }
+
+ if (m < 10) {
+ m = '0' + m;
+ }
+
+ now = h + ':' + m;
+ return now;
+}
diff --git a/front/odiparpack/app/redux/modules/calendar.js b/front/odiparpack/app/redux/modules/calendar.js
new file mode 100644
index 0000000..fb1291d
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/calendar.js
@@ -0,0 +1,79 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import {
+ FETCH_CALENDAR_DATA,
+ ADD_EVENT,
+ DISCARD_EVENT,
+ SUBMIT_EVENT,
+ DELETE_EVENT,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ events: List([]),
+ openFrm: false,
+ formValues: Map(),
+ notifMsg: '',
+};
+
+const initForm = Map({
+ title: '',
+ start: new Date(),
+ end: new Date(),
+ hexColor: 'F8BBD0',
+});
+
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_CALENDAR_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('events', items);
+ });
+ case ADD_EVENT:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('openFrm', true)
+ .set('formValues', initForm);
+ });
+ case DISCARD_EVENT:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('openFrm', false)
+ .set('formValues', Map())
+ .set('notifMsg', notif.discard);
+ });
+ case SUBMIT_EVENT:
+ return state.withMutations((mutableState) => {
+ const initItem = Map(action.newEvent);
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const newItem = initItem
+ .update('id', (val = id) => val)
+ .set('start', action.newEvent.get('start')._d || action.newEvent.get('start'))
+ .set('end', action.newEvent.get('end')._d || action.newEvent.get('end'));
+ mutableState.update('events', events => events.push(newItem));
+ mutableState
+ .set('formValues', Map())
+ .set('openFrm', false)
+ .set('notifMsg', notif.saved);
+ });
+ case DELETE_EVENT:
+ return state.withMutations((mutableState) => {
+ const eventItem = state.get('events')
+ .find(obj => (
+ obj.get('id') === action.event.id
+ ));
+ const index = state.get('events').indexOf(eventItem);
+ mutableState
+ .update('events', events => events.splice(index, 1))
+ .set('notifMsg', notif.removed);
+ });
+ case CLOSE_NOTIF:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/chat.js b/front/odiparpack/app/redux/modules/chat.js
new file mode 100644
index 0000000..e30c97a
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/chat.js
@@ -0,0 +1,73 @@
+import { fromJS, List, Map } from 'immutable';
+import {
+ FETCH_CHAT_DATA,
+ SHOW_CHAT,
+ HIDE_CHAT,
+ SEND_CHAT,
+ DELETE_CONVERSATION
+} from 'ba-actions/actionTypes';
+import { getDate, getTime } from '../helpers/dateTimeHelper';
+
+const initialState = {
+ chatList: List([]),
+ activeChat: List([]),
+ chatSelected: 0,
+ showMobileDetail: false
+};
+
+const buildMessage = (message, curData) => {
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const newData = Map({
+ id,
+ from: 'me',
+ date: getDate(),
+ time: getTime(),
+ message,
+ });
+ return curData.push(newData);
+};
+
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_CHAT_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState
+ .set('chatList', items)
+ .set('activeChat', items.getIn([state.get('chatSelected'), 'chat']));
+ });
+ case SHOW_CHAT:
+ return state.withMutations((mutableState) => {
+ const chatItem = state.get('chatList')
+ .find(obj => (
+ obj.get('with') === action.person.get('id')
+ ));
+ const index = state.get('chatList').indexOf(chatItem);
+ const chatValue = chatItem.get('chat') !== [] ? chatItem.get('chat') : List([]);
+ mutableState
+ .set('chatSelected', index)
+ .set('activeChat', chatValue)
+ .set('showMobileDetail', true);
+ });
+ case HIDE_CHAT:
+ return state.withMutations((mutableState) => {
+ mutableState.set('showMobileDetail', false);
+ });
+ case SEND_CHAT:
+ return state.withMutations((mutableState) => {
+ const newMessage = buildMessage(action.message, state.getIn(['chatList', state.get('chatSelected'), 'chat']));
+ mutableState
+ .update('chatList', chatList => chatList.setIn([state.get('chatSelected'), 'chat'], newMessage))
+ .set('activeChat', newMessage);
+ });
+ case DELETE_CONVERSATION:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .update('chatList', chatList => chatList.setIn([state.get('chatSelected'), 'chat'], List([])))
+ .set('activeChat', List([]));
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/contact.js b/front/odiparpack/app/redux/modules/contact.js
new file mode 100644
index 0000000..bf34a8b
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/contact.js
@@ -0,0 +1,131 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import {
+ FETCH_CONTACT_DATA,
+ SEARCH_CONTACT,
+ SHOW_DETAIL_CONTACT,
+ HIDE_DETAIL,
+ EDIT_CONTACT,
+ SUBMIT_CONTACT,
+ DELETE_CONTACT,
+ TOGGLE_FAVORITE,
+ ADD_CONTACT,
+ CLOSE_CONTACT_FORM,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ contactList: List([]),
+ formValues: Map(),
+ selectedIndex: 0,
+ selectedId: '',
+ keywordValue: '',
+ avatarInit: '',
+ openFrm: false,
+ showMobileDetail: false,
+ notifMsg: '',
+};
+let editingIndex = 0;
+
+const initialImmutableState = fromJS(initialState);
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_CONTACT_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('contactList', items);
+ });
+ case SEARCH_CONTACT:
+ return state.withMutations((mutableState) => {
+ action.keyword.persist();
+ const keyword = action.keyword.target.value.toLowerCase();
+ mutableState.set('keywordValue', keyword);
+ });
+ case ADD_CONTACT:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('openFrm', true)
+ .set('formValues', Map())
+ .set('avatarInit', '');
+ });
+ case CLOSE_CONTACT_FORM:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('openFrm', false)
+ .set('formValues', Map())
+ .set('avatarInit', '')
+ .set('notifMsg', notif.discard);
+ });
+ case EDIT_CONTACT:
+ return state.withMutations((mutableState) => {
+ editingIndex = state.get('contactList').indexOf(action.item);
+ mutableState
+ .set('openFrm', true)
+ .set('selectedId', action.item.get('id'))
+ .set('formValues', action.item)
+ .set('avatarInit', action.item.get('avatar'));
+ });
+ case SUBMIT_CONTACT:
+ return state.withMutations((mutableState) => {
+ const initItem = Map(action.newData);
+ if (state.get('selectedId') === action.newData.get('id')) {
+ // Update data
+ const avatar = action.avatar !== '' ? action.avatar : state.get('avatarInit');
+ const newItem = initItem.update((initUpdated) => (initUpdated.set('avatar', avatar)));
+ mutableState
+ .update('contactList', contactList => contactList.setIn(
+ [editingIndex], newItem
+ ))
+ .set('notifMsg', notif.updated);
+ } else {
+ // Insert data
+ const avatar = action.avatar !== '' ? action.avatar : '/images/pp_boy.svg';
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const newItem = initItem
+ .update('id', (val = id) => val)
+ .update('avatar', (val = avatar) => val)
+ .update('favorited', (val = false) => val);
+ mutableState
+ .update('contactList', contactList => contactList.unshift(newItem))
+ .set('selectedIndex', 0)
+ .set('notifMsg', notif.saved);
+ }
+ mutableState
+ .set('formValues', null)
+ .set('avatarInit', '')
+ .set('openFrm', false);
+ });
+ case SHOW_DETAIL_CONTACT:
+ return state.withMutations((mutableState) => {
+ const index = state.get('contactList').indexOf(action.item);
+ mutableState
+ .set('selectedIndex', index)
+ .set('showMobileDetail', true);
+ });
+ case HIDE_DETAIL:
+ return state.withMutations((mutableState) => {
+ mutableState.set('showMobileDetail', false);
+ });
+ case DELETE_CONTACT:
+ return state.withMutations((mutableState) => {
+ const index = state.get('contactList').indexOf(action.item);
+ mutableState
+ .update('contactList', contactList => contactList.splice(index, 1))
+ .set('notifMsg', notif.removed);
+ });
+ case TOGGLE_FAVORITE:
+ return state.withMutations((mutableState) => {
+ const index = state.get('contactList').indexOf(action.item);
+ mutableState.update('contactList', contactList => contactList
+ .setIn([index, 'favorited'], !state.getIn(['contactList', index, 'favorited']))
+ );
+ });
+ case CLOSE_NOTIF:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/crudTable.js b/front/odiparpack/app/redux/modules/crudTable.js
new file mode 100644
index 0000000..2bdb1e8
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/crudTable.js
@@ -0,0 +1,94 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import {
+ FETCH_DATA,
+ ADD_EMPTY_ROW,
+ UPDATE_ROW,
+ REMOVE_ROW,
+ EDIT_ROW,
+ SAVE_ROW,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ dataTable: List([]),
+ notifMsg: '',
+};
+
+const initialItem = (keyTemplate, anchor) => {
+ const [...rawKey] = keyTemplate.keys();
+ const staticKey = {
+ id: (+new Date() + Math.floor(Math.random() * 999999)).toString(36),
+ };
+ for (let i = 0; i < rawKey.length; i += 1) {
+ if (rawKey[i] !== 'id' && rawKey[i] !== 'edited') {
+ staticKey[rawKey[i]] = anchor[i].initialValue;
+ }
+ }
+ // Push another static key
+ staticKey.edited = true;
+
+ return Map(staticKey);
+};
+
+const initialImmutableState = fromJS(initialState);
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ const { branch } = action;
+ switch (action.type) {
+ case `${branch}/${FETCH_DATA}`:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('dataTable', items);
+ });
+ case `${branch}/${ADD_EMPTY_ROW}`:
+ return state.withMutations((mutableState) => {
+ const raw = state.get('dataTable').last();
+ const initial = initialItem(raw, action.anchor);
+ mutableState.update('dataTable', dataTable => dataTable.unshift(initial));
+ });
+ case `${branch}/${REMOVE_ROW}`:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTable').indexOf(action.item);
+ mutableState
+ .update('dataTable', dataTable => dataTable.splice(index, 1))
+ .set('notifMsg', notif.removed);
+ });
+ case `${branch}/${UPDATE_ROW}`:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTable').indexOf(action.item);
+ const cellTarget = action.event.target.name;
+ const newVal = type => {
+ if (type === 'checkbox') {
+ return action.event.target.checked;
+ }
+ return action.event.target.value;
+ };
+ mutableState.update('dataTable', dataTable => dataTable
+ .setIn([index, cellTarget], newVal(action.event.target.type))
+ );
+ });
+ case `${branch}/${EDIT_ROW}`:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTable').indexOf(action.item);
+ mutableState.update('dataTable', dataTable => dataTable
+ .setIn([index, 'edited'], true)
+ );
+ });
+ case `${branch}/${SAVE_ROW}`:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTable').indexOf(action.item);
+ mutableState
+ .update('dataTable', dataTable => dataTable
+ .setIn([index, 'edited'], false)
+ )
+ .set('notifMsg', notif.saved);
+ });
+ case `${branch}/${CLOSE_NOTIF}`:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/crudTableForm.js b/front/odiparpack/app/redux/modules/crudTableForm.js
new file mode 100644
index 0000000..d5194c1
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/crudTableForm.js
@@ -0,0 +1,99 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import {
+ FETCH_DATA_FORM,
+ ADD_NEW,
+ CLOSE_FORM,
+ SUBMIT_DATA,
+ REMOVE_ROW_FORM,
+ EDIT_ROW_FORM,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ dataTable: List([]),
+ formValues: Map(),
+ editingId: '',
+ showFrm: false,
+ notifMsg: '',
+};
+
+const initialItem = (keyTemplate, anchor) => {
+ const [...rawKey] = keyTemplate.keys();
+ const staticKey = {};
+ for (let i = 0; i < rawKey.length; i += 1) {
+ if (rawKey[i] !== 'id') {
+ const itemIndex = anchor.findIndex(a => a.name === rawKey[i]);
+ staticKey[rawKey[i]] = anchor[itemIndex].initialValue;
+ }
+ }
+
+ return Map(staticKey);
+};
+let editingIndex = 0;
+
+const initialImmutableState = fromJS(initialState);
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ const { branch } = action;
+ switch (action.type) {
+ case `${branch}/${FETCH_DATA_FORM}`:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('dataTable', items);
+ });
+ case `${branch}/${ADD_NEW}`:
+ return state.withMutations((mutableState) => {
+ const raw = state.get('dataTable').last();
+ const initial = initialItem(raw, action.anchor);
+ mutableState.set('formValues', initial);
+ mutableState.set('showFrm', true);
+ });
+ case `${branch}/${SUBMIT_DATA}`:
+ return state.withMutations((mutableState) => {
+ if (state.get('editingId') === action.newData.get('id')) {
+ // Update data
+ mutableState
+ .update('dataTable', dataTable => dataTable.setIn([editingIndex], action.newData))
+ .set('notifMsg', notif.updated);
+ } else {
+ // Insert data
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const initItem = Map(action.newData);
+ const newItem = initItem.update('id', (val = id) => val);
+ mutableState
+ .update('dataTable', dataTable => dataTable.unshift(newItem))
+ .set('notifMsg', notif.saved);
+ }
+ mutableState.set('showFrm', false);
+ mutableState.set('formValues', Map());
+ });
+ case `${branch}/${CLOSE_FORM}`:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('formValues', Map())
+ .set('showFrm', false);
+ });
+ case `${branch}/${REMOVE_ROW_FORM}`:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTable').indexOf(action.item);
+ mutableState
+ .update('dataTable', dataTable => dataTable.splice(index, 1))
+ .set('notifMsg', notif.removed);
+ });
+ case `${branch}/${EDIT_ROW_FORM}`:
+ return state.withMutations((mutableState) => {
+ editingIndex = state.get('dataTable').indexOf(action.item);
+ mutableState
+ .set('formValues', action.item)
+ .set('editingId', action.item.get('id'))
+ .set('showFrm', true);
+ });
+ case `${branch}/${CLOSE_NOTIF}`:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/ecommerce.js b/front/odiparpack/app/redux/modules/ecommerce.js
new file mode 100644
index 0000000..a294bae
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/ecommerce.js
@@ -0,0 +1,94 @@
+import { fromJS, List } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import {
+ FETCH_PRODUCT_DATA,
+ ADD_TO_CART,
+ DELETE_CART_ITEM,
+ CHECKOUT,
+ SHOW_DETAIL_PRODUCT,
+ SEARCH_PRODUCT,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ productList: List([]),
+ cart: List([]),
+ totalItems: 0,
+ totalPrice: 0,
+ productIndex: 0,
+ keywordValue: '',
+ notifMsg: '',
+};
+
+let itemId = [];
+
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_PRODUCT_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('productList', items);
+ });
+ case SEARCH_PRODUCT:
+ return state.withMutations((mutableState) => {
+ action.keyword.persist();
+ const keyword = action.keyword.target.value.toLowerCase();
+ mutableState.set('keywordValue', keyword);
+ });
+ case ADD_TO_CART:
+ return state.withMutations((mutableState) => {
+ const item = fromJS(action.item);
+ const qty = Number(item.get('quantity'));
+ const price = item.get('price');
+ const index = itemId.indexOf(action.item.id);
+ if (index > -1) {
+ // If item already added to cart
+ mutableState.update('cart', cart => cart.setIn(
+ [index, 'quantity'],
+ state.getIn(['cart', index, 'quantity']) + qty
+ ));
+ } else {
+ // item not exist in cart
+ itemId.push(action.item.id);
+ mutableState.update('cart', cart => cart.push(item));
+ }
+ mutableState
+ .set('totalItems', state.get('totalItems') + qty)
+ .set('totalPrice', state.get('totalPrice') + (price * qty))
+ .set('notifMsg', notif.addCart);
+ });
+ case DELETE_CART_ITEM:
+ return state.withMutations((mutableState) => {
+ const index = state.get('cart').indexOf(action.item);
+ const qty = Number(action.item.get('quantity'));
+ const price = action.item.get('price');
+ itemId = itemId.filter(item => item !== action.item.get('id'));
+ mutableState
+ .update('cart', cart => cart.splice(index, 1))
+ .set('totalItems', state.get('totalItems') - qty)
+ .set('totalPrice', state.get('totalPrice') - (price * qty))
+ .set('notifMsg', notif.removed);
+ });
+ case CHECKOUT:
+ itemId = [];
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('cart', List([]))
+ .set('totalItems', 0)
+ .set('totalPrice', 0)
+ .set('notifMsg', notif.checkout);
+ });
+ case SHOW_DETAIL_PRODUCT:
+ return state.withMutations((mutableState) => {
+ const index = state.get('productList').indexOf(action.item);
+ mutableState.set('productIndex', index);
+ });
+ case CLOSE_NOTIF:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/email.js b/front/odiparpack/app/redux/modules/email.js
new file mode 100644
index 0000000..e103316
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/email.js
@@ -0,0 +1,119 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import dummyData from 'ba-api/dummyContents';
+import {
+ FETCH_EMAIL_DATA,
+ OPEN_MAIL,
+ FILTER_MAIL,
+ COMPOSE_MAIL,
+ SEND_MAIL,
+ DISCARD_MESSAGE,
+ SEARCH_MAIL,
+ DELETE_MAIL,
+ MOVE_TO,
+ TOGGLE_STARED,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+import { getDate, getTime } from '../helpers/dateTimeHelper';
+
+const initialState = {
+ inbox: List([]),
+ selectedMail: 0,
+ selectedMailId: '',
+ keywordValue: '',
+ currentPage: 'inbox',
+ openFrm: false,
+ notifMsg: '',
+};
+
+const buildMessage = (to, subject, content, files) => {
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const newData = Map({
+ id,
+ date: getDate(),
+ time: getTime(),
+ avatar: dummyData.user.avatar,
+ name: to,
+ subject,
+ content,
+ attachment: files,
+ category: 'sent',
+ stared: false,
+ });
+ return newData;
+};
+
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_EMAIL_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('inbox', items);
+ });
+ case OPEN_MAIL:
+ return state.withMutations((mutableState) => {
+ const index = state.get('inbox').indexOf(action.mail);
+ mutableState.set('selectedMail', index);
+ });
+ case FILTER_MAIL:
+ return state.withMutations((mutableState) => {
+ mutableState.set('currentPage', action.filter);
+ });
+ case COMPOSE_MAIL:
+ return state.withMutations((mutableState) => {
+ mutableState.set('openFrm', true);
+ });
+ case SEND_MAIL:
+ return state.withMutations((mutableState) => {
+ const newMail = buildMessage(action.to, action.subject, action.content, action.attachment);
+ mutableState
+ .update('inbox', inbox => inbox.unshift(newMail))
+ .set('selectedMailId', '')
+ .set('openFrm', false)
+ .set('notifMsg', notif.sent);
+ });
+ case DISCARD_MESSAGE:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .set('openFrm', false)
+ .set('selectedMailId', '')
+ .set('notifMsg', notif.discard);
+ });
+ case SEARCH_MAIL:
+ return state.withMutations((mutableState) => {
+ action.keyword.persist();
+ const keyword = action.keyword.target.value.toLowerCase();
+ mutableState.set('keywordValue', keyword);
+ });
+ case DELETE_MAIL:
+ return state.withMutations((mutableState) => {
+ const index = state.get('inbox').indexOf(action.mail);
+ mutableState
+ .update('inbox', inbox => inbox.splice(index, 1))
+ .set('notifMsg', notif.removed);
+ });
+ case TOGGLE_STARED:
+ return state.withMutations((mutableState) => {
+ const index = state.get('inbox').indexOf(action.mail);
+ mutableState.update('inbox', inbox => inbox
+ .setIn([index, 'stared'], !state.getIn(['inbox', index, 'stared']))
+ );
+ });
+ case MOVE_TO:
+ return state.withMutations((mutableState) => {
+ const index = state.get('inbox').indexOf(action.mail);
+ mutableState
+ .update('inbox', inbox => inbox
+ .setIn([index, 'category'], action.category)
+ )
+ .set('notifMsg', notif.labeled);
+ });
+ case CLOSE_NOTIF:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/initForm.js b/front/odiparpack/app/redux/modules/initForm.js
new file mode 100644
index 0000000..82bd90b
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/initForm.js
@@ -0,0 +1,22 @@
+import { fromJS, Map } from 'immutable';
+import { INIT, CLEAR } from 'ba-actions/actionTypes';
+
+const initialState = {
+ formValues: Map()
+};
+
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case INIT:
+ return state.withMutations((mutableState) => {
+ mutableState.set('formValues', action.data);
+ });
+ case CLEAR:
+ return state.withMutations((mutableState) => {
+ mutableState.set('formValues', []);
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/login.js b/front/odiparpack/app/redux/modules/login.js
new file mode 100644
index 0000000..add50fb
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/login.js
@@ -0,0 +1,19 @@
+import { Map, fromJS } from 'immutable';
+import { INIT } from 'ba-actions/actionTypes';
+
+const initialState = {
+ usersLogin: Map({
+ email: 'johndoe@mail.com',
+ password: '12345678',
+ remember: false
+ })
+};
+const initialImmutableState = fromJS(initialState);
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case INIT:
+ return state;
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/socialMedia.js b/front/odiparpack/app/redux/modules/socialMedia.js
new file mode 100644
index 0000000..a775f49
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/socialMedia.js
@@ -0,0 +1,110 @@
+import { fromJS, List, Map } from 'immutable';
+import notif from 'ba-api/notifMessage';
+import dummy from 'ba-api/dummyContents';
+import {
+ FETCH_TIMELINE_DATA,
+ POST,
+ TOGGLE_LIKE,
+ FETCH_COMMENT_DATA,
+ POST_COMMENT,
+ CLOSE_NOTIF
+} from 'ba-actions/actionTypes';
+import { getDate, getTime } from '../helpers/dateTimeHelper';
+
+const initialState = {
+ dataTimeline: List([]),
+ commentIndex: 0,
+ notifMsg: '',
+};
+
+const icon = privacyType => {
+ switch (privacyType) {
+ case 'public':
+ return 'language';
+ case 'friends':
+ return 'people';
+ default:
+ return 'lock';
+ }
+};
+
+const buildTimeline = (text, image, privacy) => {
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const imageSrc = image !== undefined ? URL.createObjectURL(image[0]) : '';
+ return Map({
+ id,
+ name: 'John Doe',
+ date: getDate(),
+ time: getTime(),
+ icon: icon(privacy),
+ avatar: dummy.user.avatar,
+ image: imageSrc,
+ content: text,
+ liked: false,
+ comments: List([])
+ });
+};
+
+const buildComment = (message, curData) => {
+ const id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
+ const newData = Map({
+ id,
+ from: 'John Doe',
+ avatar: dummy.user.avatar,
+ date: getDate(),
+ message,
+ });
+ return curData.push(newData);
+};
+
+const initialImmutableState = fromJS(initialState);
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case FETCH_TIMELINE_DATA:
+ return state.withMutations((mutableState) => {
+ const items = fromJS(action.items);
+ mutableState.set('dataTimeline', items);
+ });
+ case POST:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .update(
+ 'dataTimeline',
+ dataTimeline => dataTimeline.unshift(
+ buildTimeline(action.text, action.media, action.privacy)
+ )
+ )
+ .set('notifMsg', notif.posted);
+ });
+ case TOGGLE_LIKE:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTimeline').indexOf(action.item);
+ mutableState.update('dataTimeline', dataTimeline => dataTimeline
+ .setIn([index, 'liked'], !state.getIn(['dataTimeline', index, 'liked']))
+ );
+ });
+ case FETCH_COMMENT_DATA:
+ return state.withMutations((mutableState) => {
+ const index = state.get('dataTimeline').indexOf(action.item);
+ mutableState.set('commentIndex', index);
+ });
+ case POST_COMMENT:
+ return state.withMutations((mutableState) => {
+ mutableState
+ .update('dataTimeline',
+ dataTimeline => dataTimeline.setIn(
+ [state.get('commentIndex'), 'comments'],
+ buildComment(action.comment, state.getIn(['dataTimeline', state.get('commentIndex'), 'comments']))
+ )
+ )
+ .set('notifMsg', notif.commented);
+ });
+ case CLOSE_NOTIF:
+ return state.withMutations((mutableState) => {
+ mutableState.set('notifMsg', '');
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/treeTable.js b/front/odiparpack/app/redux/modules/treeTable.js
new file mode 100644
index 0000000..96fa08a
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/treeTable.js
@@ -0,0 +1,49 @@
+import { fromJS, List } from 'immutable';
+import { TOGGLE_TREE } from 'ba-actions/actionTypes';
+
+const initialState = {
+ treeOpen: List([]),
+ arrowMore: List([])
+};
+
+const initialImmutableState = fromJS(initialState);
+
+// Collect existing child and parent id's
+function collectId(id, listedId, collapsed, arrowLess) {
+ arrowLess.push(id);
+ for (let i = 0; i < listedId.size; i += 1) {
+ if (listedId.getIn([i]).startsWith(id + '_')) {
+ collapsed.push(listedId.getIn([i]));
+ arrowLess.push(listedId.getIn([i]));
+ }
+ }
+}
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ const { branch } = action;
+ switch (action.type) {
+ case `${branch}/${TOGGLE_TREE}`:
+ return state.withMutations((mutableState) => {
+ const listedId = state.get('treeOpen');
+ const collapsed = [];
+ const arrowLess = [];
+
+ // Collect existing id
+ collectId(action.keyID, listedId, collapsed, arrowLess);
+
+ // Collapse and Expand row
+ if (collapsed.length > 0) { // Collapse tree table
+ mutableState.update('treeOpen', treeOpen => treeOpen.filter(x => collapsed.indexOf(x) < 0));
+ mutableState.update('arrowMore', arrowMore => arrowMore.filter(x => arrowLess.indexOf(x) < 0));
+ } else { // Expand tree table
+ mutableState.update('arrowMore', arrowMore => arrowMore.push(action.keyID));
+ action.child.map(item => {
+ mutableState.update('treeOpen', treeOpen => treeOpen.push(item.id));
+ return true;
+ });
+ }
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/modules/ui.js b/front/odiparpack/app/redux/modules/ui.js
new file mode 100644
index 0000000..a0fa4e6
--- /dev/null
+++ b/front/odiparpack/app/redux/modules/ui.js
@@ -0,0 +1,95 @@
+import { fromJS, List } from 'immutable';
+import MenuContent from 'ba-api/menu';
+import {
+ TOGGLE_SIDEBAR,
+ OPEN_SUBMENU,
+ CHANGE_THEME,
+ LOAD_PAGE
+} from 'ba-actions/actionTypes';
+
+const initialState = {
+ sidebarOpen: true,
+ theme: 'purpleRedTheme',
+ pageLoaded: false,
+ palette: List([
+ { name: 'Purple Red', value: 'purpleRedTheme' },
+ { name: 'Natural Green Orange', value: 'greenTheme' },
+ { name: 'Blue Ocean', value: 'blueTheme' },
+ { name: 'Blue Sky', value: 'skyBlueTheme' },
+ { name: 'Sweet Magenta Cyan', value: 'magentaTheme' },
+ { name: 'Violet Green', value: 'purpleTheme' },
+ { name: 'Vintage Yellow', value: 'yellowCyanTheme' },
+ { name: 'Orange Violet', value: 'orangeTheme' },
+ { name: 'Cyan Green', value: 'cyanTheme' },
+ { name: 'Red Silver', value: 'redTheme' },
+ { name: 'Grey', value: 'greyTheme' },
+ { name: 'Green Nature', value: 'greenNatureTheme' },
+ ]),
+ subMenuOpen: []
+};
+
+const getMenus = menuArray => menuArray.map(item => {
+ if (item.child) {
+ return item.child;
+ }
+ return false;
+});
+
+const setNavCollapse = (arr, curRoute) => {
+ let headMenu = 'not found';
+ for (let i = 0; i < arr.length; i += 1) {
+ for (let j = 0; j < arr[i].length; j += 1) {
+ if (arr[i][j].link === curRoute) {
+ headMenu = MenuContent[i].key;
+ }
+ }
+ }
+ return headMenu;
+};
+
+const initialImmutableState = fromJS(initialState);
+
+export default function reducer(state = initialImmutableState, action = {}) {
+ switch (action.type) {
+ case TOGGLE_SIDEBAR:
+ return state.withMutations((mutableState) => {
+ mutableState.set('sidebarOpen', !state.get('sidebarOpen'));
+ });
+ case OPEN_SUBMENU:
+ return state.withMutations((mutableState) => {
+ // Set initial open parent menu
+ const activeParent = setNavCollapse(
+ getMenus(MenuContent),
+ action.initialLocation
+ );
+
+ // Once page loaded will expand the parent menu
+ if (action.initialLocation) {
+ mutableState.set('subMenuOpen', List([activeParent]));
+ return;
+ }
+
+ // Expand / Collapse parent menu
+ const menuList = state.get('subMenuOpen');
+ if (menuList.indexOf(action.key) > -1) {
+ if (action.keyParent) {
+ mutableState.set('subMenuOpen', List([action.keyParent]));
+ } else {
+ mutableState.set('subMenuOpen', List([]));
+ }
+ } else {
+ mutableState.set('subMenuOpen', List([action.key, action.keyParent]));
+ }
+ });
+ case CHANGE_THEME:
+ return state.withMutations((mutableState) => {
+ mutableState.set('theme', action.theme);
+ });
+ case LOAD_PAGE:
+ return state.withMutations((mutableState) => {
+ mutableState.set('pageLoaded', action.isLoaded);
+ });
+ default:
+ return state;
+ }
+}
diff --git a/front/odiparpack/app/redux/reducers.js b/front/odiparpack/app/redux/reducers.js
new file mode 100644
index 0000000..902ab2b
--- /dev/null
+++ b/front/odiparpack/app/redux/reducers.js
@@ -0,0 +1,66 @@
+/**
+ * Combine all reducers in this file and export the combined reducers.
+ */
+import { reducer as form } from 'redux-form/immutable';
+import { combineReducers } from 'redux-immutable';
+import { connectRouter } from 'connected-react-router/immutable';
+import history from 'utils/history';
+
+import languageProviderReducer from 'containers/LanguageProvider/reducer';
+import login from './modules/login';
+import uiReducer from './modules/ui';
+import treeTable from './modules/treeTable';
+import crudTable from './modules/crudTable';
+import crudTableForm from './modules/crudTableForm';
+import socmed from './modules/socialMedia';
+import ecommerce from './modules/ecommerce';
+import contact from './modules/contact';
+import chat from './modules/chat';
+import email from './modules/email';
+import calendar from './modules/calendar';
+import initval from './modules/initForm';
+
+/**
+ * Branching reducers to use one reducer for many components
+ */
+
+function branchReducer(reducerFunction, reducerName) {
+ return (state, action) => {
+ const { branch } = action;
+ const isInitializationCall = state === undefined;
+ if (branch !== reducerName && !isInitializationCall) {
+ return state;
+ }
+ return reducerFunction(state, action);
+ };
+}
+
+/**
+ * Creates the main reducer with the dynamically injected ones
+ */
+export default function createReducer(injectedReducers) {
+ const rootReducer = combineReducers({
+ form,
+ ui: uiReducer,
+ initval,
+ login,
+ socmed,
+ calendar,
+ ecommerce,
+ contact,
+ chat,
+ email,
+ treeTableArrow: branchReducer(treeTable, 'treeTableArrow'),
+ treeTablePM: branchReducer(treeTable, 'treeTablePM'),
+ crudTableDemo: branchReducer(crudTable, 'crudTableDemo'),
+ crudTableForm,
+ crudTbFrmDemo: branchReducer(crudTableForm, 'crudTbFrmDemo'),
+ language: languageProviderReducer,
+ router: connectRouter(history),
+ ...injectedReducers,
+ });
+
+ // Wrap the root reducer and return a new root reducer with router state
+ const mergeWithRouterState = connectRouter(history);
+ return mergeWithRouterState(rootReducer);
+}
diff --git a/front/odiparpack/app/styles/.DS_Store b/front/odiparpack/app/styles/.DS_Store
new file mode 100644
index 0000000..27ec003
Binary files /dev/null and b/front/odiparpack/app/styles/.DS_Store differ
diff --git a/front/odiparpack/app/styles/components/Code.scss b/front/odiparpack/app/styles/components/Code.scss
new file mode 100644
index 0000000..11a105f
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Code.scss
@@ -0,0 +1,9 @@
+.codePre{
+ code{
+ color: #4f00ff;
+ padding: 3px;
+ border: #c1c1c1 1px solid;
+ border-radius: 3px;
+ font-size: 13px;
+ }
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/Form.scss b/front/odiparpack/app/styles/components/Form.scss
new file mode 100644
index 0000000..eb13fe3
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Form.scss
@@ -0,0 +1,24 @@
+@import "./../mixins";
+$sm: "(max-width: 600px)";
+.bodyForm{
+ position: relative;
+ background: $white;
+ padding: 24px;
+ @media #{$sm} {
+ padding: 15px 10px;
+ }
+ max-height: 450px;
+ overflow: auto;
+}
+.buttonArea{
+ background: material-color('grey', '100');
+ position: relative;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ text-align: right;
+ padding: 8px 24px;
+ button{
+ margin-right: 5px;
+ }
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/Messages.scss b/front/odiparpack/app/styles/components/Messages.scss
new file mode 100644
index 0000000..16b61ca
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Messages.scss
@@ -0,0 +1,89 @@
+@import "../../styles/mixins";
+
+@mixin theme() {
+ width: 100%;
+ display: flex;
+ padding: 10px;
+ background: none;
+ border: none;
+}
+
+// Fill Background
+.bgInfo, div.bgInfo{
+ background: material-color('blue', '300');
+ button{
+ color: material-color('blue', '900');
+ }
+}
+.bgSuccess, div.bgSuccess{
+ background: material-color('green', '300');
+ button{
+ color: material-color('green', '900');
+ }
+}
+.bgWarning, div.bgWarning{
+ background: material-color('orange', '300');
+ button{
+ color: material-color('orange', '900');
+ }
+}
+.bgError, div.bgError{
+ background: material-color('red', '300');
+ button{
+ color: material-color('red', '900');
+ }
+}
+.bgDefault, div.bgDefault{
+ background: material-color('grey', '700')
+}
+
+// Fill Background Table Row
+table tr{
+ &.bgInfo{
+ background: material-color('blue', '50')
+ }
+ &.bgSuccess{
+ background: material-color('green', '50')
+ }
+ &.bgWarning{
+ background: material-color('orange', '50')
+ }
+ &.bgError{
+ background: material-color('red', '50')
+ }
+ &.bgDefault{
+ background: #FFF
+ }
+}
+
+// Icon Background
+.messageInfo{
+ @include theme();
+ .icon{
+ background: material-color('blue', '300')
+ }
+}
+.messageSuccess{
+ @include theme();
+ .icon{
+ background: material-color('green', '300')
+ }
+}
+.messageWarning{
+ @include theme();
+ .icon{
+ background: material-color('orange', '300')
+ }
+}
+.messageError{
+ @include theme();
+ .icon{
+ background: material-color('red', '300')
+ }
+}
+.messageDefault{
+ @include theme();
+ .icon{
+ background: material-color('grey', '300')
+ }
+}
diff --git a/front/odiparpack/app/styles/components/Progress.scss b/front/odiparpack/app/styles/components/Progress.scss
new file mode 100644
index 0000000..fdc1757
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Progress.scss
@@ -0,0 +1,18 @@
+@import "../../styles/mixins";
+
+// Fill Background
+.bgInfo div{
+ background: material-color('blue', '300')
+}
+.bgSuccess div{
+ background: material-color('green', '300')
+}
+.bgWarning div{
+ background: material-color('orange', '300')
+}
+.bgError div{
+ background: material-color('red', '300')
+}
+.bgDefault div{
+ background: material-color('grey', '700')
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/Table.scss b/front/odiparpack/app/styles/components/Table.scss
new file mode 100644
index 0000000..04209f0
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Table.scss
@@ -0,0 +1,152 @@
+@import "../../styles/mixins";
+
+.stripped{
+ tbody tr:nth-child(even){
+ background: material-color('grey', '100');
+ }
+}
+
+.hover{
+ tbody tr:hover{
+ background: material-color('grey', '200');
+ }
+}
+
+.bordered{
+ thead tr{
+ background: material-color('grey', '200');
+ }
+ td, th{
+ border: 1px solid material-color('grey', '300');
+ }
+ tr td, tr th{
+ &:first-child{
+ border-left: none
+ }
+ &:last-child{
+ border-right: none
+ }
+ }
+}
+
+table.small{
+ tr{
+ height: 24px;
+ td, th{
+ padding: 4px 10px;
+ font-size: 12px;
+ }
+ }
+}
+
+table.medium{
+ tr{
+ height: 48px;
+ td, th{
+ padding: 4px 56px 4px 24px;
+ font-size: 14px;
+ }
+ }
+}
+
+table.big{
+ tr{
+ height: 64px;
+ td, th{
+ padding: 8px 56px 8px 24px;
+ font-size: 18px;
+ }
+ }
+}
+
+.nodata{
+ text-align: center;
+ padding: 10px 10px 40px;
+ font-size: 14px;
+ line-height: 16px;
+ color: material-color('grey', '500');
+ svg{
+ position: relative;
+ top: 5px;
+ width: 22px;
+ margin: 0 6px;
+ fill: material-color('grey', '500');
+ }
+}
+
+.hideAction{
+ display: none !important;
+}
+
+.tableCrud{
+ table-layout: fixed;
+ .hiddenField{
+ opacity: 0;
+ position: absolute;
+ }
+ .editing{
+ background: material-color('lime', '50');
+ td .crudInput{
+ &:before{
+ opacity: 1;
+ }
+ > * {
+ &:before, &:after{
+ opacity: 1;
+ }
+ }
+ svg, button {
+ visibility: visible;
+ }
+ input[type="text"],
+ input[type="number"],
+ input[type="email"]{
+ width: 100%;
+ }
+ }
+ }
+ th{
+ padding: 0 15px;
+ }
+ td{
+ padding: 0 15px;
+ &.toggleCell{
+ position: relative;
+ }
+ vertical-align: middle;
+ .coverReadonly{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 2;
+ display: none;
+ &.show{
+ display: block;
+ }
+ }
+ .crudInput{
+ &:before{
+ opacity: 0;
+ }
+ color: material-color('grey', '900');
+ > * > input {
+ color: material-color('grey', '900');
+ &:before, &:after{
+ opacity: 0;
+ }
+ }
+ svg, button {
+ visibility: hidden;
+ }
+ }
+ }
+ td [disabled], td[disabled]:hover{
+ border: none !important;
+ box-shadow: none;
+ cursor: text;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: none;
+ }
+}
diff --git a/front/odiparpack/app/styles/components/TextEditor.scss b/front/odiparpack/app/styles/components/TextEditor.scss
new file mode 100644
index 0000000..1110532
--- /dev/null
+++ b/front/odiparpack/app/styles/components/TextEditor.scss
@@ -0,0 +1,24 @@
+@import "../../styles/mixins";
+
+.TextEditor{
+ background: #fff;
+ min-height: 200px;
+ border: 1px solid material-color('grey', '300');
+ padding: 0 10px;
+}
+
+.ToolbarEditor{
+ background: material-color('grey', '50');
+ border: none;
+}
+
+.textPreview{
+ width: 100%;
+ resize: none;
+ height: 305px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: material-color('grey', '300');
+ border-image: initial;
+ padding: 5px;
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/Typography.scss b/front/odiparpack/app/styles/components/Typography.scss
new file mode 100644
index 0000000..bf179e3
--- /dev/null
+++ b/front/odiparpack/app/styles/components/Typography.scss
@@ -0,0 +1,101 @@
+@import url('https://fonts.googleapis.com/css?family=Roboto:100,700,900');
+@import "../../styles/mixins";
+
+// Font Weight
+.lighter{
+ font-weight: 100
+}
+.light{
+ font-weight: 300
+}
+.regular{
+ font-weight: 400
+}
+.medium{
+ font-weight: 500
+}
+.bold{
+ font-weight: 700
+}
+.bolder{
+ font-weight: 900
+}
+
+// Font stlye
+.italic {
+ font-style: italic
+}
+.underline {
+ text-decoration: underline
+}
+.lineThrought {
+ text-decoration: line-through
+}
+
+// Color
+.textInfo{
+ color: material-color('blue', '500') !important;
+}
+.textSuccess{
+ color: material-color('green', '500') !important;
+}
+.textWarning{
+ color: material-color('orange', '500') !important;
+}
+.textError{
+ color: material-color('red', '500') !important;
+}
+.textGreyDark{
+ color: material-color('blue-grey', '900') !important;
+}
+.textGrey{
+ color: material-color('blue-grey', '400') !important;
+}
+.textGreyLight{
+ color: material-color('blue-grey', '100') !important;
+}
+
+// Transform
+.capitalyze{
+ text-transform: capitalize
+}
+.uppercase{
+ text-transform: uppercase
+}
+.lowercase{
+ text-transform: lowercase
+}
+
+// Align
+.textLeft{
+ text-align: left
+}
+.textRight{
+ text-align: right
+}
+.textCenter{
+ text-align: center;
+}
+.textJustify{
+ text-align: justify;
+}
+
+// List
+.list{
+ list-style: disc;
+ margin-left: 20px;
+ ul {
+ list-style: circle;
+ margin-left: 20px;
+ }
+}
+
+.orderedlist{
+ list-style: decimal;
+ margin-left: 20px;
+ ul {
+ list-style: lower-alpha;
+ margin-left: 20px;
+ }
+}
+
diff --git a/front/odiparpack/app/styles/components/vendors/emoji-picker-react/emoji-picker-react.css b/front/odiparpack/app/styles/components/vendors/emoji-picker-react/emoji-picker-react.css
new file mode 100644
index 0000000..796ec48
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/emoji-picker-react/emoji-picker-react.css
@@ -0,0 +1,625 @@
+.emoji-picker .icn-magnifier:before {
+ background-image: url("data:image/svg+xml,%3Csvg id='Capa_1' xmlns='http://www.w3.org/2000/svg' width='310.4' height='310.4'%3E%3Cstyle%3E.st0%7Bfill:%239e9e9e%7D%3C/style%3E%3Cpath class='st0' d='M273.6 215c49.1-49.1 49.1-129 0-178.1-49.1-49.1-129-49.1-178.1 0-41.7 41.7-48 103.6-18.9 152 0 0 2.1 3.5-.7 6.3l-64.3 64.3c-12.8 12.8-15.8 30.7-4.5 42l2 2c11.3 11.3 29.2 8.3 42-4.5l64.1-64.1c3-3 6.4-.9 6.4-.9 48.4 28.9 110.3 22.6 152-19zm-154.9-23.3c-36.3-36.3-36.3-95.3 0-131.6s95.3-36.3 131.6 0 36.3 95.3 0 131.6-95.3 36.3-131.6 0z'/%3E%3Cpath class='st0' d='M126.8 118.4c-1.7 0-3.4-.3-5.1-1-6.6-2.8-9.7-10.4-6.9-17 17.6-41.6 65.7-61.1 107.3-43.5 6.6 2.8 9.7 10.4 6.9 17-2.8 6.6-10.4 9.7-17 6.9-28.4-12-61.2 1.3-73.2 29.7-2.2 4.9-7 7.9-12 7.9z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker ul.skin-tones {
+ position: absolute;
+ right: 0;
+}
+
+.emoji-picker ul.skin-tones.spread li {
+ opacity: 1;
+}
+
+.emoji-picker ul.skin-tones li {
+ position: absolute;
+ top: 16px;
+ right: 20px;
+ z-index: 3;
+ padding: 1px;
+ border-radius: 3px;
+ opacity: 0;
+ transition: transform .4s, opacity .3s;
+}
+
+.emoji-picker ul.skin-tones li.selected {
+ opacity: 1;
+ transform: scale(1.5);
+}
+
+.emoji-picker ul.skin-tones li.neutral a {
+ background-color: #ffe082;
+}
+
+.emoji-picker ul.skin-tones li.m1f3fb a {
+ background-color: #ffe0b2;
+}
+
+.emoji-picker ul.skin-tones li.m1f3fc a {
+ background-color: #ffccbc;
+}
+
+.emoji-picker ul.skin-tones li.m1f3fe a {
+ background-color: #795548;
+}
+
+.emoji-picker ul.skin-tones li.m1f3ff a {
+ background-color: #5d4037;
+}
+
+.emoji-picker ul.skin-tones li.m1f3fd a {
+ background-color: #ca7e55;
+}
+
+.emoji-picker ul.skin-tones li a {
+ display: block;
+ height: 10px;
+ width: 10px;
+ border-radius: 2px;
+}
+
+.emoji-picker ul.skin-tones li a img {
+ z-index: 2;
+ height: 10px;
+ width: 10px;
+}
+
+.emoji-picker nav ~ .bar-wrapper {
+ margin-top: 45px;
+ border-top: 1px solid #eeeeee;
+}
+
+.emoji-picker nav {
+ flex-direction: row;
+ min-height: 45px;
+ background-color: #ffffff;
+ display: flex;
+ justify-content: space-between;
+ position: absolute;
+ z-index: 1;
+ box-sizing: border-box;
+ left: 10px;
+ right: 10px;
+}
+
+.emoji-picker nav a {
+ position: relative;
+ transition: filter .2s;
+}
+
+.emoji-picker nav a:hover:after {
+ opacity: 1;
+ background-color: #a5d6a7;
+}
+
+.emoji-picker nav a:hover i {
+ opacity: 1;
+}
+
+.emoji-picker nav a i {
+ content: '';
+ display: block;
+ height: 45px;
+ width: 20px;
+ background-size: 18px auto;
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ opacity: .4;
+ transition: opacity .3s;
+ transition-delay: .2s;
+}
+
+.emoji-picker nav a.people i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 33 33'%3E%3Cpath d='M16.5 33C7.402 33 0 25.598 0 16.5S7.402 0 16.5 0 33 7.402 33 16.5 25.598 33 16.5 33zm0-32C7.953 1 1 7.953 1 16.5S7.953 32 16.5 32 32 25.047 32 16.5 25.047 1 16.5 1z'/%3E%3Cpath d='M16.5 33a16.38 16.38 0 0 1-9.549-3.06.5.5 0 1 1 .116-.876c4.146-1.535 4.815-2.781 4.815-5.169 0-.631-.142-.838-.398-1.214-.339-.494-.803-1.171-1.129-2.939-.048-.254-.089-.274-.316-.384-.606-.292-1.163-.712-1.309-2.628 0-.928.32-1.441.585-1.708-.058-.33-.153-.899-.242-1.519-.453-2.777-.473-6.178 3.433-7.759 3.404-1.38 6.121-.626 6.974.273.604.019 2.162.177 3.246 1.438 1.668 1.94 1.137 6.363.955 7.562.266.261.589.767.589 1.675-.146 1.954-.703 2.375-1.31 2.666-.228.11-.269.129-.316.384-.326 1.768-.789 2.445-1.128 2.939-.257.375-.398.583-.398 1.214 0 2.388.669 3.634 4.815 5.169a.498.498 0 0 1 .116.876A16.38 16.38 0 0 1 16.5 33zm-8.183-3.349C10.779 31.191 13.589 32 16.5 32s5.721-.809 8.183-2.349c-3.474-1.426-4.565-2.864-4.565-5.755 0-.941.278-1.348.573-1.779.304-.444.682-.996.971-2.556.139-.754.576-.964.865-1.103.311-.149.631-.303.744-1.803-.001-.764-.344-.972-.358-.98a.533.533 0 0 1-.264-.537c.248-1.329.656-5.474-.681-7.031-.913-1.062-2.352-1.091-2.626-1.08-.046-.004-.091-.005-.134-.016-.13-.033-.35-.146-.417-.262-.272-.466-2.641-1.403-5.91-.08-3.231 1.308-3.238 4.112-2.819 6.682.138.957.289 1.784.29 1.788a.5.5 0 0 1-.283.544c.003 0-.339.209-.339 1.008.112 1.461.433 1.616.743 1.765.289.139.727.349.866 1.103.288 1.56.666 2.112.97 2.556.296.431.574.838.574 1.779 0 2.894-1.091 4.332-4.566 5.757z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.foods i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M337.502 61.244c-46.267-19.341-98.094-21.573-145.933-6.282-5.497 1.758-8.528 7.638-6.772 13.134 1.758 5.497 7.64 8.528 13.134 6.772 43.115-13.782 89.819-11.772 131.51 5.657 1.317.55 2.682.811 4.026.811 4.087 0 7.969-2.415 9.644-6.422 2.228-5.324-.284-11.445-5.609-13.67zM368.323 77.252a11.31 11.31 0 0 0-.375-.239c-4.925-3.009-11.356-1.458-14.364 3.467-2.984 4.884-1.483 11.249 3.346 14.29a10.398 10.398 0 0 0 5.587 1.626c3.377 0 6.69-1.633 8.704-4.654 3.201-4.801 1.904-11.289-2.898-14.49zM447.293 161.884c-4.081-4.08-10.698-4.08-14.778 0l-14.629 14.629c-4.08 4.081-4.08 10.698 0 14.778 2.04 2.041 4.715 3.06 7.388 3.06s5.349-1.02 7.389-3.06l14.629-14.629c4.081-4.081 4.081-10.698.001-14.778zM83.999 214.617c-4.081-4.08-10.698-4.08-14.778 0l-14.629 14.629c-4.08 4.081-4.08 10.698 0 14.778 2.04 2.041 4.715 3.06 7.388 3.06s5.349-1.02 7.39-3.06l14.629-14.629c4.081-4.082 4.081-10.698 0-14.778zM115.508 100.235c-4.081-4.08-10.698-4.08-14.778 0l-14.629 14.629c-4.08 4.081-4.08 10.698 0 14.778 2.04 2.041 4.715 3.06 7.388 3.06s5.348-1.02 7.39-3.06l14.629-14.629c4.081-4.081 4.081-10.698 0-14.778zM386.754 116.24h-20.688c-5.771 0-10.449 4.678-10.449 10.449s4.678 10.449 10.449 10.449h20.688c5.771 0 10.449-4.678 10.449-10.449s-4.678-10.449-10.449-10.449zM151.326 161.908l-14.618-14.618c-4.081-4.08-10.698-4.081-14.778 0s-4.08 10.698 0 14.778l14.618 14.618a10.413 10.413 0 0 0 7.388 3.06c2.674 0 5.349-1.02 7.39-3.06 4.081-4.081 4.081-10.698 0-14.778zM411.753 229.241l-14.618-14.617c-4.08-4.081-10.696-4.08-14.777 0s-4.08 10.697 0 14.777l14.618 14.617c2.041 2.041 4.715 3.06 7.388 3.06s5.348-1.021 7.388-3.06c4.083-4.08 4.082-10.696.001-14.777zM318.326 126.607l-14.617-14.617c-4.081-4.08-10.698-4.081-14.778 0s-4.08 10.698 0 14.778l14.617 14.617a10.414 10.414 0 0 0 7.388 3.061 10.42 10.42 0 0 0 7.39-3.061c4.08-4.081 4.08-10.698 0-14.778zM195.194 97.387c-3.904-4.25-10.515-4.528-14.763-.622l-15.22 13.989c-4.249 3.905-4.527 10.515-.622 14.763a10.42 10.42 0 0 0 7.696 3.378c2.528 0 5.063-.911 7.068-2.756l15.22-13.989c4.248-3.905 4.526-10.515.621-14.763zM256.153 145.241H255.865c-5.762 0-10.437 4.665-10.449 10.429-.011 5.771 4.658 10.457 10.429 10.469H256.134c5.762 0 10.438-4.664 10.449-10.429.01-5.771-4.659-10.458-10.43-10.469z'/%3E%3Cpath d='M437.019 74.981C388.668 26.628 324.38 0 256 0S123.332 26.628 74.981 74.981C26.629 123.333 0 187.62 0 256c0 68.38 26.628 132.668 74.981 181.019C123.333 485.371 187.62 512 256 512c68.38 0 132.668-26.628 181.019-74.981C485.371 388.667 512 324.38 512 256s-26.628-132.668-74.981-181.019zM256 491.102c-94.256 0-175.718-55.763-213.173-136.024 6.781-.56 13.126-3.458 18.112-8.35 5.756-5.647 9.057-13.495 9.057-21.531v-9.364c0-7.449 6.027-13.624 13.435-13.767 3.561-.079 6.976 1.322 9.617 3.913 2.77 2.718 4.359 6.484 4.359 10.332v23.709c0 18.754 15.222 34.302 33.932 34.66.221.004.442.006.664.006 8.973 0 17.47-3.499 23.989-9.895 6.751-6.623 10.623-15.826 10.623-25.25v-18.215c20.172 27.524 52.723 45.432 89.384 45.432 52.209 0 96.09-36.312 107.73-85.007a10.027 10.027 0 0 1 2.18 6.23v25.773c0 19.673 15.968 35.984 35.596 36.361.233.004.464.006.696.006 9.409 0 18.321-3.671 25.161-10.38 7.086-6.951 11.149-16.61 11.149-26.5v-24.856c0-2.83 1.17-5.6 3.21-7.602 1.927-1.889 4.429-2.882 6.986-2.854 5.403.104 9.8 4.612 9.8 10.05v2.721c0 14.409 10.071 26.69 23.526 30.04C453.848 418.996 363.189 491.102 256 491.102zm223.405-200.399v-2.721c0-16.741-13.591-30.624-30.297-30.944-8.235-.159-16.057 2.978-22.022 8.829-6.021 5.906-9.473 14.113-9.473 22.52v24.856c0 4.314-1.782 8.536-4.886 11.582-2.97 2.912-6.846 4.462-10.82 4.397-8.326-.16-15.099-7.098-15.099-15.468v-25.773c0-13.154-8.392-24.538-20.091-28.971.027-1.001.043-2.004.043-3.011 0-46.06-29.007-87.788-72.182-103.836-5.411-2.01-11.425.745-13.434 6.154-2.01 5.409.745 11.424 6.154 13.434 35.027 13.021 58.562 46.877 58.562 84.248 0 49.549-40.312 89.861-89.861 89.861-49.549 0-89.861-40.312-89.861-89.861 0-37.372 23.535-71.228 58.565-84.246 5.409-2.01 8.164-8.026 6.154-13.434s-8.022-8.165-13.434-6.154C174.248 168.21 145.239 209.938 145.239 256a110.22 110.22 0 0 0 7.085 38.971 30.145 30.145 0 0 0-6.607 18.808v25.763c0 3.848-1.589 7.614-4.359 10.332-2.642 2.591-6.036 3.973-9.617 3.913-7.407-.142-13.434-6.317-13.434-13.766v-23.709c0-9.424-3.872-18.627-10.623-25.251-6.681-6.554-15.435-10.081-24.652-9.889-18.71.358-33.932 15.907-33.932 34.66v9.364c0 2.461-1.019 4.871-2.794 6.613-1.668 1.635-3.808 2.506-6.034 2.47-3.374-.065-6.387-2.139-7.733-5.21-7.543-23.011-11.64-47.569-11.64-73.07C20.898 126.365 126.365 20.898 256 20.898S491.102 126.365 491.102 256c0 15.182-1.464 30.026-4.227 44.414-4.281-1.138-7.47-5.083-7.47-9.711z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.nature i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 470 470'%3E%3Cpath d='M401.17 68.83C356.784 24.444 297.771 0 235 0S113.216 24.444 68.83 68.83 0 172.229 0 235s24.444 121.784 68.83 166.17S172.229 470 235 470s121.784-24.444 166.17-68.83S470 297.771 470 235s-24.444-121.784-68.83-166.17zM235 455c-121.309 0-220-98.691-220-220S113.691 15 235 15s220 98.691 220 220-98.691 220-220 220z'/%3E%3Cpath d='M382.5 173.979c3.532 0 6.735 1.824 8.568 4.879a7.499 7.499 0 0 0 12.864 0c1.833-3.055 5.036-4.879 8.568-4.879 4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5c-5.461 0-10.724 1.829-15 5.039-4.276-3.21-9.539-5.039-15-5.039-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5zM322.5 135.459c3.532 0 6.735 1.824 8.568 4.879a7.499 7.499 0 0 0 12.864 0c1.833-3.055 5.036-4.879 8.568-4.879 4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5c-5.461 0-10.724 1.829-15 5.039-4.276-3.21-9.539-5.039-15-5.039-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5zM117.5 173.979c3.532 0 6.735 1.824 8.568 4.879a7.499 7.499 0 0 0 12.864 0c1.833-3.055 5.036-4.879 8.568-4.879 4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5c-5.461 0-10.724 1.829-15 5.039-4.276-3.21-9.539-5.039-15-5.039-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5zM436.826 253.173a7.5 7.5 0 0 0-5.443-2.6c-12.664-.4-24.343-7.548-32.041-19.608a7.5 7.5 0 0 0-12.643-.001c-7.974 12.489-20.074 19.652-33.2 19.652-13.089 0-25.177-7.164-33.162-19.656a7.502 7.502 0 0 0-12.635-.004c-8 12.494-20.098 19.66-33.192 19.66-13.098 0-25.189-7.164-33.175-19.656a7.5 7.5 0 0 0-12.64.004c-7.974 12.489-20.069 19.652-33.187 19.652-13.098 0-25.19-7.164-33.176-19.656a7.502 7.502 0 0 0-12.635-.004c-8 12.494-20.098 19.66-33.191 19.66-13.099 0-25.19-7.164-33.175-19.655a7.5 7.5 0 0 0-12.64.004c-7.699 12.061-19.389 19.207-32.07 19.608a7.494 7.494 0 0 0-5.443 2.6 7.497 7.497 0 0 0-1.769 5.767c5.786 49.506 29.545 95.215 66.901 128.706C135.964 421.407 184.509 440 235 440c45.241 0 88.17-14.518 124.145-41.982a7.498 7.498 0 0 0 1.41-10.512 7.496 7.496 0 0 0-10.512-1.41C316.705 411.547 276.924 425 235 425c-93.882 0-173.276-68.424-187.68-160.366 11.265-2.217 21.561-8.215 29.707-17.284 10.49 11.584 24.673 18.267 39.476 18.267 14.808 0 29.002-6.691 39.505-18.291 10.493 11.6 24.685 18.291 39.498 18.291 14.828 0 29.022-6.689 39.511-18.284 10.493 11.595 24.682 18.284 39.491 18.284 14.808 0 29.002-6.691 39.505-18.291 10.493 11.6 24.679 18.291 39.485 18.291 14.826 0 29.018-6.681 39.505-18.264 8.14 9.065 18.422 15.061 29.671 17.278-6.044 38.177-24.008 74.246-51.068 102.269a7.5 7.5 0 1 0 10.791 10.419c31.08-32.185 51.038-74.226 56.198-118.38a7.495 7.495 0 0 0-1.769-5.766z'/%3E%3Cpath d='M289.513 310.616c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h10c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-10zM358.49 280.616h-10c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h10c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5zM111.503 280.616c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h10c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-10zM235 191.25c30.327 0 55-24.673 55-55s-24.673-55-55-55-55 24.673-55 55 24.673 55 55 55zm0-95c22.056 0 40 17.944 40 40s-17.944 40-40 40-40-17.944-40-40 17.944-40 40-40z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.activity i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath d='M32 0C14.355 0 0 14.355 0 32s14.355 32 32 32 32-14.355 32-32S49.645 0 32 0zm29.624 36.731l-3.885-6.439 2.681-7.88a29.867 29.867 0 0 1 1.204 14.319zm-7.558 15.567a.994.994 0 0 0-.408-.02L43.98 53.83a.993.993 0 0 0-.123-.345l-5.502-9.17 8.896-13.7h8.428a.992.992 0 0 0 .105.312l5.236 8.678a29.956 29.956 0 0 1-6.954 12.693zm-10.085 3.557l7.688-1.232a29.958 29.958 0 0 1-11.706 6.296l4.018-5.064zM12.65 9.1a29.858 29.858 0 0 1 18.628-7.082.982.982 0 0 0 .24.376l5.525 5.214-2.185 8.156-14.237 5.465c-.052-.042-.093-.094-.154-.126l-8.87-4.701L12.65 9.1zm25.736-2.976l-4.283-4.042a29.763 29.763 0 0 1 10.989 2.931l-6.706 1.111zM21.93 38.737l-.816-15.554L35.655 17.6l9.803 12.106-8.483 13.063-15.045-4.032zm37.375-19.141c-.031.054-.072.098-.093.159l-3.015 8.86h-9.048L36.882 15.937l2.113-7.887 8.27-1.371a.979.979 0 0 0 .453-.218 30.2 30.2 0 0 1 11.587 13.135zm-48.994-8.289l-.802 5.561-5.349 3.975a30.035 30.035 0 0 1 6.151-9.536zm-7.255 12.82c.044-.023.09-.037.131-.068l7.737-5.751 8.158 4.323.888 16.936c.002.025.013.048.016.073l-7.71 7.629c-.066.065-.105.145-.149.222L4.734 44.32c-.028-.012-.057-.009-.085-.018A29.822 29.822 0 0 1 2 32c0-2.725.372-5.362 1.056-7.873zm3.022 22.945l5.415 2.322 4.141 7.729a30.222 30.222 0 0 1-9.556-10.051zm12.759 11.879c-.019-.064-.025-.131-.058-.192l-5.317-9.924c.076-.043.155-.08.22-.145l8.027-7.942 14.507 3.888 5.927 9.879c.05.083.11.154.178.217l-5.449 6.867c-1.587.26-3.213.401-4.872.401-4.72 0-9.186-1.099-13.163-3.049z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.objects i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58.153 58.153'%3E%3Cpath d='M40.076 29.153h-7.142a3.995 3.995 0 0 0-2.858-2.858V16.153a1 1 0 1 0-2 0v10.142c-1.72.447-3 1.999-3 3.858 0 2.206 1.794 4 4 4 1.858 0 3.411-1.28 3.858-3h7.142a1 1 0 1 0 0-2zm-11 3c-1.103 0-2-.897-2-2s.897-2 2-2 2 .897 2 2-.897 2-2 2z'/%3E%3Cpath d='M50.188 9.764l4.096 4.096a1 1 0 0 0 1.414 0c3.167-3.166 3.167-8.319 0-11.485s-8.319-3.166-11.485 0a.997.997 0 0 0 0 1.414l4.561 4.561-1.699 1.699c-4.78-4.284-11.089-6.896-17.998-6.896s-13.218 2.612-17.998 6.896l-1.7-1.699 4.561-4.561a.997.997 0 0 0 0-1.414c-3.166-3.166-8.318-3.166-11.485 0s-3.167 8.319 0 11.485a1 1 0 0 0 1.414 0l4.096-4.096 1.676 1.676c-4.679 4.857-7.565 11.453-7.565 18.713 0 9.898 5.357 18.564 13.321 23.265l-3.028 3.028a.999.999 0 1 0 1.414 1.414l3.45-3.45c3.578 1.754 7.597 2.743 11.843 2.743s8.265-.989 11.843-2.743l3.45 3.45a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414l-3.028-3.028c7.964-4.701 13.321-13.367 13.321-23.265 0-7.26-2.886-13.856-7.565-18.713l1.677-1.676zm4.095-5.975c2.146 2.146 2.362 5.502.649 7.893L46.391 3.14a6.13 6.13 0 0 1 7.892.649zM3.22 11.681c-1.713-2.39-1.497-5.746.649-7.892s5.502-2.361 7.892-.649L3.22 11.681zm25.856 43.472c-13.785 0-25-11.215-25-25s11.215-25 25-25 25 11.215 25 25-11.214 25-25 25z'/%3E%3Cpath d='M29.076 10.032a1 1 0 0 0 1-1v-1a1 1 0 1 0-2 0v1a1 1 0 0 0 1 1zM29.076 50.032a1 1 0 0 0-1 1v1a1 1 0 1 0 2 0v-1a1 1 0 0 0-1-1zM50.076 31.032h1a1 1 0 1 0 0-2h-1a1 1 0 1 0 0 2zM8.076 29.032h-1a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2zM43.926 13.768l-.707.707a.999.999 0 1 0 1.414 1.414l.707-.707a.999.999 0 1 0-1.414-1.414zM13.52 44.174l-.707.707a.999.999 0 1 0 1.414 1.414l.707-.707a.999.999 0 1 0-1.414-1.414zM44.633 44.174a.999.999 0 1 0-1.414 1.414l.707.707a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414l-.707-.707zM14.227 13.768a.999.999 0 1 0-1.414 1.414l.707.707a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414l-.707-.707z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.places i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 470 470'%3E%3Cpath d='M401.17 68.83C356.784 24.444 297.771 0 235 0S113.216 24.444 68.83 68.83C24.444 113.215 0 172.229 0 235s24.444 121.785 68.83 166.17C113.216 445.556 172.229 470 235 470s121.784-24.444 166.17-68.83C445.556 356.785 470 297.771 470 235s-24.444-121.785-68.83-166.17zM235 455c-121.309 0-220-98.691-220-220S113.691 15 235 15s220 98.691 220 220-98.691 220-220 220z'/%3E%3Ccircle cx='235' cy='97.5' r='7.5'/%3E%3Cpath d='M437.56 242.365a7.501 7.501 0 0 0-5.467-2.365h-26.046v-22.5c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5V240H372.5v-52.5a7.5 7.5 0 0 0-3.525-6.36L292.5 133.343V97.5A7.5 7.5 0 0 0 285 90h-13.253C268.262 72.905 253.109 60 235 60s-33.262 12.905-36.747 30H185a7.5 7.5 0 0 0-7.5 7.5V130h-25v-22.5c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5V130H105a7.5 7.5 0 0 0-7.5 7.5v102.499l-59.593-.01a7.504 7.504 0 0 0-7.487 7.969c3.523 56.171 29.666 105.984 69.187 140.798.281.291.587.556.911.799 23.389 20.362 51.39 35.496 82.128 43.638.307.102.622.184.946.246A204.258 204.258 0 0 0 235 440c17.409 0 34.679-2.229 51.386-6.558a7.297 7.297 0 0 0 1.002-.262 203.842 203.842 0 0 0 50.574-20.966c30.222-17.629 55.631-42.86 73.479-72.965a7.5 7.5 0 0 0-12.902-7.65 189.49 189.49 0 0 1-26.039 34.299V255h51.438a188.457 188.457 0 0 1-12.616 50.728 7.499 7.499 0 0 0 4.156 9.758 7.498 7.498 0 0 0 9.758-4.157 203.511 203.511 0 0 0 14.342-63.359 7.499 7.499 0 0 0-2.018-5.605zM192.5 175h85v215h-85V175zm0-70H205a7.5 7.5 0 0 0 7.5-7.5c0-12.407 10.094-22.5 22.5-22.5s22.5 10.093 22.5 22.5a7.5 7.5 0 0 0 7.5 7.5h12.5v55h-85v-55zM46.059 254.99l51.441.009V307.5c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5V145h65v245H175c-4.143 0-7.5 3.358-7.5 7.5s3.357 7.5 7.5 7.5h2.5v11.078c-24.056-7.668-46.091-20.018-65-35.997V337.5c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v28.458c-28.127-29.492-46.937-68.033-51.441-110.968zM192.5 420.179V405h85v15.106A187.644 187.644 0 0 1 235 425a189.427 189.427 0 0 1-42.5-4.821zm100-4.235V405h2.5c4.143 0 7.5-3.358 7.5-7.5s-3.357-7.5-7.5-7.5h-2.5V151.032l65 40.625v188.307a191.989 191.989 0 0 1-65 35.98z'/%3E%3Cpath d='M325 320a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM325 280a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM325 240a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM325 200a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM145 345a7.5 7.5 0 0 0 7.5-7.5v-10c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v10a7.5 7.5 0 0 0 7.5 7.5zM145 305a7.5 7.5 0 0 0 7.5-7.5v-10c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v10a7.5 7.5 0 0 0 7.5 7.5zM145 265a7.5 7.5 0 0 0 7.5-7.5v-10c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v10a7.5 7.5 0 0 0 7.5 7.5zM145 185a7.5 7.5 0 0 0 7.5-7.5v-10c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v10a7.5 7.5 0 0 0 7.5 7.5zM145 225a7.5 7.5 0 0 0 7.5-7.5v-10c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v10a7.5 7.5 0 0 0 7.5 7.5zM235 350a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM235 310a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM235 270a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM235 230a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM235 190a7.5 7.5 0 0 0-7.5 7.5v10c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-10a7.5 7.5 0 0 0-7.5-7.5zM215 145h40c4.143 0 7.5-3.358 7.5-7.5s-3.357-7.5-7.5-7.5h-40c-4.143 0-7.5 3.358-7.5 7.5s3.357 7.5 7.5 7.5z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.flags i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 502 502'%3E%3Cpath d='M428.484 73.516C381.076 26.108 318.044 0 251 0S120.924 26.108 73.516 73.516 0 183.956 0 251s26.108 130.076 73.516 177.484S183.956 502 251 502s130.076-26.108 177.484-73.516C475.892 381.076 502 318.044 502 251s-26.108-130.076-73.516-177.484zM283.829 39h58.868c58.354 25.338 104.274 74.079 125.849 134.317h-41.725a21.139 21.139 0 0 0-19.587 13.087 21.139 21.139 0 0 0 4.595 23.104l3.3 3.3c4.638 4.637 4.638 12.184 0 16.821a11.42 11.42 0 0 1-8.13 3.368 11.422 11.422 0 0 1-8.13-3.368l-7.969-7.969c-13.135-13.135-30.599-20.369-49.175-20.369h-6.397v-8.036c0-19.265-7.502-37.376-21.124-50.999l-9.952-9.952c-10.216-10.216-23.799-15.843-38.247-15.843h-19.931c-7.721 0-14.98 3.007-20.439 8.466l-5.17 5.169c-5.459 5.459-8.466 12.718-8.466 20.439a4.736 4.736 0 0 1-4.73 4.73h-8.66v-12.154c0-8.648 3.368-16.78 9.483-22.895l5.849-5.849c5.244-5.243 8.131-12.214 8.131-19.629V92.71c0-.394.32-.713.713-.713H320.5c12.407 0 22.5-10.093 22.5-22.5S332.907 47 320.5 47h-36.671c-2.206 0-4-1.794-4-4s1.794-4 4-4zm74.893 252.437l-5.452 5.484a155.066 155.066 0 0 0-22.913 29.41l-9.918 16.5-12.403 20.492a48.673 48.673 0 0 0-7.036 25.21v.615a.857.857 0 0 1-.856.856h-.004a8.78 8.78 0 0 1-6.247-2.586 8.776 8.776 0 0 1-2.589-6.25c0-12.58-4.899-24.407-13.794-33.303l-4.591-4.591c-6.947-6.947-10.773-16.183-10.773-26.007v-29.475c0-14.806-12.045-26.851-26.852-26.851H231.8c-8.349 0-15.142-6.792-15.142-15.142v-15.343c0-9.034 7.35-16.384 16.384-16.384h79.886l24.099 24.1c6.003 6.003 9.309 13.984 9.309 22.473v11.464c0 8.56 5.082 15.955 12.386 19.328zM20 251c0-9.444.583-18.752 1.69-27.902h30.619c10.153 0 19.698 3.954 26.876 11.133l8.781 8.78c7.527 7.527 17.534 11.672 28.179 11.672 5.65 0 10.962 2.2 14.957 6.195l.193.193c7.233 7.233 11.217 16.851 11.217 27.081v17.886c0 13.63-5.308 26.444-14.945 36.082l-19.15 19.15c-13.442 13.443-21.939 30.512-24.58 49.002C44.303 368.799 20 312.684 20 251zm231 231c-56.288 0-107.93-20.247-148.049-53.827v-5.423c0-17.881 6.963-34.693 19.607-47.337l19.15-19.15c13.415-13.416 20.803-31.252 20.803-50.224v-17.886c0-15.573-6.064-30.213-17.075-41.224l-.193-.192c-7.772-7.772-18.106-12.053-29.099-12.053a19.72 19.72 0 0 1-14.036-5.814l-8.781-8.781c-10.957-10.956-25.524-16.99-41.019-16.99h-27.3C47.126 98.635 140.047 20 251 20c7.743 0 15.396.39 22.946 1.138-8.316 3.774-14.117 12.151-14.117 21.862 0 13.234 10.766 24 24 24H320.5c1.378 0 2.5 1.122 2.5 2.5s-1.122 2.5-2.5 2.5h-97.713c-11.421 0-20.713 9.292-20.713 20.713v2.028a7.706 7.706 0 0 1-2.273 5.486l-5.85 5.85c-9.893 9.893-15.341 23.047-15.341 37.037v13.574c0 10.245 8.334 18.58 18.579 18.58h10.081c13.636 0 24.73-11.094 24.73-24.73 0-2.379.926-4.615 2.608-6.297l5.169-5.169c.203-.203.414-.393.632-.574.167.195.334.389.518.574l19.932 19.932c-3.833 3.911-3.813 10.186.068 14.068 1.953 1.953 4.512 2.929 7.071 2.929s5.119-.976 7.071-2.929l7-7c3.905-3.905 3.905-10.237 0-14.143l-15.45-15.45c8.875.156 17.197 3.677 23.489 9.97l9.953 9.952c9.844 9.844 15.266 22.934 15.266 36.856v.817H233.04c-20.062 0-36.384 16.322-36.384 36.384V245.8c0 19.377 15.765 35.142 35.142 35.142h3.493a6.86 6.86 0 0 1 6.852 6.851v29.475c0 15.167 5.906 29.425 16.63 40.15l4.591 4.591c5.118 5.118 7.937 11.923 7.937 19.161 0 7.705 3.001 14.948 8.451 20.396 5.446 5.443 12.685 8.44 20.384 8.44h.015C311.648 410 321 400.644 321 389.149v-.614a28.68 28.68 0 0 1 4.146-14.854l12.409-20.502a.226.226 0 0 1 .016-.026l9.928-16.517a135.064 135.064 0 0 1 19.955-25.613l11.147-11.213c4.428-4.455 5.731-11.08 3.319-16.879s-8.029-9.546-14.31-9.546a1.274 1.274 0 0 1-1.273-1.273v-11.464c0-13.832-5.386-26.835-15.167-36.616l-2.215-2.215c10.49 1.524 20.173 6.357 27.804 13.988l7.969 7.969c6.141 6.141 14.207 9.211 22.272 9.211s16.132-3.07 22.272-9.211c6.024-6.024 9.341-14.033 9.341-22.553 0-8.519-3.317-16.528-9.341-22.553l-3.3-3.3c-.198-.198-.567-.567-.26-1.308.307-.741.829-.741 1.109-.741h47.888C479.468 211.761 482 231.09 482 251c0 127.374-103.626 231-231 231z'/%3E%3Cpath d='M184 85c5.523 0 10-4.477 10-10V54.494c0-5.523-4.477-10-10-10s-10 4.477-10 10V75c0 5.523 4.477 10 10 10zM450.39 314.63c-5.176-1.93-10.935.702-12.863 5.877C408.652 397.961 333.692 450 251 450c-5.523 0-10 4.477-10 10s4.477 10 10 10c45.543 0 89.207-13.849 126.272-40.048 36.24-25.617 63.556-61.046 78.995-102.458 1.929-5.175-.702-10.934-5.877-12.864zM202.433 444.034a198.232 198.232 0 0 1-28.554-9.526c-5.092-2.144-10.954.249-13.096 5.339-2.142 5.09.249 10.954 5.339 13.096a218.202 218.202 0 0 0 31.445 10.491c.817.205 1.635.303 2.44.303 4.478 0 8.554-3.03 9.692-7.57 1.344-5.358-1.909-10.79-7.266-12.133z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a.symbols i {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 490.4 490.4'%3E%3Cpath d='M229 381.2c4.4 4.4 10.1 6.8 16.3 6.8 6.2 0 12-2.4 16.3-6.8l96.3-96.3c15.7-15.7 24.4-36.6 24.4-58.7 0-22.2-8.6-43.1-24.3-58.8-15.7-15.7-36.6-24.3-58.7-24.3-20 0-38.9 7-54 19.9-15.1-13-34.1-20-54.1-20-22.2 0-43 8.6-58.7 24.3s-24.3 36.6-24.3 58.8 8.7 43 24.4 58.7l96.4 96.4zm-79.3-196.7c11.1-11.1 25.7-17.1 41.4-17.1s30.4 6.1 41.5 17.2l4 4c4.8 4.8 12.5 4.8 17.3 0l3.9-3.9c11.1-11.1 25.8-17.2 41.5-17.2 15.6 0 30.3 6.1 41.4 17.2 11.1 11.1 17.2 25.8 17.1 41.4 0 15.7-6.1 30.4-17.2 41.5l-95.3 95.3-95.5-95.5c-11.1-11.1-17.2-25.8-17.2-41.4 0-15.7 6.1-30.4 17.1-41.5z'/%3E%3Cpath d='M245.2 490.4c135.2 0 245.2-110 245.2-245.2S380.4 0 245.2 0 0 110 0 245.2s110 245.2 245.2 245.2zm0-465.9c121.7 0 220.7 99 220.7 220.7s-99 220.7-220.7 220.7-220.7-99-220.7-220.7 99-220.7 220.7-220.7z'/%3E%3C/svg%3E");
+}
+
+.emoji-picker nav a:after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ left: 0;
+ height: 2px;
+ border-radius: 5px;
+ background-color: #90caf9;
+ opacity: 0;
+ transition-delay: 1s;
+ transition: opacity .4s, background .2s;
+}
+
+.emoji-picker.people nav .people i {
+ opacity: 1;
+}
+
+.emoji-picker.people nav .people:after {
+ opacity: 1;
+}
+
+.emoji-picker.foods nav .foods i {
+ opacity: 1;
+}
+
+.emoji-picker.foods nav .foods:after {
+ opacity: 1;
+}
+
+.emoji-picker.nature nav .nature i {
+ opacity: 1;
+}
+
+.emoji-picker.nature nav .nature:after {
+ opacity: 1;
+}
+
+.emoji-picker.activity nav .activity i {
+ opacity: 1;
+}
+
+.emoji-picker.activity nav .activity:after {
+ opacity: 1;
+}
+
+.emoji-picker.objects nav .objects i {
+ opacity: 1;
+}
+
+.emoji-picker.objects nav .objects:after {
+ opacity: 1;
+}
+
+.emoji-picker.places nav .places i {
+ opacity: 1;
+}
+
+.emoji-picker.places nav .places:after {
+ opacity: 1;
+}
+
+.emoji-picker.flags nav .flags i {
+ opacity: 1;
+}
+
+.emoji-picker.flags nav .flags:after {
+ opacity: 1;
+}
+
+.emoji-picker.symbols nav .symbols i {
+ opacity: 1;
+}
+
+.emoji-picker.symbols nav .symbols:after {
+ opacity: 1;
+}
+
+.emoji-picker .diversity-picker {
+ background-color: #fafafa;
+ display: flex;
+ justify-content: space-around;
+ flex-direction: row-reverse;
+ position: absolute;
+ z-index: 3;
+ left: 0;
+ top: 0;
+ right: 0;
+ height: 30px;
+ transform: translateY(-30px);
+ opacity: .6;
+ transition: .2s opacity, .2s transform;
+}
+
+.emoji-picker .diversity-picker.shown {
+ transform: translateY(0);
+ opacity: 1;
+ border-bottom: 1px solid #eeeeee;
+}
+
+.emoji-picker .diversity-picker .emoji {
+ display: inline-block;
+}
+
+.emoji-picker .emoji {
+ border-radius: 5px;
+ height: 32px;
+ width: 32px;
+ padding: 5px;
+ background-size: 20px;
+ background-repeat: no-repeat;
+ background-position: 50% 50%;
+ overflow: hidden;
+ transition: background-color .2s;
+ display: none;
+}
+
+.emoji-picker .emoji.shown {
+ display: inline-block;
+}
+
+.emoji-picker .emoji:hover {
+ background-color: #bbdefb;
+}
+
+.emoji-picker .emoji:hover.has-diversities:before {
+ opacity: 1;
+}
+
+.emoji-picker .emoji.has-diversities:before {
+ content: '';
+ background-color: #f5f5f5;
+ display: block;
+ height: 8px;
+ width: 8px;
+ float: right;
+ opacity: 0;
+ transform: translateY(-6px) translateX(6px);
+ transition: opacity .2s;
+}
+
+.emoji-picker .emoji-category {
+ position: relative;
+ padding: 30px 5px 0 5px;
+ margin: 0;
+ text-align: left;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+}
+
+.emoji-picker .emoji-category .category-name {
+ background-color: rgba(255, 255, 255, 0.9);
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 0;
+ display: block;
+ padding: 0 10px;
+ font-size: 12px;
+ font-weight: 700;
+ letter-spacing: .1em;
+ text-transform: uppercase;
+ color: #bdbdbd;
+ height: 30px;
+ line-height: 30px;
+ box-sizing: border-box;
+ transition: color .2s;
+}
+
+.emoji-picker.people .people.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.people .people.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.foods .foods.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.foods .foods.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.nature .nature.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.nature .nature.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.activity .activity.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.activity .activity.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.objects .objects.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.objects .objects.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.places .places.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.places .places.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.flags .flags.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.flags .flags.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.regional .regional.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.regional .regional.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker.symbols .symbols.emoji-category {
+ position: initial;
+}
+
+.emoji-picker.symbols .symbols.emoji-category .category-name {
+ color: #9e9e9e;
+}
+
+.emoji-picker .emoji-list {
+ width: 100%;
+ height: 240px;
+ padding: 0;
+ overflow-x: hidden;
+ box-sizing: border-box;
+ -ms-overflow-style: none;
+}
+
+.emoji-picker .emoji-list::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+}
+
+.emoji-picker .emoji-list::scrollbar {
+ height: 0;
+ width: 0;
+}
+
+.emoji-picker .emoji-list.filter:before {
+ content: '';
+ background: #ffffff;
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ height: 30px;
+ z-index: 1;
+ opacity: 0.9;
+}
+
+.emoji-picker .emoji-list.filter .category-name {
+ background: none;
+ z-index: 1;
+}
+
+.emoji-picker .emoji-list:not(.filter) .emoji-category {
+ min-height: 100%;
+}
+
+.emoji-picker .wrapper {
+ position: relative;
+ overflow: hidden;
+}
+
+.emoji-picker .wrapper.no-results:before {
+ content: '';
+ background-repeat: no-repeat;
+ background-image: url("data:image/svg+xml,%3Csvg id='Capa_1' xmlns='http://www.w3.org/2000/svg' width='310.4' height='310.4'%3E%3Cstyle%3E.st0%7Bfill:%239e9e9e%7D%3C/style%3E%3Cpath class='st0' d='M273.6 215c49.1-49.1 49.1-129 0-178.1-49.1-49.1-129-49.1-178.1 0-41.7 41.7-48 103.6-18.9 152 0 0 2.1 3.5-.7 6.3l-64.3 64.3c-12.8 12.8-15.8 30.7-4.5 42l2 2c11.3 11.3 29.2 8.3 42-4.5l64.1-64.1c3-3 6.4-.9 6.4-.9 48.4 28.9 110.3 22.6 152-19zm-154.9-23.3c-36.3-36.3-36.3-95.3 0-131.6s95.3-36.3 131.6 0 36.3 95.3 0 131.6-95.3 36.3-131.6 0z'/%3E%3Cpath class='st0' d='M126.8 118.4c-1.7 0-3.4-.3-5.1-1-6.6-2.8-9.7-10.4-6.9-17 17.6-41.6 65.7-61.1 107.3-43.5 6.6 2.8 9.7 10.4 6.9 17-2.8 6.6-10.4 9.7-17 6.9-28.4-12-61.2 1.3-73.2 29.7-2.2 4.9-7 7.9-12 7.9z'/%3E%3C/svg%3E");
+ background-position: 50% 50%;
+ background-size: 100px 100px;
+ display: block;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ opacity: .07;
+ transform: translateX(-50%) translateY(-50%);
+}
+
+.emoji-picker .wrapper.no-results .emoji-name {
+ display: none;
+}
+
+.emoji-picker .wrapper:after {
+ content: '';
+ background-color: #ffffff;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 5px;
+}
+
+.emoji-picker .wrapper .scroller {
+ display: block;
+ position: absolute;
+ width: 5px;
+ padding-top: 5px;
+ z-index: 2;
+ right: 3px;
+ box-sizing: border-box;
+ opacity: 0;
+ transition: opacity .2s;
+}
+
+.emoji-picker .wrapper .scroller.shown {
+ opacity: 1;
+}
+
+.emoji-picker .wrapper .scroller div {
+ background-color: #bdbdbd;
+ width: 100%;
+ min-height: 12px;
+}
+
+.emoji-picker .wrapper .emoji-name {
+ position: absolute;
+ right: 10px;
+ top: 8px;
+ font-size: 10px;
+ font-weight: 100;
+ z-index: 2;
+ color: #9e9e9e;
+ max-width: 130px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.emoji-picker .search-bar {
+ height: 45px;
+ margin-top: 0;
+ padding: 10px;
+ position: relative;
+ z-index: 2;
+ left: 0;
+ box-sizing: border-box;
+}
+
+.emoji-picker .search-bar input {
+ padding: 5px 5px 5px 35px;
+ margin: 0;
+ box-sizing: border-box;
+ color: #9e9e9e;
+ width: 100%;
+ outline: none;
+ border: 1px solid #eeeeee;
+ border-radius: 5px;
+ transition: border .2s;
+}
+
+.emoji-picker .search-bar input::placeholder {
+ color: #e0e0e0;
+}
+
+.emoji-picker .search-bar input:focus {
+ border: 1px solid #e0e0e0;
+}
+
+.emoji-picker .search-bar input:focus + i:before {
+ opacity: 1;
+}
+
+.emoji-picker .search-bar i:before {
+ content: '';
+ background-repeat: no-repeat;
+ background-image: url("data:image/svg+xml,%3Csvg id='Capa_1' xmlns='http://www.w3.org/2000/svg' width='310.4' height='310.4'%3E%3Cstyle%3E.st0%7Bfill:%239e9e9e%7D%3C/style%3E%3Cpath class='st0' d='M273.6 215c49.1-49.1 49.1-129 0-178.1-49.1-49.1-129-49.1-178.1 0-41.7 41.7-48 103.6-18.9 152 0 0 2.1 3.5-.7 6.3l-64.3 64.3c-12.8 12.8-15.8 30.7-4.5 42l2 2c11.3 11.3 29.2 8.3 42-4.5l64.1-64.1c3-3 6.4-.9 6.4-.9 48.4 28.9 110.3 22.6 152-19zm-154.9-23.3c-36.3-36.3-36.3-95.3 0-131.6s95.3-36.3 131.6 0 36.3 95.3 0 131.6-95.3 36.3-131.6 0z'/%3E%3Cpath class='st0' d='M126.8 118.4c-1.7 0-3.4-.3-5.1-1-6.6-2.8-9.7-10.4-6.9-17 17.6-41.6 65.7-61.1 107.3-43.5 6.6 2.8 9.7 10.4 6.9 17-2.8 6.6-10.4 9.7-17 6.9-28.4-12-61.2 1.3-73.2 29.7-2.2 4.9-7 7.9-12 7.9z'/%3E%3C/svg%3E");
+ background-position: 50% 50%;
+ background-size: 15px 15px;
+ height: 15px;
+ width: 15px;
+ position: absolute;
+ left: 20px;
+ top: 15px;
+ display: block;
+ opacity: .3;
+ transition: opacity .2s;
+}
+
+.emoji-picker {
+ background-color: #ffffff;
+ width: 285px;
+ display: block;
+ position: relative;
+ padding: 0;
+ border: 1px solid #eeeeee;
+ border-radius: 3px;
+ overflow: hidden;
+ font-family: sans-serif;
+}
+
+.emoji-picker .hidden {
+ display: none !important;
+ visibility: hidden !important;
+ padding: 0 !important;
+ margin: 0 !important;
+}
+
+.emoji-picker a {
+ outline: none;
+}
+
+.emoji-picker ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+.emoji-picker ul li {
+ display: inline-block;
+}
+
+.emoji-picker .bar-wrapper {
+ position: relative;
+}
+
+.emoji-text-field {
+ height: 100%;
+ position: relative;
+ flex: 1;
+}
+
+.emoji-text-field input,
+.emoji-text-field textarea {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 2px 20px 2px 2px;
+ box-sizing: border-box;
+ border: none;
+ box-shadow: none !important;
+ outline: none !important;
+}
+
+.emoji-text-field.picker-hidden .emoji-picker {
+ display: none;
+ opacity: 0;
+ visibility: none;
+}
+
+.emoji-text-field .emoji-picker {
+ position: absolute;
+ z-index: 1;
+ right: 0;
+ bottom: 30px;
+}
+
+.emoji-text-field .emoji-trigger {
+ background-size: 16px 16px;
+ position: absolute;
+ z-index: 1;
+ bottom: 3px;
+ right: 5px;
+ opacity: .2;
+ transition: opacity .3s;
+}
diff --git a/front/odiparpack/app/styles/components/vendors/image-lightbox/image-lightbox.css b/front/odiparpack/app/styles/components/vendors/image-lightbox/image-lightbox.css
new file mode 100644
index 0000000..9c4dfa3
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/image-lightbox/image-lightbox.css
@@ -0,0 +1,344 @@
+@keyframes closeWindow {
+ 0% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
+
+.ril__outer {
+ background-color: rgba(0, 0, 0, 0.85);
+ outline: none;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1000;
+ width: 100%;
+ height: 100%;
+ -ms-content-zooming: none;
+ -ms-user-select: none;
+ -ms-touch-select: none;
+ touch-action: none;
+}
+
+.ril__outerClosing {
+ opacity: 0;
+}
+
+.ril__inner {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.ril__image,
+.ril__imagePrev,
+.ril__imageNext {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin: auto;
+ max-width: none;
+ -ms-content-zooming: none;
+ -ms-user-select: none;
+ -ms-touch-select: none;
+ touch-action: none;
+}
+
+.ril__imageDiscourager {
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+}
+
+.ril__navButtons {
+ border: none;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 20px;
+ height: 34px;
+ padding: 40px 30px;
+ margin: auto;
+ cursor: pointer;
+ opacity: 0.7;
+}
+.ril__navButtons:hover {
+ opacity: 1;
+}
+.ril__navButtons:active {
+ opacity: 0.7;
+}
+
+.ril__navButtonPrev {
+ left: 0;
+ background: rgba(0, 0, 0, 0.2)
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjM0Ij48cGF0aCBkPSJtIDE5LDMgLTIsLTIgLTE2LDE2IDE2LDE2IDEsLTEgLTE1LC0xNSAxNSwtMTUgeiIgZmlsbD0iI0ZGRiIvPjwvc3ZnPg==')
+ no-repeat center;
+}
+
+.ril__navButtonNext {
+ right: 0;
+ background: rgba(0, 0, 0, 0.2)
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjM0Ij48cGF0aCBkPSJtIDEsMyAyLC0yIDE2LDE2IC0xNiwxNiAtMSwtMSAxNSwtMTUgLTE1LC0xNSB6IiBmaWxsPSIjRkZGIi8+PC9zdmc+')
+ no-repeat center;
+}
+
+.ril__downloadBlocker {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
+ background-size: cover;
+}
+
+.ril__caption,
+.ril__toolbar {
+ background-color: rgba(0, 0, 0, 0.5);
+ position: absolute;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: space-between;
+}
+
+.ril__caption {
+ bottom: 0;
+ max-height: 150px;
+ overflow: auto;
+}
+
+.ril__captionContent {
+ padding: 10px 20px;
+ color: #fff;
+}
+
+.ril__toolbar {
+ top: 0;
+ height: 50px;
+}
+
+.ril__toolbarSide {
+ height: 50px;
+ margin: 0;
+}
+
+.ril__toolbarLeftSide {
+ padding-left: 20px;
+ padding-right: 0;
+ flex: 0 1 auto;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.ril__toolbarRightSide {
+ padding-left: 0;
+ padding-right: 20px;
+ flex: 0 0 auto;
+}
+
+.ril__toolbarItem {
+ display: inline-block;
+ line-height: 50px;
+ padding: 0;
+ color: #fff;
+ font-size: 120%;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.ril__toolbarItemChild {
+ vertical-align: middle;
+}
+
+.ril__builtinButton {
+ width: 40px;
+ height: 35px;
+ cursor: pointer;
+ border: none;
+ opacity: 0.7;
+}
+.ril__builtinButton:hover {
+ opacity: 1;
+}
+.ril__builtinButton:active {
+ outline: none;
+}
+
+.ril__builtinButtonDisabled {
+ cursor: default;
+ opacity: 0.5;
+}
+.ril__builtinButtonDisabled:hover {
+ opacity: 0.5;
+}
+
+.ril__closeButton {
+ background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj48cGF0aCBkPSJtIDEsMyAxLjI1LC0xLjI1IDcuNSw3LjUgNy41LC03LjUgMS4yNSwxLjI1IC03LjUsNy41IDcuNSw3LjUgLTEuMjUsMS4yNSAtNy41LC03LjUgLTcuNSw3LjUgLTEuMjUsLTEuMjUgNy41LC03LjUgLTcuNSwtNy41IHoiIGZpbGw9IiNGRkYiLz48L3N2Zz4=')
+ no-repeat center;
+}
+
+.ril__zoomInButton {
+ background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+PGcgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PHBhdGggZD0iTTEgMTlsNi02Ii8+PHBhdGggZD0iTTkgOGg2Ii8+PHBhdGggZD0iTTEyIDV2NiIvPjwvZz48Y2lyY2xlIGN4PSIxMiIgY3k9IjgiIHI9IjciIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+')
+ no-repeat center;
+}
+
+.ril__zoomOutButton {
+ background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+PGcgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PHBhdGggZD0iTTEgMTlsNi02Ii8+PHBhdGggZD0iTTkgOGg2Ii8+PC9nPjxjaXJjbGUgY3g9IjEyIiBjeT0iOCIgcj0iNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiLz48L3N2Zz4=')
+ no-repeat center;
+}
+
+.ril__outerAnimating {
+ animation-name: closeWindow;
+}
+
+@keyframes pointFade {
+ 0%,
+ 19.999%,
+ 100% {
+ opacity: 0;
+ }
+ 20% {
+ opacity: 1;
+ }
+}
+
+.ril__loadingCircle {
+ width: 60px;
+ height: 60px;
+ position: relative;
+}
+
+.ril__loadingCirclePoint {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+.ril__loadingCirclePoint::before {
+ content: '';
+ display: block;
+ margin: 0 auto;
+ width: 11%;
+ height: 30%;
+ background-color: #fff;
+ border-radius: 30%;
+ animation: pointFade 800ms infinite ease-in-out both;
+}
+.ril__loadingCirclePoint:nth-of-type(1) {
+ transform: rotate(0deg);
+}
+.ril__loadingCirclePoint:nth-of-type(7) {
+ transform: rotate(180deg);
+}
+.ril__loadingCirclePoint:nth-of-type(1)::before,
+.ril__loadingCirclePoint:nth-of-type(7)::before {
+ animation-delay: -800ms;
+}
+.ril__loadingCirclePoint:nth-of-type(2) {
+ transform: rotate(30deg);
+}
+.ril__loadingCirclePoint:nth-of-type(8) {
+ transform: rotate(210deg);
+}
+.ril__loadingCirclePoint:nth-of-type(2)::before,
+.ril__loadingCirclePoint:nth-of-type(8)::before {
+ animation-delay: -666ms;
+}
+.ril__loadingCirclePoint:nth-of-type(3) {
+ transform: rotate(60deg);
+}
+.ril__loadingCirclePoint:nth-of-type(9) {
+ transform: rotate(240deg);
+}
+.ril__loadingCirclePoint:nth-of-type(3)::before,
+.ril__loadingCirclePoint:nth-of-type(9)::before {
+ animation-delay: -533ms;
+}
+.ril__loadingCirclePoint:nth-of-type(4) {
+ transform: rotate(90deg);
+}
+.ril__loadingCirclePoint:nth-of-type(10) {
+ transform: rotate(270deg);
+}
+.ril__loadingCirclePoint:nth-of-type(4)::before,
+.ril__loadingCirclePoint:nth-of-type(10)::before {
+ animation-delay: -400ms;
+}
+.ril__loadingCirclePoint:nth-of-type(5) {
+ transform: rotate(120deg);
+}
+.ril__loadingCirclePoint:nth-of-type(11) {
+ transform: rotate(300deg);
+}
+.ril__loadingCirclePoint:nth-of-type(5)::before,
+.ril__loadingCirclePoint:nth-of-type(11)::before {
+ animation-delay: -266ms;
+}
+.ril__loadingCirclePoint:nth-of-type(6) {
+ transform: rotate(150deg);
+}
+.ril__loadingCirclePoint:nth-of-type(12) {
+ transform: rotate(330deg);
+}
+.ril__loadingCirclePoint:nth-of-type(6)::before,
+.ril__loadingCirclePoint:nth-of-type(12)::before {
+ animation-delay: -133ms;
+}
+.ril__loadingCirclePoint:nth-of-type(7) {
+ transform: rotate(180deg);
+}
+.ril__loadingCirclePoint:nth-of-type(13) {
+ transform: rotate(360deg);
+}
+.ril__loadingCirclePoint:nth-of-type(7)::before,
+.ril__loadingCirclePoint:nth-of-type(13)::before {
+ animation-delay: 0ms;
+}
+
+.ril__loadingContainer {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+.ril__imagePrev .ril__loadingContainer,
+.ril__imageNext .ril__loadingContainer {
+ display: none;
+}
+
+.ril__errorContainer {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+}
+.ril__imagePrev .ril__errorContainer,
+.ril__imageNext .ril__errorContainer {
+ display: none;
+}
+
+.ril__loadingContainer__icon {
+ color: #fff;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translateX(-50%) translateY(-50%);
+}
diff --git a/front/odiparpack/app/styles/components/vendors/react-animated-slider/react-animated-slider.css b/front/odiparpack/app/styles/components/vendors/react-animated-slider/react-animated-slider.css
new file mode 100644
index 0000000..135da22
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-animated-slider/react-animated-slider.css
@@ -0,0 +1,373 @@
+.slider {
+ position: relative;
+ width: 100%;
+ height: 400px;
+ overflow: hidden
+}
+
+.slider a.previousButton, .slider a.nextButton {
+ font-size: 22px;
+ line-height: 0;
+ display: block;
+ position: absolute;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+ -webkit-transition: all .3s linear;
+ transition: all .3s linear;
+ z-index: 1;
+ color: #333;
+ padding: 10px;
+ text-decoration: none;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden
+ /* prevent jump effect when scaling */
+}
+
+.slider a.previousButton:not(.disabled):hover, .slider a.nextButton:not(.disabled):hover {
+ -webkit-transform: translateY(-50%) scale(1.25);
+ transform: translateY(-50%) scale(1.25);
+ cursor: pointer;
+}
+
+.slider a.previousButton {
+ left: 20px;
+}
+
+.slider a.nextButton {
+ right: 20px;
+}
+
+.slide {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ overflow: hidden
+}
+
+.slide.hidden {
+ visibility: hidden;
+}
+
+.slide.previous {
+ left: -100%;
+}
+
+.slide.current {
+ left: 0;
+}
+
+.slide.next {
+ left: 100%;
+}
+
+.slide.animateIn,
+ .slide.animateOut {
+ -webkit-transition: all 2s ease;
+ transition: all 2s ease;
+}
+
+.slide.animateIn.previous,
+ .slide.animateIn.next {
+ left: 0;
+ visibility: visible;
+}
+
+.slide.animateOut.previous {
+ left: 100%;
+}
+
+.slide.animateOut.next {
+ left: -100%;
+}
+
+.slide h1, .slide h3 {
+ transition: all 0.3s ease;
+ -webkit-transform: translateY(-20px);
+ transform: translateY(-20px);
+ opacity: 0;
+}
+
+.slide button {
+ transition: all 0.3s ease;
+ -webkit-transform: translateY(20px);
+ transform: translateY(20px);
+ opacity: 0;
+}
+
+.slide p {
+ transition: all 0.3s ease;
+ -webkit-transform: translateY(20px);
+ transform: translateY(20px);
+ opacity: 0;
+}
+
+.slide section * {
+ transition: all 0.3s ease;
+}
+
+.slide section img {
+ -webkit-transform: translateX(-10px);
+ transform: translateX(-10px);
+ opacity: 0;
+}
+
+.slide section span {
+ -webkit-transform: translateY(-10px);
+ transform: translateY(-10px);
+ opacity: 0;
+}
+
+.slide section span strong {
+ -webkit-transform: translateY(10px);
+ transform: translateY(10px);
+ opacity: 0;
+ font-weight: 500
+}
+
+.slide.animateIn.previous h1,
+.slide.animateIn.previous h3,
+.slide.current h1,
+.slide.current h3,
+.slide.animateIn.next h1,
+.slide.animateIn.next h3,
+.slide.animateIn.previous button,
+.slide.current button,
+.slide.animateIn.next button,
+.slide.animateIn.previous p,
+.slide.current p,
+.slide.animateIn.next p,
+.slide.animateIn.previous section *,
+.slide.current section *,
+.slide.animateIn.next section * {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ -webkit-transition-delay: .9s;
+ transition-delay: .9s;
+ opacity: 1;
+}
+
+.slide.animateIn.previous p,
+.slide.animateIn.next p {
+ -webkit-transition-delay: 1.1s;
+ transition-delay: 1.1s;
+}
+
+.slide.animateIn.previous button,
+.slide.animateIn.next button {
+ -webkit-transition-delay: 1.3s;
+ transition-delay: 1.3s;
+}
+
+.slide.animateIn.previous section img,
+.slide.animateIn.next section img {
+ -webkit-transition-delay: 1.3s;
+ transition-delay: 1.3s;
+}
+
+.slide.animateIn.previous section span,
+.slide.animateIn.next section span {
+ -webkit-transition-delay: 1.4s;
+ transition-delay: 1.4s;
+}
+
+.slide.animateIn.previous section span strong,
+.slide.animateIn.next section span strong {
+ -webkit-transition-delay: 1.5s;
+ transition-delay: 1.5s;
+}
+
+.slide.animateOut h1 {
+ -webkit-transition-delay: .3s;
+ transition-delay: .3s;
+}
+
+.slide.animateOut p {
+ -webkit-transition-delay: .2s;
+ transition-delay: .2s;
+}
+
+.slide.animateOut section span {
+ -webkit-transition-delay: .1s;
+ transition-delay: .1s;
+}
+
+.slide.animateOut section span strong {
+ -webkit-transition-delay: 0s;
+ transition-delay: 0s;
+}
+
+.slide {
+ height: 70vh;
+ background-size: cover !important;
+}
+
+.slide::before {
+ content: '';
+ display: block;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(0, 0, 0, 0.9)));
+ background: linear-gradient(transparent, rgba(0, 0, 0, 0.9));
+ bottom: 0;
+ left: 0;
+}
+
+.previousButton,
+.nextButton {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ z-index: 10;
+ width: 32px;
+ height: 32px;
+ transition: all .3s ease;
+ cursor: pointer;
+ text-align: center;
+}
+
+.previousButton svg polygon,
+.nextButton svg polygon {
+ fill: #fff;
+ opacity: .5;
+}
+
+.previousButton {
+ left: 10px;
+}
+
+.previousButton:hover {
+ left: 5px;
+}
+
+.nextButton {
+ right: 10px;
+}
+
+.nextButton:hover {
+ right: 5px;
+}
+
+.slider-content {
+ text-align: center;
+}
+
+.slider-content .inner {
+ padding: 0 70px;
+ box-sizing: border-box;
+ position: absolute;
+ width: 100%;
+ top: 50%;
+ left: 50%;
+ -webkit-transform: translate(-50%, -50%);
+ transform: translate(-50%, -50%);
+}
+
+.slider-content .inner button {
+ -webkit-transition-delay: 0s;
+ transition-delay: 0s;
+}
+
+.slider-content .inner h1,
+.slider-content .inner h3 {
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 840px;
+ color: #FFFFFF;
+ font-size: 64px;
+ line-height: 1;
+}
+
+.slider-content .inner p {
+ color: #FFFFFF;
+ font-size: 14px;
+ line-height: 1.5;
+ margin: 20px auto 30px;
+ max-width: 640px;
+}
+
+.slider-content section {
+ position: absolute;
+ bottom: 20px;
+ left: 20px;
+}
+
+.slider-content section span {
+ color: #FFFFFF;
+}
+
+.slider-content section span {
+ color: rgba(255, 255, 255, 0.5);
+ font-size: 12px;
+ display: inline-block;
+ text-align: left;
+ line-height: 1.4;
+ vertical-align: middle;
+ margin-left: 10px;
+}
+
+.slider-content section img {
+ width: 40px;
+ height: 40px;
+ border: solid 2px rgba(255, 255, 255, 0.5);
+ border-radius: 100%;
+ vertical-align: middle;
+}
+
+.slider-content section span strong {
+ color: #FFFFFF;
+ font-size: 14px;
+ display: block;
+}
+
+.slider-wrapper{
+ position: relative;
+ overflow: hidden;
+ border-radius: 4px;
+}
+
+.slider-wrapper,
+.slide {
+ height: calc(100vh - 75px);
+}
+
+.slider-wrapper.medium,
+.slider-wrapper.medium .slide {
+ height: 500px;
+}
+
+.slider-wrapper.short,
+.slider-wrapper.short .slide {
+ height: 261px;
+}
+
+.slider-content .inner h1 {
+ font-size: 32px;
+}
+
+.slider-content .inner h3 {
+ font-size: 24px;
+}
+
+@media (max-width: 640px) {
+ .slider-wrapper,
+ .slide {
+ height: calc(80vh - 75px);
+ }
+ .custom-nav .slick-dots{
+ visibility: hidden;
+ }
+}
+
+@media (max-width: 480px) {
+ .slider-content .inner h3,
+ .slider-content .inner h1 {
+ font-size: 18px;
+ line-height: 24px
+ }
+ .slider-content .inner {
+ padding: 0 40px
+ }
+}
+
diff --git a/front/odiparpack/app/styles/components/vendors/react-big-calendar/react-big-calendar.css b/front/odiparpack/app/styles/components/vendors/react-big-calendar/react-big-calendar.css
new file mode 100644
index 0000000..6562da2
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-big-calendar/react-big-calendar.css
@@ -0,0 +1,665 @@
+.rbc-btn {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+button.rbc-btn {
+ overflow: visible;
+ text-transform: none;
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled].rbc-btn {
+ cursor: not-allowed;
+}
+button.rbc-input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+.rbc-calendar {
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ height: 100%;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -ms-flex-align: stretch;
+ -webkit-box-align: stretch;
+ align-items: stretch;
+}
+.rbc-calendar *,
+.rbc-calendar *:before,
+.rbc-calendar *:after {
+ -webkit-box-sizing: inherit;
+ box-sizing: inherit;
+}
+.rbc-abs-full,
+.rbc-row-bg {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.rbc-ellipsis,
+.rbc-event-label,
+.rbc-row-segment .rbc-event-content,
+.rbc-show-more {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.rbc-rtl {
+ direction: rtl;
+}
+.rbc-off-range {
+ color: #cccccc;
+}
+.rbc-off-range-bg {
+ background: #f7f7f7;
+}
+.rbc-header {
+ overflow: hidden;
+ -ms-flex: 1 0 0%;
+ -webkit-box-flex: 1;
+ flex: 1 0 0%;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 5px 3px;
+ text-align: right;
+ vertical-align: middle;
+ font-weight: 400;
+ font-size: 18px;
+ min-height: 0;
+ background: #eaeaea;
+ color: #757575;
+}
+.rbc-rtl .rbc-header + .rbc-header {
+ border-left-width: 0;
+}
+.rbc-header > a,
+.rbc-header > a:active,
+.rbc-header > a:visited {
+ color: inherit;
+ text-decoration: none;
+}
+.rbc-row-content {
+ position: relative;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-user-select: none;
+ z-index: 4;
+}
+.rbc-today {
+ background-color: #eaf6ff;
+}
+.rbc-toolbar {
+ margin-bottom: 10px;
+ font-size: 16px;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-align: center;
+ -webkit-box-align: center;
+ align-items: center;
+}
+.rbc-toolbar .rbc-toolbar-label {
+ -ms-flex-positive: 1;
+ -webkit-box-flex: 1;
+ flex-grow: 1;
+ padding: 10px;
+ text-align: center;
+}
+.rbc-toolbar button {
+ color: #373a3c;
+ display: inline-block;
+ margin: 0;
+ text-align: center;
+ vertical-align: middle;
+ background: #EEEEEE;
+ border: 1px solid #f9f9f9;
+ background-image: none;
+ padding: .375rem 1rem;
+ border-radius: 2px;
+ line-height: normal;
+ white-space: nowrap;
+ font-weight: 400;
+ font-size: 14px;
+ text-transform: capitalize;
+}
+.rbc-toolbar button:active,
+.rbc-toolbar button.rbc-active {
+ background-color: #2196F3 !important;
+ color: #FFF;
+}
+.rbc-toolbar button:hover {
+ color: #373a3c;
+ background-color: #e6e6e6;
+}
+.rbc-btn-group {
+ display: inline-block;
+ white-space: nowrap;
+}
+.rbc-btn-group > button:first-child:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rbc-btn-group > button:last-child:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.rbc-rtl .rbc-btn-group > button:first-child:not(:last-child) {
+ border-radius: 4px;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.rbc-rtl .rbc-btn-group > button:last-child:not(:first-child) {
+ border-radius: 4px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rbc-btn-group > button:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.rbc-btn-group button + button {
+ margin-left: -1px;
+}
+.rbc-rtl .rbc-btn-group button + button {
+ margin-left: 0;
+ margin-right: -1px;
+}
+.rbc-btn-group + .rbc-btn-group,
+.rbc-btn-group + button {
+ margin-left: 10px;
+}
+.rbc-event {
+ padding: 5px 8px;
+ background-color: #3174ad;
+ border-radius: 2px;
+ color: #3a3a3a;
+ cursor: pointer;
+ font-size: 13px;
+}
+.rbc-slot-selecting .rbc-event {
+ cursor: inherit;
+ pointer-events: none;
+}
+.rbc-event.rbc-selected {
+ background-color: #265985;
+}
+.rbc-event-label {
+ font-size: 80%;
+}
+.rbc-event-overlaps {
+ -webkit-box-shadow: -1px 1px 5px 0px rgba(51, 51, 51, 0.5);
+ box-shadow: -1px 1px 5px 0px rgba(51, 51, 51, 0.5);
+}
+.rbc-event-continues-prior {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.rbc-event-continues-after {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rbc-event-continues-earlier {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.rbc-event-continues-later {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rbc-event-continues-day-after {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rbc-event-continues-day-prior {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.rbc-row {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: row;
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ flex-direction: row;
+}
+.rbc-row-segment {
+ padding: 0 1px 1px 1px;
+}
+.rbc-selected-cell {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.rbc-show-more {
+ z-index: 4;
+ font-weight: bold;
+ font-size: 85%;
+ height: auto;
+ color: #424242;
+ line-height: normal;
+ white-space: nowrap;
+}
+.rbc-month-view {
+ position: relative;
+ border: none;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -ms-flex: 1 0 0px;
+ -webkit-box-flex: 1;
+ flex: 1 0 0;
+ width: 100%;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-user-select: none;
+ height: 100%;
+}
+.rbc-month-header {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: row;
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ flex-direction: row;
+}
+.rbc-month-row {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ position: relative;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -ms-flex: 1 0 0px;
+ -webkit-box-flex: 1;
+ flex: 1 0 0;
+ -ms-flex-preferred-size: 0px;
+ flex-basis: 0px;
+ overflow: hidden;
+ height: 100%;
+}
+.rbc-month-row + .rbc-month-row {
+ border-top: 1px solid #DDD;
+}
+.rbc-date-cell {
+ -ms-flex: 1 1 0px;
+ -webkit-box-flex: 1;
+ flex: 1 1 0;
+ min-width: 0;
+ padding-right: 5px;
+ text-align: right;
+}
+.rbc-date-cell.rbc-now {
+ font-weight: bold;
+}
+.rbc-date-cell > a,
+.rbc-date-cell > a:active,
+.rbc-date-cell > a:visited {
+ color: inherit;
+ text-decoration: none;
+}
+.rbc-row-bg {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: row;
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ flex-direction: row;
+ -ms-flex: 1 0 0px;
+ -webkit-box-flex: 1;
+ flex: 1 0 0;
+ overflow: hidden;
+}
+.rbc-day-bg {
+ -ms-flex: 1 0 0%;
+ -webkit-box-flex: 1;
+ flex: 1 0 0%;
+}
+
+.rbc-overlay {
+ position: absolute;
+ z-index: 5;
+ border: 1px solid #e5e5e5;
+ background-color: #fff;
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.25);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.25);
+ padding: 10px;
+}
+.rbc-overlay > * + * {
+ margin-top: 1px;
+}
+.rbc-overlay-header {
+ border-bottom: 1px solid #e5e5e5;
+ margin: -10px -10px 5px -10px;
+ padding: 2px 10px;
+}
+.rbc-agenda-view {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -ms-flex: 1 0 0px;
+ -webkit-box-flex: 1;
+ flex: 1 0 0;
+ overflow: auto;
+}
+.rbc-agenda-view table.rbc-agenda-table {
+ width: 100%;
+ border: 1px solid #DDD;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+.rbc-agenda-view table.rbc-agenda-table tbody > tr > td {
+ padding: 5px 10px;
+ vertical-align: top;
+}
+.rbc-agenda-view table.rbc-agenda-table .rbc-agenda-time-cell {
+ padding-left: 15px;
+ padding-right: 15px;
+ text-transform: lowercase;
+}
+.rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td {
+ border-left: 1px solid #DDD;
+}
+.rbc-rtl .rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td {
+ border-left-width: 0;
+ border-right: 1px solid #DDD;
+}
+.rbc-agenda-view table.rbc-agenda-table tbody > tr + tr {
+ border-top: 1px solid #DDD;
+}
+.rbc-agenda-view table.rbc-agenda-table thead > tr > th {
+ padding: 3px 5px;
+ text-align: left;
+ border-bottom: 1px solid #DDD;
+}
+.rbc-rtl .rbc-agenda-view table.rbc-agenda-table thead > tr > th {
+ text-align: right;
+}
+.rbc-agenda-time-cell {
+ text-transform: lowercase;
+}
+.rbc-agenda-time-cell .rbc-continues-after:after {
+ content: ' »';
+}
+.rbc-agenda-time-cell .rbc-continues-prior:before {
+ content: '« ';
+}
+.rbc-agenda-date-cell,
+.rbc-agenda-time-cell {
+ white-space: nowrap;
+}
+.rbc-agenda-event-cell {
+ width: 100%;
+}
+.rbc-time-column {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ min-height: 100%;
+}
+.rbc-time-column .rbc-timeslot-group {
+ -ms-flex: 1;
+ -webkit-box-flex: 1;
+ flex: 1;
+}
+.rbc-timeslot-group {
+ border-bottom: 1px solid #DDD;
+ min-height: 40px;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-flow: column nowrap;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-flow: column nowrap;
+}
+.rbc-time-gutter,
+.rbc-header-gutter {
+ -ms-flex: none;
+ -webkit-box-flex: 0;
+ flex: none;
+}
+.rbc-label {
+ padding: 0 5px;
+}
+.rbc-day-slot {
+ position: relative;
+}
+.rbc-day-slot .rbc-events-container {
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 10px;
+ top: 0;
+}
+.rbc-day-slot .rbc-events-container.rbc-is-rtl {
+ left: 10px;
+ right: 0;
+}
+.rbc-day-slot .rbc-event {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ max-height: 100%;
+ min-height: 20px;
+ -ms-flex-flow: column wrap;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-flow: column wrap;
+ -ms-flex-align: start;
+ -webkit-box-align: start;
+ align-items: flex-start;
+ overflow: hidden;
+ position: absolute;
+}
+.rbc-day-slot .rbc-event-label {
+ -ms-flex: none;
+ -webkit-box-flex: 0;
+ flex: none;
+ padding-right: 5px;
+ width: auto;
+}
+.rbc-day-slot .rbc-event-content {
+ width: 100%;
+ -ms-flex: 1 1 0px;
+ -webkit-box-flex: 1;
+ flex: 1 1 0;
+ word-wrap: break-word;
+ line-height: 1;
+ height: 100%;
+ min-height: 1em;
+}
+.rbc-day-slot .rbc-time-slot {
+ border-top: 1px solid #f7f7f7;
+}
+.rbc-time-slot {
+ -ms-flex: 1 0 0px;
+ -webkit-box-flex: 1;
+ flex: 1 0 0;
+ font-size: 11px;
+ padding: 3px 7px;
+
+}
+.rbc-time-slot.rbc-now {
+ font-weight: bold;
+}
+.rbc-day-header {
+ text-align: center;
+}
+.rbc-slot-selection {
+ z-index: 10;
+ position: absolute;
+ background-color: rgba(0, 0, 0, 0.5);
+ color: white;
+ font-size: 75%;
+ width: 100%;
+ padding: 3px;
+}
+.rbc-slot-selecting {
+ cursor: move;
+}
+.rbc-time-view {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -ms-flex: 1;
+ -webkit-box-flex: 1;
+ flex: 1;
+ width: 100%;
+ min-height: 0;
+}
+.rbc-time-view .rbc-time-gutter {
+ white-space: nowrap;
+}
+.rbc-time-view .rbc-allday-cell {
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+ width: 100%;
+ position: relative;
+}
+.rbc-time-view .rbc-allday-events {
+ position: relative;
+ z-index: 4;
+}
+.rbc-time-view .rbc-row {
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 20px;
+}
+.rbc-time-header {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex: 0 0 auto;
+ -webkit-box-flex: 0;
+ flex: 0 0 auto;
+ -ms-flex-direction: row;
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ flex-direction: row;
+}
+.rbc-time-header.rbc-overflowing {
+ border-right: 1px solid #DDD;
+}
+.rbc-rtl .rbc-time-header.rbc-overflowing {
+ border-right-width: 0;
+ border-left: 1px solid #DDD;
+}
+.rbc-time-header > .rbc-row:first-child {
+ border-bottom: 1px solid #DDD;
+}
+.rbc-time-header > .rbc-row.rbc-row-resource {
+ border-bottom: 1px solid #DDD;
+}
+.rbc-time-header-content {
+ -ms-flex: 1;
+ -webkit-box-flex: 1;
+ flex: 1;
+ min-width: 0;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ border-left: 1px solid #DDD;
+}
+.rbc-rtl .rbc-time-header-content {
+ border-left-width: 0;
+ border-right: 1px solid #DDD;
+}
+.rbc-time-content {
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: flex;
+ -ms-flex: 1 0 0%;
+ -webkit-box-flex: 1;
+ flex: 1 0 0%;
+ -ms-flex-align: start;
+ -webkit-box-align: start;
+ align-items: flex-start;
+ width: 100%;
+ border-top: 2px solid #DDD;
+ overflow-y: auto;
+ position: relative;
+}
+.rbc-time-content > .rbc-time-gutter {
+ -ms-flex: none;
+ -webkit-box-flex: 0;
+ flex: none;
+}
+.rbc-time-content > * + * > * {
+ border-left: 1px solid #DDD;
+}
+.rbc-rtl .rbc-time-content > * + * > * {
+ border-left-width: 0;
+ border-right: 1px solid #DDD;
+}
+.rbc-time-content > .rbc-day-slot {
+ width: 100%;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-user-select: none;
+}
+.rbc-current-time-indicator {
+ position: absolute;
+ z-index: 3;
+ height: 1px;
+ background-color: #74ad31;
+ pointer-events: none;
+}
+
+@media only screen and (max-width: 600px) {
+ .rbc-toolbar {
+ flex-direction: column
+ }
+ .rbc-btn-group {
+ width: 100%;
+ text-align: center;
+ overflow: auto;
+ }
+ .rbc-header {
+ border-right: 1px solid #fff;
+ }
+ .rbc-header span {
+ display: block;
+ visibility: hidden;
+ text-align: center
+ }
+ .rbc-header span:first-letter {
+ visibility: visible
+ }
+}
+
+.eventBlock {
+ line-height: 18px
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/vendors/react-draft-wysiwyg/react-draft-wysiwyg.css b/front/odiparpack/app/styles/components/vendors/react-draft-wysiwyg/react-draft-wysiwyg.css
new file mode 100644
index 0000000..048a8f1
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-draft-wysiwyg/react-draft-wysiwyg.css
@@ -0,0 +1,852 @@
+.rdw-option-wrapper {
+ border: 1px solid #F1F1F1;
+ padding: 5px;
+ min-width: 25px;
+ height: 20px;
+ border-radius: 2px;
+ margin: 0 4px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ background: white;
+ text-transform: capitalize;
+}
+.rdw-option-wrapper:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+}
+.rdw-option-wrapper:active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-option-active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-option-disabled {
+ opacity: 0.3;
+ cursor: default;
+}
+.rdw-dropdown-wrapper {
+ height: 30px;
+ background: white;
+ cursor: pointer;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ margin: 0 3px;
+ text-transform: capitalize;
+ background: white;
+}
+.rdw-dropdown-wrapper:focus {
+ outline: none;
+}
+.rdw-dropdown-wrapper:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+ background-color: #FFFFFF;
+}
+.rdw-dropdown-wrapper:active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-dropdown-carettoopen {
+ height: 0px;
+ width: 0px;
+ position: absolute;
+ top: 35%;
+ right: 10%;
+ border-top: 6px solid black;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+}
+.rdw-dropdown-carettoclose {
+ height: 0px;
+ width: 0px;
+ position: absolute;
+ top: 35%;
+ right: 10%;
+ border-bottom: 6px solid black;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+}
+.rdw-dropdown-selectedtext {
+ display: flex;
+ position: relative;
+ height: 100%;
+ align-items: center;
+ padding: 0 5px;
+}
+.rdw-dropdown-optionwrapper {
+ z-index: 100;
+ position: relative;
+ border: 1px solid #F1F1F1;
+ width: 98%;
+ background: white;
+ border-radius: 2px;
+ margin: 0;
+ padding: 0;
+ max-height: 250px;
+ overflow-y: scroll;
+}
+.rdw-dropdown-optionwrapper:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+ background-color: #FFFFFF;
+}
+.rdw-dropdownoption-default {
+ min-height: 25px;
+ display: flex;
+ align-items: center;
+ padding: 0 5px;
+}
+.rdw-dropdownoption-highlighted {
+ background: #F1F1F1;
+}
+.rdw-dropdownoption-active {
+ background: #f5f5f5;
+}
+.rdw-dropdownoption-disabled {
+ opacity: 0.3;
+ cursor: default;
+}
+.rdw-inline-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-inline-dropdown {
+ width: 50px;
+}
+.rdw-inline-dropdownoption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-block-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-block-dropdown {
+ width: 110px;
+}
+.rdw-fontsize-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-fontsize-dropdown {
+ min-width: 40px;
+}
+.rdw-fontsize-option {
+ display: flex;
+ justify-content: center;
+}
+.rdw-fontfamily-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-fontfamily-dropdown {
+ width: 115px;
+}
+.rdw-fontfamily-placeholder {
+ white-space: nowrap;
+ max-width: 90px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.rdw-fontfamily-optionwrapper {
+ width: 140px;
+}
+.rdw-list-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-list-dropdown {
+ width: 50px;
+ z-index: 90;
+}
+.rdw-list-dropdownOption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-text-align-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-text-align-dropdown {
+ width: 50px;
+ z-index: 90;
+}
+.rdw-text-align-dropdownOption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-right-aligned-block {
+ text-align: right;
+}
+.rdw-left-aligned-block {
+ text-align: left !important;
+}
+.rdw-center-aligned-block {
+ text-align: center !important;
+}
+.rdw-justify-aligned-block {
+ text-align: justify !important;
+}
+.rdw-right-aligned-block > div {
+ display: inline-block;
+}
+.rdw-left-aligned-block > div {
+ display: inline-block;
+}
+.rdw-center-aligned-block > div {
+ display: inline-block;
+}
+.rdw-justify-aligned-block > div {
+ display: inline-block;
+}
+.rdw-colorpicker-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-colorpicker-modal {
+ position: absolute;
+ top: 35px;
+ left: 5px;
+ display: flex;
+ flex-direction: column;
+ width: 175px;
+ height: 175px;
+ border: 1px solid #F1F1F1;
+ padding: 15px;
+ border-radius: 2px;
+ z-index: 100;
+ background: white;
+ box-shadow: 3px 3px 5px #BFBDBD;
+}
+.rdw-colorpicker-modal-header {
+ display: flex;
+ padding-bottom: 5px;
+}
+.rdw-colorpicker-modal-style-label {
+ font-size: 15px;
+ width: 50%;
+ text-align: center;
+ cursor: pointer;
+ padding: 0 10px 5px;
+}
+.rdw-colorpicker-modal-style-label-active {
+ border-bottom: 2px solid #0a66b7;
+}
+.rdw-colorpicker-modal-options {
+ margin: 5px auto;
+ display: flex;
+ width: 100%;
+ height: 100%;
+ flex-wrap: wrap;
+ overflow: scroll;
+}
+.rdw-colorpicker-cube {
+ width: 22px;
+ height: 22px;
+ border: 1px solid #F1F1F1;
+}
+.rdw-colorpicker-option {
+ margin: 3px;
+ padding: 0;
+ min-height: 20px;
+ border: none;
+ width: 22px;
+ height: 22px;
+ min-width: 22px;
+ box-shadow: 1px 2px 1px #BFBDBD inset;
+}
+.rdw-colorpicker-option:hover {
+ box-shadow: 1px 2px 1px #BFBDBD;
+}
+.rdw-colorpicker-option:active {
+ box-shadow: -1px -2px 1px #BFBDBD;
+}
+.rdw-colorpicker-option-active {
+ box-shadow: 0px 0px 2px 2px #BFBDBD;
+}
+.rdw-link-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-link-dropdown {
+ width: 50px;
+}
+.rdw-link-dropdownOption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-link-dropdownPlaceholder {
+ margin-left: 8px;
+}
+.rdw-link-modal {
+ position: absolute;
+ top: 35px;
+ left: 5px;
+ display: flex;
+ flex-direction: column;
+ width: 235px;
+ height: 205px;
+ border: 1px solid #F1F1F1;
+ padding: 15px;
+ border-radius: 2px;
+ z-index: 100;
+ background: white;
+ box-shadow: 3px 3px 5px #BFBDBD;
+}
+.rdw-link-modal-label {
+ font-size: 15px;
+}
+.rdw-link-modal-input {
+ margin-top: 5px;
+ border-radius: 2px;
+ border: 1px solid #F1F1F1;
+ height: 25px;
+ margin-bottom: 15px;
+ padding: 0 5px;
+}
+.rdw-link-modal-input:focus {
+ outline: none;
+}
+.rdw-link-modal-buttonsection {
+ margin: 0 auto;
+}
+.rdw-link-modal-target-option {
+ margin-bottom: 20px;
+}
+.rdw-link-modal-target-option > span {
+ margin-left: 5px;
+}
+.rdw-link-modal-btn {
+ margin-left: 10px;
+ width: 75px;
+ height: 30px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ cursor: pointer;
+ background: white;
+ text-transform: capitalize;
+}
+.rdw-link-modal-btn:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+}
+.rdw-link-modal-btn:active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-link-modal-btn:focus {
+ outline: none !important;
+}
+.rdw-link-modal-btn:disabled {
+ background: #ece9e9;
+}
+.rdw-link-dropdownoption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-history-dropdown {
+ width: 50px;
+}
+.rdw-embedded-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-embedded-modal {
+ position: absolute;
+ top: 35px;
+ left: 5px;
+ display: flex;
+ flex-direction: column;
+ width: 235px;
+ height: 180px;
+ border: 1px solid #F1F1F1;
+ padding: 15px;
+ border-radius: 2px;
+ z-index: 100;
+ background: white;
+ justify-content: space-between;
+ box-shadow: 3px 3px 5px #BFBDBD;
+}
+.rdw-embedded-modal-header {
+ font-size: 15px;
+ display: flex;
+}
+.rdw-embedded-modal-header-option {
+ width: 50%;
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+}
+.rdw-embedded-modal-header-label {
+ width: 95px;
+ border: 1px solid #f1f1f1;
+ margin-top: 5px;
+ background: #6EB8D4;
+ border-bottom: 2px solid #0a66b7;
+}
+.rdw-embedded-modal-link-section {
+ display: flex;
+ flex-direction: column;
+}
+.rdw-embedded-modal-link-input {
+ width: 88%;
+ height: 35px;
+ margin: 10px 0;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ font-size: 15px;
+ padding: 0 5px;
+}
+.rdw-embedded-modal-link-input-wrapper {
+ display: flex;
+ align-items: center;
+}
+.rdw-embedded-modal-link-input:focus {
+ outline: none;
+}
+.rdw-embedded-modal-btn-section {
+ display: flex;
+ justify-content: center;
+}
+.rdw-embedded-modal-btn {
+ margin: 0 3px;
+ width: 75px;
+ height: 30px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ cursor: pointer;
+ background: white;
+ text-transform: capitalize;
+}
+.rdw-embedded-modal-btn:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+}
+.rdw-embedded-modal-btn:active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-embedded-modal-btn:focus {
+ outline: none !important;
+}
+.rdw-embedded-modal-btn:disabled {
+ background: #ece9e9;
+}
+.rdw-embedded-modal-size {
+ align-items: center;
+ display: flex;
+ margin: 8px 0;
+ justify-content: space-between;
+}
+.rdw-embedded-modal-size-input {
+ width: 80%;
+ height: 20px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ font-size: 12px;
+}
+.rdw-embedded-modal-size-input:focus {
+ outline: none;
+}
+.rdw-emoji-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-emoji-modal {
+ overflow: auto;
+ position: absolute;
+ top: 35px;
+ left: 5px;
+ display: flex;
+ flex-wrap: wrap;
+ width: 235px;
+ height: 180px;
+ border: 1px solid #F1F1F1;
+ padding: 15px;
+ border-radius: 2px;
+ z-index: 100;
+ background: white;
+ box-shadow: 3px 3px 5px #BFBDBD;
+}
+.rdw-emoji-icon {
+ margin: 2.5px;
+ height: 24px;
+ width: 24px;
+ cursor: pointer;
+ font-size: 22px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+.rdw-spinner {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ width: 100%;
+}
+.rdw-spinner > div {
+ width: 12px;
+ height: 12px;
+ background-color: #333;
+
+ border-radius: 100%;
+ display: inline-block;
+ -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
+ animation: sk-bouncedelay 1.4s infinite ease-in-out both;
+}
+.rdw-spinner .rdw-bounce1 {
+ -webkit-animation-delay: -0.32s;
+ animation-delay: -0.32s;
+}
+.rdw-spinner .rdw-bounce2 {
+ -webkit-animation-delay: -0.16s;
+ animation-delay: -0.16s;
+}
+@-webkit-keyframes sk-bouncedelay {
+ 0%, 80%, 100% { -webkit-transform: scale(0) }
+ 40% { -webkit-transform: scale(1.0) }
+}
+@keyframes sk-bouncedelay {
+ 0%, 80%, 100% {
+ -webkit-transform: scale(0);
+ transform: scale(0);
+ } 40% {
+ -webkit-transform: scale(1.0);
+ transform: scale(1.0);
+ }
+}
+.rdw-image-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-image-modal {
+ position: absolute;
+ top: 35px;
+ left: 5px;
+ display: flex;
+ flex-direction: column;
+ width: 235px;
+ border: 1px solid #F1F1F1;
+ padding: 15px;
+ border-radius: 2px;
+ z-index: 100;
+ background: white;
+ box-shadow: 3px 3px 5px #BFBDBD;
+}
+.rdw-image-modal-header {
+ font-size: 15px;
+ margin: 10px 0;
+ display: flex;
+}
+.rdw-image-modal-header-option {
+ width: 50%;
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+}
+.rdw-image-modal-header-label {
+ width: 80px;
+ background: #f1f1f1;
+ border: 1px solid #f1f1f1;
+ margin-top: 5px;
+}
+.rdw-image-modal-header-label-highlighted {
+ background: #6EB8D4;
+ border-bottom: 2px solid #0a66b7;
+}
+.rdw-image-modal-upload-option {
+ width: 100%;
+ color: gray;
+ cursor: pointer;
+ display: flex;
+ border: none;
+ font-size: 15px;
+ align-items: center;
+ justify-content: center;
+ background-color: #f1f1f1;
+ outline: 2px dashed gray;
+ outline-offset: -10px;
+ margin: 10px 0;
+ padding: 9px 0;
+}
+.rdw-image-modal-upload-option-highlighted {
+ outline: 2px dashed #0a66b7;
+}
+.rdw-image-modal-upload-option-label {
+ cursor: pointer;
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+}
+.rdw-image-modal-upload-option-label span{
+ padding: 0 20px;
+}
+.rdw-image-modal-upload-option-image-preview {
+ max-width: 100%;
+ max-height: 200px;
+}
+.rdw-image-modal-upload-option-input {
+ width: 0.1px;
+ height: 0.1px;
+ opacity: 0;
+ overflow: hidden;
+ position: absolute;
+ z-index: -1;
+}
+.rdw-image-modal-url-section {
+ display: flex;
+ align-items: center;
+}
+.rdw-image-modal-url-input {
+ width: 90%;
+ height: 35px;
+ margin: 15px 0 12px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ font-size: 15px;
+ padding: 0 5px;
+}
+.rdw-image-modal-btn-section {
+ margin: 10px auto 0;
+}
+.rdw-image-modal-url-input:focus {
+ outline: none;
+}
+.rdw-image-modal-btn {
+ margin: 0 5px;
+ width: 75px;
+ height: 30px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ cursor: pointer;
+ background: white;
+ text-transform: capitalize;
+}
+.rdw-image-modal-btn:hover {
+ box-shadow: 1px 1px 0px #BFBDBD;
+}
+.rdw-image-modal-btn:active {
+ box-shadow: 1px 1px 0px #BFBDBD inset;
+}
+.rdw-image-modal-btn:focus {
+ outline: none !important;
+}
+.rdw-image-modal-btn:disabled {
+ background: #ece9e9;
+}
+.rdw-image-modal-spinner {
+ position: absolute;
+ top: -3px;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0.5;
+}
+.rdw-image-modal-alt-input {
+ width: 70%;
+ height: 20px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ font-size: 12px;
+ margin-left: 5px;
+}
+.rdw-image-modal-alt-input:focus {
+ outline: none;
+}
+.rdw-image-modal-alt-lbl {
+ font-size: 12px;
+}
+.rdw-image-modal-size {
+ align-items: center;
+ display: flex;
+ margin: 8px 0;
+ justify-content: space-between;
+}
+.rdw-image-modal-size-input {
+ width: 40%;
+ height: 20px;
+ border: 1px solid #F1F1F1;
+ border-radius: 2px;
+ font-size: 12px;
+}
+.rdw-image-modal-size-input:focus {
+ outline: none;
+}
+.rdw-image-mandatory-sign {
+ color: red;
+ margin-left: 3px;
+ margin-right: 3px;
+}
+.rdw-remove-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ position: relative;
+}
+.rdw-history-wrapper {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.rdw-history-dropdownoption {
+ height: 40px;
+ display: flex;
+ justify-content: center;
+}
+.rdw-history-dropdown {
+ width: 50px;
+}
+.rdw-link-decorator-wrapper {
+ position: relative;
+}
+.rdw-link-decorator-icon {
+ position: absolute;
+ left: 40%;
+ top: 0;
+ cursor: pointer;
+ background-color: white;
+}
+.rdw-mention-link {
+ text-decoration: none;
+ color: #1236ff;
+ background-color: #f0fbff;
+ padding: 1px 2px;
+ border-radius: 2px;
+}
+.rdw-suggestion-wrapper {
+ position: relative;
+}
+.rdw-suggestion-dropdown {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ border: 1px solid #F1F1F1;
+ min-width: 100px;
+ max-height: 150px;
+ overflow: auto;
+ background: white;
+ z-index: 100;
+}
+.rdw-suggestion-option {
+ padding: 7px 5px;
+ border-bottom: 1px solid #f1f1f1;
+}
+.rdw-suggestion-option-active {
+ background-color: #F1F1F1;
+}
+.rdw-hashtag-link {
+ text-decoration: none;
+ color: #1236ff;
+ background-color: #f0fbff;
+ padding: 1px 2px;
+ border-radius: 2px;
+}
+.rdw-image-alignment-options-popup {
+ position: absolute;;
+ background: white;
+ display: flex;
+ padding: 5px 2px;
+ border-radius: 2px;
+ border: 1px solid #F1F1F1;
+ width: 105px;
+ cursor: pointer;
+ z-index: 100;
+}
+.rdw-alignment-option-left {
+ justify-content: flex-start;
+}
+.rdw-image-alignment-option {
+ height: 15px;
+ width: 15px;
+ min-width: 15px;
+}
+.rdw-image-alignment {
+ position: relative;
+}
+.rdw-image-imagewrapper {
+ position: relative;
+}
+.rdw-image-center {
+ display: flex;
+ justify-content: center;
+}
+.rdw-image-left {
+ display: flex;
+}
+.rdw-image-right {
+ display: flex;
+ justify-content: flex-end;
+}
+.rdw-image-alignment-options-popup-right {
+ right: 0;
+}
+.rdw-editor-main {
+ height: 100%;
+ overflow: auto;
+ box-sizing: border-box;
+}
+.rdw-editor-toolbar {
+ padding: 6px 5px 0;
+ border-radius: 2px;
+ border: 1px solid #F1F1F1;
+ display: flex;
+ justify-content: flex-start;
+ background: white;
+ flex-wrap: wrap;
+ font-size: 15px;
+ margin-bottom: 5px;
+ user-select: none;
+}
+.public-DraftStyleDefault-block {
+ margin: 1em 0;
+}
+.rdw-editor-wrapper:focus {
+ outline: none;
+}
+.rdw-editor-wrapper {
+ box-sizing: content-box;
+}
+.rdw-editor-main blockquote {
+ border-left: 5px solid #f1f1f1;
+ padding-left: 5px;
+}
+.rdw-editor-main pre {
+ background: #f1f1f1;
+ border-radius: 3px;
+ padding: 1px 10px;
+}/**
+ * Draft v0.9.1
+ *
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:rgba(255,255,255,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:0}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}
+
+/*# sourceMappingURL=react-draft-wysiwyg.css.map*/
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/vendors/react-dropzone/react-dropzone.css b/front/odiparpack/app/styles/components/vendors/react-dropzone/react-dropzone.css
new file mode 100644
index 0000000..ff4ae01
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-dropzone/react-dropzone.css
@@ -0,0 +1,182 @@
+.dropzoneTextStyle {
+ text-align: center;
+ top: 25%;
+ position: relative;
+}
+
+.dropzoneParagraph {
+ font-size: 24px
+}
+
+.dropZone {
+ position: relative;
+ width: 100%;
+ height: 250px;
+ border: 2px dashed;
+ cursor: pointer;
+ padding: 20px;
+}
+
+.stripes {
+ width: 100%;
+ height: 250px;
+ cursor: pointer;
+ border: solid;
+ border-color: #C8C8C8;
+ background-image: repeating-linear-gradient(-45deg, #F0F0F0, #F0F0F0 25px, #C8C8C8 25px, #C8C8C8 50px);
+ -webkit-animation: progress 2s linear infinite !important;
+ -moz-animation: progress 2s linear infinite !important;
+ animation: progress 2s linear infinite !important;
+ background-size: 150% 100%;
+}
+
+.rejectStripes {
+ width: 100%;
+ height: 250px;
+ cursor: pointer;
+ border: solid;
+ border-color: #C8C8C8;
+ background-image: repeating-linear-gradient(-45deg, #fc8785, #fc8785 25px, #f4231f 25px, #f4231f 50px);
+ -webkit-animation: progress 2s linear infinite !important;
+ -moz-animation: progress 2s linear infinite !important;
+ animation: progress 2s linear infinite !important;
+ background-size: 150% 100%;
+}
+
+.fileIconImg {
+ color: #909090 !important;
+}
+
+.smallPreviewImg {
+ height: 100px !important;
+ width: initial !important;
+ max-width: 100%;
+}
+
+@-webkit-keyframes progress {
+ 0% {
+ background-position: 0 0;
+ }
+ 100% {
+ background-position: -75px 0;
+ }
+}
+
+@-moz-keyframes progress {
+ 0% {
+ background-position: 0 0;
+ }
+ 100% {
+ background-position: -75px 0;
+ }
+}
+
+@-ms-keyframes progress {
+ 0% {
+ background-position: 0 0;
+ }
+ 100% {
+ background-position: -75px 0;
+ }
+}
+
+@keyframes progress {
+ 0% {
+ background-position: 0 0;
+ }
+ 100% {
+ background-position: -70px 0;
+ }
+}
+
+.imageContainer {
+ position: relative;
+ z-index: 10;
+ margin-bottom: 5px
+}
+
+.imageContainer:hover .smallPreviewImg {
+ opacity: 0.7;
+}
+
+.imageContainer:hover .middle {
+ opacity: 1;
+}
+
+.imageContainer:hover .middleBigPic {
+ opacity: 1;
+}
+
+.removeBtn {
+ color: white;
+ z-index: 3;
+}
+
+.middle {
+ transition: .5s ease;
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ right: 5px;
+ z-index: 20
+}
+
+.row {
+ margin-right: -0.5rem;
+ margin-left: -0.5rem;
+ box-sizing: border-box;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ flex: 0 1 auto;
+ -webkit-box-flex: 0;
+ -ms-flex: 0 1 auto;
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.preview {
+ margin: 10px
+}
+
+.imgWrap, .fileWrap {
+ color: #c7c7c7;
+ transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms !important;
+ box-sizing: border-box;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ box-shadow: rgba(0, 0, 0, 0.12) 0 1px 6px, rgba(0, 0, 0, 0.12) 0 1px 4px !important;
+ border-radius: 2px;
+ z-index: 5;
+ overflow: hidden;
+ text-align: center;
+ height: 100px;
+ position: relative;
+}
+
+.imgWrap {
+ background: #c7c7c7;
+}
+
+.fileWrap {
+ background: #e2e2e2;
+ color: #969696;
+}
+
+.downloadBtn {
+ position: absolute;
+ right: 0;
+ top: 0;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.4);
+ z-index: 10;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
diff --git a/front/odiparpack/app/styles/components/vendors/react-input-range/react-input-range.css b/front/odiparpack/app/styles/components/vendors/react-input-range/react-input-range.css
new file mode 100644
index 0000000..323d18f
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-input-range/react-input-range.css
@@ -0,0 +1,92 @@
+.input-range__slider {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: #3f51b5;
+ border: 1px solid #3f51b5;
+ border-radius: 100%;
+ cursor: pointer;
+ display: block;
+ height: 1rem;
+ margin-left: -0.5rem;
+ margin-top: -0.65rem;
+ outline: none;
+ position: absolute;
+ top: 50%;
+ -webkit-transition: box-shadow 0.3s ease-out, -webkit-transform 0.3s ease-out;
+ transition: box-shadow 0.3s ease-out, -webkit-transform 0.3s ease-out;
+ transition: transform 0.3s ease-out, box-shadow 0.3s ease-out;
+ transition: transform 0.3s ease-out, box-shadow 0.3s ease-out, -webkit-transform 0.3s ease-out;
+ width: 1rem; }
+ .input-range__slider:active {
+ -webkit-transform: scale(1.3);
+ transform: scale(1.3); }
+ .input-range__slider:focus {
+ box-shadow: 0 0 0 5px rgba(63, 81, 181, 0.2); }
+ .input-range--disabled .input-range__slider {
+ background: #cccccc;
+ border: 1px solid #cccccc;
+ box-shadow: none;
+ -webkit-transform: none;
+ transform: none; }
+
+.input-range__slider-container {
+ -webkit-transition: left 0.3s ease-out;
+ transition: left 0.3s ease-out; }
+
+.input-range__label {
+ color: #aaaaaa;
+ font-family: "Helvetica Neue", san-serif;
+ font-size: 0.8rem;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ white-space: nowrap; }
+
+.input-range__label--min,
+.input-range__label--max {
+ bottom: -1.4rem;
+ position: absolute; }
+
+.input-range__label--min {
+ left: 0; }
+
+.input-range__label--max {
+ right: 0; }
+
+.input-range__label--value {
+ position: absolute;
+ top: -1.8rem; }
+
+.input-range__label-container {
+ left: -50%;
+ position: relative; }
+ .input-range__label--max .input-range__label-container {
+ left: 50%; }
+
+.input-range__track {
+ background: #eeeeee;
+ border-radius: 0.3rem;
+ cursor: pointer;
+ display: block;
+ height: 0.3rem;
+ position: relative;
+ -webkit-transition: left 0.3s ease-out, width 0.3s ease-out;
+ transition: left 0.3s ease-out, width 0.3s ease-out; }
+ .input-range--disabled .input-range__track {
+ background: #eeeeee; }
+
+.input-range__track--background {
+ left: 0;
+ margin-top: -0.15rem;
+ position: absolute;
+ right: 0;
+ top: 50%; }
+
+.input-range__track--active {
+ background: #3f51b5; }
+
+.input-range {
+ height: 1rem;
+ position: relative;
+ width: 100%; }
+
diff --git a/front/odiparpack/app/styles/components/vendors/react-loading-bar/index.css b/front/odiparpack/app/styles/components/vendors/react-loading-bar/index.css
new file mode 100644
index 0000000..8301b01
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/react-loading-bar/index.css
@@ -0,0 +1,71 @@
+.Loading__loading___1m_fZ {
+ pointer-events: none;
+ transition: 400ms linear all;
+}
+
+.Loading__bar___21yOt {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 10002;
+ display: none;
+ width: 100%;
+ height: 2px;
+ background: #29d;
+ border-radius: 0 1px 1px 0;
+ transition: width 350ms;
+}
+
+.Loading__peg___3Y_28 {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 70px;
+ height: 2px;
+ border-radius: 50%;
+ opacity: .45;
+ box-shadow: #29d 1px 0 6px 1px;
+}
+
+.Loading__spinner___11Pm4 {
+ position: fixed;
+ top: 5px;
+ left: 5px;
+ z-index: 10002;
+ pointer-events: none;
+ transition: 350ms linear all;
+}
+
+.Loading__icon___3OOyu {
+ width: 14px;
+ height: 14px;
+ border: solid #29d;
+ border-width: 0 2px 2px 0;
+ border-radius: 50%;
+ -webkit-animation: Loading__loading-bar-spinner___1hKY9 400ms linear infinite;
+ animation: Loading__loading-bar-spinner___1hKY9 400ms linear infinite;
+}
+
+@-webkit-keyframes Loading__loading-bar-spinner___1hKY9 {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes Loading__loading-bar-spinner___1hKY9 {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
diff --git a/front/odiparpack/app/styles/components/vendors/select/select.css b/front/odiparpack/app/styles/components/vendors/select/select.css
new file mode 100644
index 0000000..89a11f4
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/select/select.css
@@ -0,0 +1,420 @@
+.Select {
+ position: relative;
+}
+.Select input::-webkit-contacts-auto-fill-button,
+.Select input::-webkit-credentials-auto-fill-button {
+ display: none !important;
+}
+.Select input::-ms-clear {
+ display: none !important;
+}
+.Select input::-ms-reveal {
+ display: none !important;
+}
+.Select,
+.Select div,
+.Select input,
+.Select span {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.Select.is-disabled .Select-arrow-zone {
+ cursor: default;
+ pointer-events: none;
+ opacity: 0.35;
+}
+.Select.is-disabled > .Select-control {
+ background-color: #f9f9f9;
+}
+.Select.is-disabled > .Select-control:hover {
+ box-shadow: none;
+}
+.Select.is-open > .Select-control {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ background: #fff;
+ border-color: #b3b3b3 #ccc #d9d9d9;
+}
+.Select.is-open > .Select-control .Select-arrow {
+ top: -2px;
+ border-color: transparent transparent #999;
+ border-width: 0 5px 5px;
+}
+.Select.is-searchable.is-open > .Select-control {
+ cursor: text;
+}
+.Select.is-searchable.is-focused:not(.is-open) > .Select-control {
+ cursor: text;
+}
+.Select.is-focused > .Select-control {
+ background: #fff;
+}
+.Select.is-focused:not(.is-open) > .Select-control {
+ border-color: #007eff;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 0 3px rgba(0, 126, 255, 0.1);
+ background: #fff;
+}
+.Select.has-value.is-clearable.Select--single > .Select-control .Select-value {
+ padding-right: 42px;
+}
+.Select.has-value.Select--single > .Select-control .Select-value .Select-value-label,
+.Select.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value .Select-value-label {
+ color: #333;
+}
+.Select.has-value.Select--single > .Select-control .Select-value a.Select-value-label,
+.Select.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label {
+ cursor: pointer;
+ text-decoration: none;
+}
+.Select.has-value.Select--single > .Select-control .Select-value a.Select-value-label:hover,
+.Select.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:hover,
+.Select.has-value.Select--single > .Select-control .Select-value a.Select-value-label:focus,
+.Select.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:focus {
+ color: #007eff;
+ outline: none;
+ text-decoration: underline;
+}
+.Select.has-value.Select--single > .Select-control .Select-value a.Select-value-label:focus,
+.Select.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:focus {
+ background: #fff;
+}
+.Select.has-value.is-pseudo-focused .Select-input {
+ opacity: 0;
+}
+.Select.is-open .Select-arrow,
+.Select .Select-arrow-zone:hover > .Select-arrow {
+ border-top-color: #666;
+}
+.Select.Select--rtl {
+ direction: rtl;
+ text-align: right;
+}
+.Select-control {
+ background-color: #fff;
+ border-color: #d9d9d9 #ccc #b3b3b3;
+ border-radius: 4px;
+ border: 1px solid #ccc;
+ color: #333;
+ cursor: default;
+ display: table;
+ border-spacing: 0;
+ border-collapse: separate;
+ height: 36px;
+ outline: none;
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+}
+.Select-control:hover {
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
+}
+.Select-control .Select-input:focus {
+ outline: none;
+ background: #fff;
+}
+.Select-placeholder,
+.Select--single > .Select-control .Select-value {
+ bottom: 0;
+ color: #000;
+ left: 0;
+ line-height: 34px;
+ padding-left: 10px;
+ padding-right: 10px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.Select-input {
+ height: 34px;
+ padding-left: 10px;
+ padding-right: 10px;
+ vertical-align: middle;
+}
+.Select-input > input {
+ width: 100%;
+ background: none transparent;
+ border: 0 none;
+ box-shadow: none;
+ cursor: default;
+ display: inline-block;
+ font-family: inherit;
+ font-size: inherit;
+ margin: 0;
+ outline: none;
+ line-height: 17px;
+ /* For IE 8 compatibility */
+ padding: 8px 0 12px;
+ /* For IE 8 compatibility */
+ -webkit-appearance: none;
+}
+.is-focused .Select-input > input {
+ cursor: text;
+}
+.has-value.is-pseudo-focused .Select-input {
+ opacity: 0;
+}
+.Select-control:not(.is-searchable) > .Select-input {
+ outline: none;
+}
+.Select-loading-zone {
+ cursor: pointer;
+ display: table-cell;
+ position: relative;
+ text-align: center;
+ vertical-align: middle;
+ width: 16px;
+}
+.Select-loading {
+ -webkit-animation: Select-animation-spin 400ms infinite linear;
+ -o-animation: Select-animation-spin 400ms infinite linear;
+ animation: Select-animation-spin 400ms infinite linear;
+ width: 16px;
+ height: 16px;
+ box-sizing: border-box;
+ border-radius: 50%;
+ border: 2px solid #ccc;
+ border-right-color: #333;
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+}
+.Select-clear-zone {
+ -webkit-animation: Select-animation-fadeIn 200ms;
+ -o-animation: Select-animation-fadeIn 200ms;
+ animation: Select-animation-fadeIn 200ms;
+ color: #999;
+ cursor: pointer;
+ display: table-cell;
+ position: relative;
+ text-align: center;
+ vertical-align: middle;
+ width: 17px;
+}
+.Select-clear-zone:hover {
+ color: #D0021B;
+}
+.Select-clear {
+ display: inline-block;
+ font-size: 18px;
+ line-height: 1;
+}
+.Select--multi .Select-clear-zone {
+ width: 17px;
+}
+.Select-arrow-zone {
+ cursor: pointer;
+ display: table-cell;
+ position: relative;
+ text-align: center;
+ vertical-align: middle;
+ width: 25px;
+ padding-right: 5px;
+}
+.Select--rtl .Select-arrow-zone {
+ padding-right: 0;
+ padding-left: 5px;
+}
+.Select-arrow {
+ border-color: #999 transparent transparent;
+ border-style: solid;
+ border-width: 5px 5px 2.5px;
+ display: inline-block;
+ height: 0;
+ width: 0;
+ position: relative;
+}
+.Select-control > *:last-child {
+ padding-right: 5px;
+}
+.Select--multi .Select-multi-value-wrapper {
+ display: inline-block;
+}
+.Select .Select-aria-only {
+ position: absolute;
+ display: inline-block;
+ height: 1px;
+ width: 1px;
+ margin: -1px;
+ clip: rect(0, 0, 0, 0);
+ overflow: hidden;
+ float: left;
+}
+@-webkit-keyframes Select-animation-fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+@keyframes Select-animation-fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+.Select-menu-outer {
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border-top-color: #e6e6e6;
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
+ box-sizing: border-box;
+ margin-top: -1px;
+ max-height: 200px;
+ position: absolute;
+ left: 0;
+ top: 100%;
+ width: 100%;
+ z-index: 1;
+ -webkit-overflow-scrolling: touch;
+}
+.Select-menu {
+ max-height: 198px;
+ overflow-y: auto;
+}
+.Select-option {
+ box-sizing: border-box;
+ background-color: #fff;
+ color: #666666;
+ cursor: pointer;
+ display: block;
+ padding: 8px 10px;
+}
+.Select-option:last-child {
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.Select-option.is-selected {
+ background-color: #f5faff;
+ /* Fallback color for IE 8 */
+ background-color: rgba(0, 126, 255, 0.04);
+ color: #333;
+}
+.Select-option.is-focused {
+ background-color: #ebf5ff;
+ /* Fallback color for IE 8 */
+ background-color: rgba(0, 126, 255, 0.08);
+ color: #333;
+}
+.Select-option.is-disabled {
+ color: #cccccc;
+ cursor: default;
+}
+.Select-noresults {
+ box-sizing: border-box;
+ color: #999999;
+ cursor: default;
+ display: block;
+ padding: 8px 10px;
+}
+.Select--multi .Select-input {
+ vertical-align: middle;
+ margin-left: 10px;
+ padding: 0;
+}
+.Select--multi.Select--rtl .Select-input {
+ margin-left: 0;
+ margin-right: 10px;
+}
+.Select--multi.has-value .Select-input {
+ margin-left: 5px;
+}
+.Select--multi .Select-value {
+ background-color: #ebf5ff;
+ /* Fallback color for IE 8 */
+ background-color: rgba(0, 126, 255, 0.08);
+ border-radius: 2px;
+ border: 1px solid #c2e0ff;
+ /* Fallback color for IE 8 */
+ border: 1px solid rgba(0, 126, 255, 0.24);
+ color: #007eff;
+ display: inline-block;
+ font-size: 0.9em;
+ line-height: 1.4;
+ margin-left: 5px;
+ margin-top: 5px;
+ vertical-align: top;
+}
+.Select--multi .Select-value-icon,
+.Select--multi .Select-value-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.Select--multi .Select-value-label {
+ border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+ cursor: default;
+ padding: 2px 5px;
+}
+.Select--multi a.Select-value-label {
+ color: #007eff;
+ cursor: pointer;
+ text-decoration: none;
+}
+.Select--multi a.Select-value-label:hover {
+ text-decoration: underline;
+}
+.Select--multi .Select-value-icon {
+ cursor: pointer;
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+ border-right: 1px solid #c2e0ff;
+ /* Fallback color for IE 8 */
+ border-right: 1px solid rgba(0, 126, 255, 0.24);
+ padding: 1px 5px 3px;
+}
+.Select--multi .Select-value-icon:hover,
+.Select--multi .Select-value-icon:focus {
+ background-color: #d8eafd;
+ /* Fallback color for IE 8 */
+ background-color: rgba(0, 113, 230, 0.08);
+ color: #0071e6;
+}
+.Select--multi .Select-value-icon:active {
+ background-color: #c2e0ff;
+ /* Fallback color for IE 8 */
+ background-color: rgba(0, 126, 255, 0.24);
+}
+.Select--multi.Select--rtl .Select-value {
+ margin-left: 0;
+ margin-right: 5px;
+}
+.Select--multi.Select--rtl .Select-value-icon {
+ border-right: none;
+ border-left: 1px solid #c2e0ff;
+ /* Fallback color for IE 8 */
+ border-left: 1px solid rgba(0, 126, 255, 0.24);
+}
+.Select--multi.is-disabled .Select-value {
+ background-color: #fcfcfc;
+ border: 1px solid #e3e3e3;
+ color: #333;
+}
+.Select--multi.is-disabled .Select-value-icon {
+ cursor: not-allowed;
+ border-right: 1px solid #e3e3e3;
+}
+.Select--multi.is-disabled .Select-value-icon:hover,
+.Select--multi.is-disabled .Select-value-icon:focus,
+.Select--multi.is-disabled .Select-value-icon:active {
+ background-color: #fcfcfc;
+}
+@keyframes Select-animation-spin {
+ to {
+ transform: rotate(1turn);
+ }
+}
+@-webkit-keyframes Select-animation-spin {
+ to {
+ -webkit-transform: rotate(1turn);
+ }
+}
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/ajax-loader.gif b/front/odiparpack/app/styles/components/vendors/slick-carousel/ajax-loader.gif
new file mode 100644
index 0000000..e0e6e97
Binary files /dev/null and b/front/odiparpack/app/styles/components/vendors/slick-carousel/ajax-loader.gif differ
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.eot b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.eot
new file mode 100644
index 0000000..2cbab9c
Binary files /dev/null and b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.eot differ
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.svg b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.svg
new file mode 100644
index 0000000..b36a66a
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.svg
@@ -0,0 +1,14 @@
+
+
+
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.ttf b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.ttf
new file mode 100644
index 0000000..9d03461
Binary files /dev/null and b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.ttf differ
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.woff b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.woff
new file mode 100644
index 0000000..8ee9972
Binary files /dev/null and b/front/odiparpack/app/styles/components/vendors/slick-carousel/fonts/slick.woff differ
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-carousel.css b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-carousel.css
new file mode 100644
index 0000000..8d91736
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-carousel.css
@@ -0,0 +1,118 @@
+.variable-width .slick-slide p {
+ background: blue;
+ height: 100px;
+ color: #fff;
+ margin: 5px;
+ line-height: 100px;
+ text-align: center;
+}
+.center .slick-center h3 {
+ color: #e67e22;
+ opacity: 1;
+ transform: scale(1.08);
+}
+.center h3 {
+ opacity: 0.8;
+ transition: all 300ms ease;
+}
+.content {
+ padding: 20px;
+ margin: auto;
+ width: 90%;
+}
+.slick-slide {
+ transition: transform .3s
+}
+.slick-slide .image {
+ padding: 10px;
+}
+.slick-slide img {
+ border: 5px solid #fff;
+ display: block;
+ margin: auto;
+}
+.slick-slide img.slick-loading {
+ border: 0;
+}
+.slick-slider {
+ margin: 0 auto 32px;
+}
+.slick-dots {
+ margin-left: 0;
+}
+.slick-thumb {
+ bottom: -45px;
+}
+.slick-thumb li {
+ width: 60px;
+ height: 45px;
+}
+.slick-thumb li img {
+ filter: grayscale(100%);
+}
+.slick-thumb li.slick-active img {
+ filter: grayscale(0%);
+}
+@media (max-width: 768px) {
+ h3 {
+ font-size: 24px;
+ }
+ .center {
+ margin-left: -40px;
+ margin-right: -40px;
+ }
+ .center .slick-center h3 {
+ color: #e67e22;
+ opacity: 1;
+ transform: scale(1);
+ }
+ .center h3 {
+ opacity: 0.8;
+ transform: scale(0.95);
+ transition: all 300ms ease;
+ }
+}
+.slick-vertical .slick-slide {
+ height: 180px;
+}
+button.slick-arrow {
+ background-color: grey !important;
+ width: 40px;
+ height: 40px;
+ padding-top: 5px;
+ z-index: 10;
+}
+button.slick-arrow:before{
+ font-size: 36px;
+}
+button.slick-arrow:hover,
+button.slick-arrow:focus: {
+ background-color: grey;
+}
+.slick-center{
+ transform: scale(1.2);
+}
+.thumb-nav .slick-dots {
+ margin: 20px 0;
+ bottom: -60px;
+}
+.thumb-nav .slick-dots li{
+ width: 60px;
+ height: auto;
+ max-width: none;
+}
+.thumb-nav .slick-dots li.slick-active{
+ border-bottom: 2px solid grey;
+}
+.custom-arrow .nav-prev,
+.custom-arrow .nav-next{
+ position: absolute;
+ bottom: -40px;
+ z-index: 10;
+}
+.custom-arrow .nav-prev{
+ left: 0
+}
+.custom-arrow .nav-next{
+ right: 0
+}
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-theme.css b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-theme.css
new file mode 100644
index 0000000..5566c15
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick-theme.css
@@ -0,0 +1,213 @@
+@charset 'UTF-8';
+/* Slider */
+.slick-loading .slick-list
+{
+ background: #fff url('./ajax-loader.gif') center center no-repeat;
+}
+
+/* Icons */
+@font-face
+{
+ font-family: 'slick';
+ font-weight: normal;
+ font-style: normal;
+
+ src: url('./fonts/slick.eot');
+ src: url('./fonts/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick.woff') format('woff'), url('./fonts/slick.ttf') format('truetype'), url('./fonts/slick.svg#slick') format('svg');
+}
+/* Arrows */
+.slick-prev,
+.slick-next
+{
+ font-size: 0;
+ line-height: 0;
+
+ position: absolute;
+ top: 50%;
+
+ display: block;
+
+ width: 20px;
+ height: 20px;
+ padding: 0;
+ -webkit-transform: translate(0, -50%);
+ -ms-transform: translate(0, -50%);
+ transform: translate(0, -50%);
+
+ cursor: pointer;
+
+ color: transparent;
+ border: none;
+ outline: none;
+ background: transparent;
+}
+.slick-prev:hover,
+.slick-prev:focus,
+.slick-next:hover,
+.slick-next:focus
+{
+ color: transparent;
+ outline: none;
+ background: transparent;
+}
+.slick-prev:hover:before,
+.slick-prev:focus:before,
+.slick-next:hover:before,
+.slick-next:focus:before
+{
+ opacity: 1;
+}
+.slick-prev.slick-disabled:before,
+.slick-next.slick-disabled:before
+{
+ opacity: .25;
+}
+
+.slick-prev:before,
+.slick-next:before
+{
+ font-family: 'slick';
+ font-size: 20px;
+ line-height: 1;
+
+ opacity: .75;
+ color: white;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.slick-prev
+{
+ left: -25px;
+}
+[dir='rtl'] .slick-prev
+{
+ right: -25px;
+ left: auto;
+}
+.slick-prev:before
+{
+ content: '←';
+}
+[dir='rtl'] .slick-prev:before
+{
+ content: '→';
+}
+
+.slick-next
+{
+ right: -25px;
+}
+[dir='rtl'] .slick-next
+{
+ right: auto;
+ left: -25px;
+}
+.slick-next:before
+{
+ content: '→';
+}
+[dir='rtl'] .slick-next:before
+{
+ content: '←';
+}
+
+/* Dots */
+.slick-dotted.slick-slider
+{
+ margin-bottom: 30px;
+}
+
+.slick-dots
+{
+ position: absolute;
+ bottom: -25px;
+
+ display: block;
+
+ width: 100%;
+ padding: 0;
+ margin: 0;
+
+ list-style: none;
+
+ text-align: center;
+}
+.slick-dots li
+{
+ position: relative;
+
+ display: inline-block;
+
+ width: 20px;
+ height: 20px;
+ margin: 0 5px;
+ padding: 0;
+
+ cursor: pointer;
+}
+.slick-dots li button
+{
+ font-size: 0;
+ line-height: 0;
+
+ display: block;
+
+ width: 20px;
+ height: 20px;
+ padding: 5px;
+
+ cursor: pointer;
+
+ color: transparent;
+ border: 0;
+ outline: none;
+ background: transparent;
+}
+.slick-dots li button:hover,
+.slick-dots li button:focus
+{
+ outline: none;
+}
+.slick-dots li button:hover:before,
+.slick-dots li button:focus:before
+{
+ opacity: 1;
+}
+.slick-dots li button:before
+{
+ font-family: 'slick';
+ font-size: 6px;
+ line-height: 20px;
+
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ width: 20px;
+ height: 20px;
+
+ content: '•';
+ text-align: center;
+
+ opacity: .25;
+ color: black;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.slick-dots li.slick-active button:before
+{
+ opacity: .75;
+ color: black;
+}
+
+@media only screen and (max-width: 960px) {
+ .slick-next {
+ right: 5px
+ }
+ .slick-prev {
+ left: 5px
+ }
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/components/vendors/slick-carousel/slick.css b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick.css
new file mode 100644
index 0000000..cd76a53
--- /dev/null
+++ b/front/odiparpack/app/styles/components/vendors/slick-carousel/slick.css
@@ -0,0 +1,119 @@
+/* Slider */
+.slick-slider
+{
+ position: relative;
+
+ display: block;
+ box-sizing: border-box;
+
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ -webkit-touch-callout: none;
+ -khtml-user-select: none;
+ -ms-touch-action: pan-y;
+ touch-action: pan-y;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.slick-list
+{
+ position: relative;
+
+ display: block;
+ overflow: hidden;
+
+ margin: 0 -4px;
+ padding: 0;
+}
+.slick-list:focus
+{
+ outline: none;
+}
+.slick-list.dragging
+{
+ cursor: pointer;
+ cursor: hand;
+}
+
+.slick-slider .slick-track,
+.slick-slider .slick-list
+{
+ -webkit-transform: translate3d(0, 0, 0);
+ -moz-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ -o-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+
+.slick-track
+{
+ position: relative;
+ top: 0;
+ left: 0;
+
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+.slick-track:before,
+.slick-track:after
+{
+ display: table;
+
+ content: '';
+}
+.slick-track:after
+{
+ clear: both;
+}
+.slick-loading .slick-track
+{
+ visibility: hidden;
+}
+
+.slick-slide
+{
+ display: none;
+ float: left;
+
+ height: 100%;
+ min-height: 1px;
+}
+[dir='rtl'] .slick-slide
+{
+ float: right;
+}
+.slick-slide img
+{
+ display: block;
+}
+.slick-slide.slick-loading img
+{
+ display: none;
+}
+.slick-slide.dragging img
+{
+ pointer-events: none;
+}
+.slick-initialized .slick-slide
+{
+ display: block;
+}
+.slick-loading .slick-slide
+{
+ visibility: hidden;
+}
+.slick-vertical .slick-slide
+{
+ display: block;
+
+ height: auto;
+
+ border: 1px solid transparent;
+}
+.slick-arrow.slick-hidden {
+ display: none;
+}
diff --git a/front/odiparpack/app/styles/layout/_buttons.scss b/front/odiparpack/app/styles/layout/_buttons.scss
new file mode 100644
index 0000000..045ba0f
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_buttons.scss
@@ -0,0 +1,38 @@
+$_button-background-color: $action-color;
+$_button-background-color-hover: shade($action-color, 20%);
+
+#{$all-buttons} {
+ appearance: none;
+ background-color: $_button-background-color;
+ border: 0;
+ border-radius: $base-border-radius;
+ color: contrast-switch($_button-background-color);
+ cursor: pointer;
+ display: inline-block;
+ font-family: $base-font-family;
+ font-size: 16px;
+ -webkit-font-smoothing: antialiased;
+ font-weight: 600;
+ line-height: 1;
+ padding: $small-spacing $base-spacing;
+ text-align: center;
+ text-decoration: none;
+ transition: background-color $base-duration $base-timing;
+ user-select: none;
+ vertical-align: middle;
+ white-space: nowrap;
+
+ &:focus {
+ outline: none;
+ outline-offset: inherit;
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+
+ &:hover {
+ background-color: $_button-background-color;
+ }
+ }
+}
diff --git a/front/odiparpack/app/styles/layout/_forms.scss b/front/odiparpack/app/styles/layout/_forms.scss
new file mode 100644
index 0000000..7f943e4
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_forms.scss
@@ -0,0 +1,47 @@
+$_form-background-color: #fff;
+$_form-box-shadow: inset 0 1px 3px rgba(#000, 0.06);
+$_form-box-shadow-focus: $_form-box-shadow, 0 0 5px rgba($action-color, 0.7);
+
+fieldset {
+ background-color: transparent;
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+
+legend {
+ font-weight: 600;
+ margin-bottom: $small-spacing / 2;
+ padding: 0;
+}
+
+textarea {
+ resize: vertical;
+ font-family: $base-font-family;
+}
+
+[type="checkbox"],
+[type="radio"] {
+ display: inline;
+ margin-right: $small-spacing / 2;
+}
+
+[type="file"] {
+ margin-bottom: $small-spacing;
+ width: 100%;
+}
+
+select {
+ margin-bottom: $small-spacing;
+ width: 100%;
+}
+
+[type="checkbox"],
+[type="radio"],
+[type="file"],
+select {
+ &:focus {
+ outline: $focus-outline;
+ outline-offset: $focus-outline-offset;
+ }
+}
diff --git a/front/odiparpack/app/styles/layout/_layout.scss b/front/odiparpack/app/styles/layout/_layout.scss
new file mode 100644
index 0000000..4f4001e
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_layout.scss
@@ -0,0 +1,19 @@
+html {
+ background-color: $viewport-background-color;
+ box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: inherit;
+}
+
+html,
+body {
+ height: 100%;
+}
+
+body {
+ margin: 0;
+}
diff --git a/front/odiparpack/app/styles/layout/_lists.scss b/front/odiparpack/app/styles/layout/_lists.scss
new file mode 100644
index 0000000..06a7c0a
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_lists.scss
@@ -0,0 +1,19 @@
+ul,
+ol {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+dl {
+ margin: 0;
+}
+
+dt {
+ font-weight: 600;
+ margin: 0;
+}
+
+dd {
+ margin: 0;
+}
diff --git a/front/odiparpack/app/styles/layout/_media.scss b/front/odiparpack/app/styles/layout/_media.scss
new file mode 100644
index 0000000..dfa22ea
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_media.scss
@@ -0,0 +1,9 @@
+figure {
+ margin: 0;
+}
+
+img,
+picture {
+ margin: 0;
+ max-width: 100%;
+}
diff --git a/front/odiparpack/app/styles/layout/_tables.scss b/front/odiparpack/app/styles/layout/_tables.scss
new file mode 100644
index 0000000..8287bcf
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_tables.scss
@@ -0,0 +1,32 @@
+table {
+ border-collapse: collapse;
+ margin: $base-spacing 0;
+ text-align: left;
+ width: 100%;
+}
+
+thead {
+ line-height: $heading-line-height;
+ vertical-align: bottom;
+}
+
+tbody {
+ vertical-align: top;
+}
+
+tr {
+ border-bottom: $base-border;
+}
+
+th {
+ font-weight: 600;
+}
+
+th,
+td {
+ padding: $small-spacing $base-spacing;
+ @media screen and (max-width: 1400px) {
+ padding: $small-spacing;
+ padding-left: $base-spacing
+ }
+}
diff --git a/front/odiparpack/app/styles/layout/_typography.scss b/front/odiparpack/app/styles/layout/_typography.scss
new file mode 100644
index 0000000..49a10c6
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_typography.scss
@@ -0,0 +1,58 @@
+@import "../../styles/mixins";
+
+html {
+ color: $base-font-color;
+ font-family: $base-font-family;
+ font-size: 100%;
+ line-height: $base-line-height;
+}
+
+h1,
+h2,
+h3,
+h4,
+h6 {
+ font-family: $heading-font-family;
+ font-size: modular-scale(1);
+ line-height: $heading-line-height;
+ margin: 0 0 $small-spacing;
+}
+
+h5 {
+ font-family: $heading-font-family;
+ font-size: modular-scale(1);
+ line-height: $base-line-height;
+ font-weight: 600;
+ color: #202A75;
+ margin: 0 0 $small-spacing;
+}
+
+
+p {
+ margin: 0 0 $small-spacing;
+}
+
+a {
+ color: material-color('blue', '500');
+ ttext-decoration-skip-ink: auto;
+ transition: color $base-duration $base-timing;
+
+ &:focus {
+ outline: none;
+ outline-offset: none;
+ }
+}
+
+hr {
+ border-bottom: $base-border;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+ margin: $base-spacing 0;
+}
+
+
+[textalign="center"]{text-align: center !important}
+[textalign="left"]{text-align: left}
+[textalign="right"]{text-align: right}
+[textalign="justify"]{text-align: justify}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/layout/_variables.scss b/front/odiparpack/app/styles/layout/_variables.scss
new file mode 100644
index 0000000..cc20acf
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/_variables.scss
@@ -0,0 +1,41 @@
+// Typography
+$base-font-family: $font-stack-system;
+$heading-font-family: $base-font-family;
+
+// Line height
+$base-line-height: 1.5;
+$heading-line-height: 1.2;
+
+// Other Sizes
+$base-border-radius: 3px;
+$base-spacing: 1.5em;
+$big-spacing: $base-spacing * 2;
+$small-spacing: $base-spacing / 2;
+$base-z-index: 0;
+
+// Colors
+$white: #FFF;
+$grey-light: #F5F5F5;
+$grey: #E0E0E0;
+$grey-dark: #424242;
+
+// Font Colors
+$base-font-color: $grey-dark;
+$action-color: $grey;
+
+// Border
+$base-border-color: $grey;
+$base-border: 1px solid $base-border-color;
+
+// Background Colors
+$viewport-background-color: #fff;
+
+// Focus
+$focus-outline-color: transparentize($action-color, 0.4);
+$focus-outline-width: 3px;
+$focus-outline: $focus-outline-width solid $focus-outline-color;
+$focus-outline-offset: 2px;
+
+// Animations
+$base-duration: 150ms;
+$base-timing: ease;
diff --git a/front/odiparpack/app/styles/layout/base.scss b/front/odiparpack/app/styles/layout/base.scss
new file mode 100644
index 0000000..8daf825
--- /dev/null
+++ b/front/odiparpack/app/styles/layout/base.scss
@@ -0,0 +1,15 @@
+// Bitters 1.7.0
+// http://bitters.bourbon.io
+// Copyright 2013-2017 thoughtbot, inc.
+// MIT License
+
+@import "../variables";
+@import "variables";
+
+@import "buttons";
+@import "forms";
+@import "layout";
+@import "lists";
+@import "media";
+@import "tables";
+@import "typography";
diff --git a/front/odiparpack/app/styles/mixins.scss b/front/odiparpack/app/styles/mixins.scss
new file mode 100644
index 0000000..ac97b6b
--- /dev/null
+++ b/front/odiparpack/app/styles/mixins.scss
@@ -0,0 +1,3 @@
+@import "mixins/bourbon";
+@import "mixins/neat";
+@import "mixins/pallete";
diff --git a/front/odiparpack/app/styles/mixins/bourbon.scss b/front/odiparpack/app/styles/mixins/bourbon.scss
new file mode 100644
index 0000000..8d07bec
--- /dev/null
+++ b/front/odiparpack/app/styles/mixins/bourbon.scss
@@ -0,0 +1 @@
+@import "node_modules/bourbon/core/_bourbon.scss";
diff --git a/front/odiparpack/app/styles/mixins/neat.scss b/front/odiparpack/app/styles/mixins/neat.scss
new file mode 100644
index 0000000..af35e4a
--- /dev/null
+++ b/front/odiparpack/app/styles/mixins/neat.scss
@@ -0,0 +1 @@
+@import "node_modules/bourbon-neat/core/_neat.scss";
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/mixins/pallete.scss b/front/odiparpack/app/styles/mixins/pallete.scss
new file mode 100644
index 0000000..34f1fc9
--- /dev/null
+++ b/front/odiparpack/app/styles/mixins/pallete.scss
@@ -0,0 +1,8 @@
+// See the material colot pallete list here https://material-ui-next.com/style/color/
+@import 'node_modules/sass-material-colors/sass/sass-material-colors';
+
+// Colors
+$white: #FFF;
+$grey-light: #F5F5F5;
+$grey: #E0E0E0;
+$grey-dark: #424242;
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/variables.scss b/front/odiparpack/app/styles/variables.scss
new file mode 100644
index 0000000..1527f67
--- /dev/null
+++ b/front/odiparpack/app/styles/variables.scss
@@ -0,0 +1,3 @@
+@import "variables/bitters";
+@import "variables/neat";
+@import "variables/custom_pallete";
diff --git a/front/odiparpack/app/styles/variables/bitters.scss b/front/odiparpack/app/styles/variables/bitters.scss
new file mode 100644
index 0000000..4f8f996
--- /dev/null
+++ b/front/odiparpack/app/styles/variables/bitters.scss
@@ -0,0 +1,4 @@
+$font-stack-system: "Roboto", "Helvetica", "Arial", sans-serif;
+$heading-font-family: "Roboto", "Helvetica", "Arial", sans-serif;
+$all-buttons: 'button, input[type="button"], input[type="submit"]';
+$all-text-inputs: 'input[type="text"], input[type="password"], input[type="email"], input[type="tel"]';
diff --git a/front/odiparpack/app/styles/variables/custom_pallete.scss b/front/odiparpack/app/styles/variables/custom_pallete.scss
new file mode 100644
index 0000000..e5c0d0d
--- /dev/null
+++ b/front/odiparpack/app/styles/variables/custom_pallete.scss
@@ -0,0 +1,31 @@
+@function grey(){
+ @return material-color('blue-grey', '400');
+}
+
+@function greyLight(){
+ @return material-color('blue-grey', '200');
+}
+
+@function greyLigther(){
+ @return material-color('blue-grey', '100');
+}
+
+@function greyDark(){
+ @return material-color('blue-grey', '600');
+}
+
+@function greyDarker(){
+ @return material-color('blue-grey', '800');
+}
+
+@function black(){
+ @return material-color('blue-grey', '900');
+}
+
+@function white(){
+ @return "#FFFFFF";
+}
+
+@function primaryColor(){
+ @return material-color('indigo', '900');
+}
\ No newline at end of file
diff --git a/front/odiparpack/app/styles/variables/neat.scss b/front/odiparpack/app/styles/variables/neat.scss
new file mode 100644
index 0000000..e02bb9f
--- /dev/null
+++ b/front/odiparpack/app/styles/variables/neat.scss
@@ -0,0 +1 @@
+$border-box-sizing: false;
diff --git a/front/odiparpack/app/translations/en.json b/front/odiparpack/app/translations/en.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/front/odiparpack/app/translations/en.json
@@ -0,0 +1 @@
+[]
diff --git a/front/odiparpack/app/utils/checkStore.js b/front/odiparpack/app/utils/checkStore.js
new file mode 100644
index 0000000..610ea0f
--- /dev/null
+++ b/front/odiparpack/app/utils/checkStore.js
@@ -0,0 +1,21 @@
+import { conformsTo, isFunction, isObject } from 'lodash';
+import invariant from 'invariant';
+
+/**
+ * Validate the shape of redux store
+ */
+export default function checkStore(store) {
+ const shape = {
+ dispatch: isFunction,
+ subscribe: isFunction,
+ getState: isFunction,
+ replaceReducer: isFunction,
+ runSaga: isFunction,
+ injectedReducers: isObject,
+ injectedSagas: isObject,
+ };
+ invariant(
+ conformsTo(store, shape),
+ '(app/utils...) injectors: Expected a valid redux store',
+ );
+}
diff --git a/front/odiparpack/app/utils/constants.js b/front/odiparpack/app/utils/constants.js
new file mode 100644
index 0000000..97ece0f
--- /dev/null
+++ b/front/odiparpack/app/utils/constants.js
@@ -0,0 +1,3 @@
+export const RESTART_ON_REMOUNT = '@@saga-injector/restart-on-remount';
+export const DAEMON = '@@saga-injector/daemon';
+export const ONCE_TILL_UNMOUNT = '@@saga-injector/once-till-unmount';
diff --git a/front/odiparpack/app/utils/history.js b/front/odiparpack/app/utils/history.js
new file mode 100644
index 0000000..ee3abb7
--- /dev/null
+++ b/front/odiparpack/app/utils/history.js
@@ -0,0 +1,3 @@
+import { createBrowserHistory } from 'history';
+const history = createBrowserHistory();
+export default history;
diff --git a/front/odiparpack/app/utils/injectReducer.js b/front/odiparpack/app/utils/injectReducer.js
new file mode 100644
index 0000000..13833c2
--- /dev/null
+++ b/front/odiparpack/app/utils/injectReducer.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import hoistNonReactStatics from 'hoist-non-react-statics';
+import { ReactReduxContext } from 'react-redux';
+
+import getInjectors from './reducerInjectors';
+
+/**
+ * Dynamically injects a reducer
+ *
+ * @param {string} key A key of the reducer
+ * @param {function} reducer A reducer that will be injected
+ *
+ */
+export default ({ key, reducer }) => WrappedComponent => {
+ class ReducerInjector extends React.Component {
+ static WrappedComponent = WrappedComponent;
+
+ static contextType = ReactReduxContext;
+
+ static displayName = `withReducer(${WrappedComponent.displayName
+ || WrappedComponent.name
+ || 'Component'})`;
+
+ constructor(props, context) {
+ super(props, context);
+
+ getInjectors(context.store).injectReducer(key, reducer);
+ }
+
+ render() {
+ return ;
+ }
+ }
+
+ return hoistNonReactStatics(ReducerInjector, WrappedComponent);
+};
+
+const useInjectReducer = ({ key, reducer }) => {
+ const context = React.useContext(ReactReduxContext);
+ React.useEffect(() => {
+ getInjectors(context.store).injectReducer(key, reducer);
+ }, []);
+};
+
+export { useInjectReducer };
diff --git a/front/odiparpack/app/utils/injectSaga.js b/front/odiparpack/app/utils/injectSaga.js
new file mode 100644
index 0000000..3f8752b
--- /dev/null
+++ b/front/odiparpack/app/utils/injectSaga.js
@@ -0,0 +1,59 @@
+import React from 'react';
+import hoistNonReactStatics from 'hoist-non-react-statics';
+import { ReactReduxContext } from 'react-redux';
+
+import getInjectors from './sagaInjectors';
+
+/**
+ * Dynamically injects a saga, passes component's props as saga arguments
+ *
+ * @param {string} key A key of the saga
+ * @param {function} saga A root saga that will be injected
+ * @param {string} [mode] By default (constants.DAEMON) the saga will be started
+ * on component mount and never canceled or started again. Another two options:
+ * - constants.RESTART_ON_REMOUNT — the saga will be started on component mount and
+ * cancelled with `task.cancel()` on component unmount for improved performance,
+ * - constants.ONCE_TILL_UNMOUNT — behaves like 'RESTART_ON_REMOUNT' but never runs it again.
+ *
+ */
+export default ({ key, saga, mode }) => WrappedComponent => {
+ class InjectSaga extends React.Component {
+ static WrappedComponent = WrappedComponent;
+
+ static contextType = ReactReduxContext;
+
+ static displayName = `withSaga(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
+
+ constructor(props, context) {
+ super(props, context);
+
+ this.injectors = getInjectors(context.store);
+
+ this.injectors.injectSaga(key, { saga, mode }, this.props);
+ }
+
+ componentWillUnmount() {
+ this.injectors.ejectSaga(key);
+ }
+
+ render() {
+ return ;
+ }
+ }
+
+ return hoistNonReactStatics(InjectSaga, WrappedComponent);
+};
+
+const useInjectSaga = ({ key, saga, mode }) => {
+ const context = React.useContext(ReactReduxContext);
+ React.useEffect(() => {
+ const injectors = getInjectors(context.store);
+ injectors.injectSaga(key, { saga, mode });
+
+ return () => {
+ injectors.ejectSaga(key);
+ };
+ }, []);
+};
+
+export { useInjectSaga };
diff --git a/front/odiparpack/app/utils/reducerInjectors.js b/front/odiparpack/app/utils/reducerInjectors.js
new file mode 100644
index 0000000..d664680
--- /dev/null
+++ b/front/odiparpack/app/utils/reducerInjectors.js
@@ -0,0 +1,33 @@
+import invariant from 'invariant';
+import { isEmpty, isFunction, isString } from 'lodash';
+
+import checkStore from './checkStore';
+import createReducer from '../redux/reducers';
+
+export function injectReducerFactory(store, isValid) {
+ return function injectReducer(key, reducer) {
+ if (!isValid) checkStore(store);
+
+ invariant(
+ isString(key) && !isEmpty(key) && isFunction(reducer),
+ '(app/utils...) injectReducer: Expected `reducer` to be a reducer function',
+ );
+
+ // Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different
+ if (
+ Reflect.has(store.injectedReducers, key)
+ && store.injectedReducers[key] === reducer
+ ) return;
+
+ store.injectedReducers[key] = reducer; // eslint-disable-line no-param-reassign
+ store.replaceReducer(createReducer(store.injectedReducers));
+ };
+}
+
+export default function getInjectors(store) {
+ checkStore(store);
+
+ return {
+ injectReducer: injectReducerFactory(store, true),
+ };
+}
diff --git a/front/odiparpack/app/utils/sagaInjectors.js b/front/odiparpack/app/utils/sagaInjectors.js
new file mode 100644
index 0000000..edb4626
--- /dev/null
+++ b/front/odiparpack/app/utils/sagaInjectors.js
@@ -0,0 +1,92 @@
+import invariant from 'invariant';
+import {
+ isEmpty, isFunction, isString, conformsTo
+} from 'lodash';
+
+import checkStore from './checkStore';
+import { DAEMON, ONCE_TILL_UNMOUNT, RESTART_ON_REMOUNT } from './constants';
+
+const allowedModes = [RESTART_ON_REMOUNT, DAEMON, ONCE_TILL_UNMOUNT];
+
+const checkKey = key => invariant(
+ isString(key) && !isEmpty(key),
+ '(app/utils...) injectSaga: Expected `key` to be a non empty string',
+);
+
+const checkDescriptor = descriptor => {
+ const shape = {
+ saga: isFunction,
+ mode: mode => isString(mode) && allowedModes.includes(mode),
+ };
+ invariant(
+ conformsTo(descriptor, shape),
+ '(app/utils...) injectSaga: Expected a valid saga descriptor',
+ );
+};
+
+export function injectSagaFactory(store, isValid) {
+ return function injectSaga(key, descriptor = {}, args) {
+ if (!isValid) checkStore(store);
+
+ const newDescriptor = {
+ ...descriptor,
+ mode: descriptor.mode || DAEMON,
+ };
+ const { saga, mode } = newDescriptor;
+
+ checkKey(key);
+ checkDescriptor(newDescriptor);
+
+ let hasSaga = Reflect.has(store.injectedSagas, key);
+
+ if (process.env.NODE_ENV !== 'production') {
+ const oldDescriptor = store.injectedSagas[key];
+ // enable hot reloading of daemon and once-till-unmount sagas
+ if (hasSaga && oldDescriptor.saga !== saga) {
+ oldDescriptor.task.cancel();
+ hasSaga = false;
+ }
+ }
+
+ if (
+ !hasSaga
+ || (hasSaga && mode !== DAEMON && mode !== ONCE_TILL_UNMOUNT)
+ ) {
+ /* eslint-disable no-param-reassign */
+ store.injectedSagas[key] = {
+ ...newDescriptor,
+ task: store.runSaga(saga, args),
+ };
+ /* eslint-enable no-param-reassign */
+ }
+ };
+}
+
+export function ejectSagaFactory(store, isValid) {
+ return function ejectSaga(key) {
+ if (!isValid) checkStore(store);
+
+ checkKey(key);
+
+ if (Reflect.has(store.injectedSagas, key)) {
+ const descriptor = store.injectedSagas[key];
+ if (descriptor.mode && descriptor.mode !== DAEMON) {
+ descriptor.task.cancel();
+ // Clean up in production; in development we need `descriptor.saga` for hot reloading
+ if (process.env.NODE_ENV === 'production') {
+ // Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
+ store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
+ }
+ }
+ }
+ };
+}
+
+export default function getInjectors(store) {
+ checkStore(store);
+
+ return {
+ injectSaga: injectSagaFactory(store, true),
+ ejectSaga: ejectSagaFactory(store, true),
+ };
+}
diff --git a/front/odiparpack/app/utils/sagas.js b/front/odiparpack/app/utils/sagas.js
new file mode 100644
index 0000000..f5d3e78
--- /dev/null
+++ b/front/odiparpack/app/utils/sagas.js
@@ -0,0 +1,15 @@
+import { all } from 'redux-saga/effects';
+import taskSagas from 'enl-containers/SampleFullstackApps//Todo/reducers/todoSagas';
+import contactSagas from 'enl-containers/SampleFullstackApps/Contact/reducers/contactSagas';
+import emailSagas from 'enl-containers/SampleFullstackApps/Email/reducers/emailSagas';
+import authSagas from 'enl-redux/modules/authSagas';
+
+
+export default function* sagas() {
+ yield all([
+ ...authSagas,
+ ...contactSagas,
+ ...taskSagas,
+ ...emailSagas
+ ]);
+}
diff --git a/front/odiparpack/app/utils/tests/.DS_Store b/front/odiparpack/app/utils/tests/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/front/odiparpack/app/utils/tests/.DS_Store differ
--
cgit v1.2.3