diff --git a/client/src/actions/modal-actions.js b/client/src/actions/modal-actions.js
new file mode 100644
index 00000000..06f6c939
--- /dev/null
+++ b/client/src/actions/modal-actions.js
@@ -0,0 +1,16 @@
+
+export default {
+ openModal(content) {
+ return {
+ type: 'OPEN_MODAL',
+ payload: content
+ }
+ },
+
+ closeModal() {
+ return {
+ type: 'CLOSE_MODAL',
+ payload: {}
+ };
+ }
+};
\ No newline at end of file
diff --git a/client/src/app-components/are-you-sure.js b/client/src/app-components/are-you-sure.js
new file mode 100644
index 00000000..df76ee79
--- /dev/null
+++ b/client/src/app-components/are-you-sure.js
@@ -0,0 +1,60 @@
+import React from 'react';
+
+import i18n from 'lib-app/i18n';
+import Button from 'core-components/button';
+
+class AreYouSure extends React.Component {
+ static propTypes = {
+ description: React.PropTypes.string,
+ onYes: React.PropTypes.func
+ };
+
+ static contextTypes = {
+ closeModal: React.PropTypes.func
+ };
+
+ render() {
+ return (
+
+
+ {i18n('ARE_YOU_SURE')}
+
+
+ {this.props.description}
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ onYes() {
+ this.closeModal();
+
+ if (this.props.onYes) {
+ this.props.onYes();
+ }
+ }
+
+ onNo() {
+ this.closeModal();
+ }
+
+ closeModal() {
+ if (this.context.closeModal) {
+ this.context.closeModal();
+ }
+ }
+}
+
+export default AreYouSure;
\ No newline at end of file
diff --git a/client/src/app-components/are-you-sure.scss b/client/src/app-components/are-you-sure.scss
new file mode 100644
index 00000000..921ed1c3
--- /dev/null
+++ b/client/src/app-components/are-you-sure.scss
@@ -0,0 +1,30 @@
+@import "../scss/vars";
+
+.are-you-sure {
+ width: 400px;
+ text-align: center;
+
+ &__header {
+ color: $primary-red;
+ font-size: $font-size--xl;
+ font-weight: bold;
+ margin-bottom: 20px;
+
+ }
+
+ &__description {
+ color: $dark-grey;
+ font-size: $font-size--md;
+ margin-bottom: 50px;
+ }
+
+ &__butttons {
+ margin: 0 auto;
+ }
+
+ &__yes-button,
+ &__no-button {
+ display: inline-block;
+ margin-right: 10px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/app/App.js b/client/src/app/App.js
index d6639e06..e35a0be7 100644
--- a/client/src/app/App.js
+++ b/client/src/app/App.js
@@ -3,6 +3,8 @@ import _ from 'lodash';
import { connect } from 'react-redux'
import { browserHistory } from 'react-router';
+import ModalContainer from 'app/modal-container';
+
class App extends React.Component {
static contextTypes = {
router: React.PropTypes.object,
@@ -21,6 +23,7 @@ class App extends React.Component {
return (
{React.cloneElement(this.props.children, {})}
+
);
}
@@ -49,6 +52,7 @@ class App extends React.Component {
export default connect((store) => {
return {
config: store.config,
+ modal: store.modal,
session: store.session,
routing: store.routing
};
diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js
index 2d64b834..874edabb 100644
--- a/client/src/app/demo/components-demo-page.js
+++ b/client/src/app/demo/components-demo-page.js
@@ -3,6 +3,11 @@
const React = require('react');
const DocumentTitle = require('react-document-title');
+const ModalActions = require('actions/modal-actions');
+const store = require('app/store');
+
+const AreYouSure = require('app-components/are-you-sure');
+
const Button = require('core-components/button');
const Input = require('core-components/input');
const Checkbox = require('core-components/checkbox');
@@ -82,7 +87,23 @@ let DemoPage = React.createClass({
{
title: 'Tooltip',
render: (
- hola
+
+ hola
+
+ )
+ },
+ {
+ title: 'ModalTrigger',
+ render: (
+
)
}
],
diff --git a/client/src/app/modal-container.js b/client/src/app/modal-container.js
new file mode 100644
index 00000000..5f6ca33c
--- /dev/null
+++ b/client/src/app/modal-container.js
@@ -0,0 +1,57 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import keyCode from 'keycode';
+
+import ModalActions from 'actions/modal-actions';
+import Modal from 'core-components/modal';
+
+class ModalContainer extends React.Component {
+
+ static childContextTypes = {
+ closeModal: React.PropTypes.func
+ };
+
+ getChildContext() {
+ return {
+ closeModal: this.closeModal.bind(this)
+ };
+ };
+
+ componentDidMount() {
+ window.addEventListener('keydown', this.onKeyDown.bind(this));
+ }
+
+ componentWillUnMount() {
+ window.removeEventListener('keydown', this.onKeyDown.bind(this));
+ }
+
+ render() {
+ return (
+
+ {(this.props.modal.opened) ? this.renderModal() : null}
+
+ );
+ }
+
+ renderModal() {
+ return (
+
+ );
+ }
+
+ onKeyDown(event) {
+ if (event.keyCode === keyCode('ESCAPE')) {
+ this.closeModal();
+ }
+ }
+
+ closeModal() {
+ this.props.dispatch(ModalActions.closeModal());
+ }
+}
+
+export default connect((store) => {
+ return {
+ modal: store.modal
+ };
+})(ModalContainer);
\ No newline at end of file
diff --git a/client/src/core-components/button.js b/client/src/core-components/button.js
index 8ad69522..13dc4298 100644
--- a/client/src/core-components/button.js
+++ b/client/src/core-components/button.js
@@ -17,9 +17,16 @@ class Button extends React.Component {
static propTypes = {
children: React.PropTypes.node,
+ size: React.PropTypes.oneOf([
+ 'small',
+ 'medium',
+ 'large',
+ 'auto'
+ ]),
type: React.PropTypes.oneOf([
'primary',
- 'primary-icon',
+ 'secondary',
+ 'tertiary',
'clean',
'link'
]),
@@ -32,7 +39,8 @@ class Button extends React.Component {
};
static defaultProps = {
- type: 'primary'
+ type: 'primary',
+ size: 'medium'
};
render() {
@@ -59,10 +67,20 @@ class Button extends React.Component {
getClass() {
let classes = {
'button': true,
- 'button_disabled': this.props.disabled
+ 'button_disabled': this.props.disabled,
+
+ 'button_primary': (this.props.type === 'primary'),
+ 'button_secondary': (this.props.type === 'secondary'),
+ 'button_tertiary': (this.props.type === 'tertiary'),
+ 'button_clean': (this.props.type === 'clean'),
+ 'button_link': (this.props.type === 'link'),
+
+ 'button_small': (this.props.size === 'small'),
+ 'button_medium': (this.props.size === 'medium'),
+ 'button_large': (this.props.size === 'large'),
+ 'button_auto': (this.props.size === 'auto')
};
- classes['button-' + this.props.type] = (this.props.type);
classes[this.props.className] = (this.props.className);
return classNames(classes);
diff --git a/client/src/core-components/button.scss b/client/src/core-components/button.scss
index 34c58bea..a446402e 100644
--- a/client/src/core-components/button.scss
+++ b/client/src/core-components/button.scss
@@ -2,28 +2,31 @@
.button {
- &-primary,
- &-primary-icon {
+ &_primary,
+ &_secondary,
+ &_tertiary {
background-color: $primary-red;
border: solid transparent;
border-radius: 4px;
color: white;
height: 47px;
text-transform: uppercase;
- width: 239px;
}
- &-primary-icon {
- width: initial;
- height: initial;
+ &_secondary {
+ background-color: $primary-green;
}
- &-clean {
+ &_tertiary {
+ background-color: $secondary-blue;
+ }
+
+ &_clean {
background: none;
border: none;
}
- &-link {
+ &_link {
background: none;
border: none;
color: $dark-grey;
@@ -37,4 +40,22 @@
&_disabled {
background-color: #ec9696;
}
+
+ &_small {
+ width: 100px;
+ height: 47px;
+ }
+
+ &_medium {
+ width: 239px;
+ }
+
+ &_large {
+ //width: 239px;
+ }
+
+ &_auto {
+ width: initial;
+ height: initial;
+ }
}
\ No newline at end of file
diff --git a/client/src/core-components/checkbox.js b/client/src/core-components/checkbox.js
index 28a48ffa..4c4bfe32 100644
--- a/client/src/core-components/checkbox.js
+++ b/client/src/core-components/checkbox.js
@@ -1,7 +1,7 @@
import React from 'react';
import classNames from 'classnames';
import _ from 'lodash';
-import keyCode from 'keycode';
+import keyCode from 'keycode';
import callback from 'lib-core/callback';
import getIcon from 'lib-core/get-icon';
diff --git a/client/src/core-components/input.scss b/client/src/core-components/input.scss
index d3b88eee..2bcb1f54 100644
--- a/client/src/core-components/input.scss
+++ b/client/src/core-components/input.scss
@@ -44,7 +44,7 @@
}
.input__text {
- padding-left: 40px;
+ padding-left: 48px;
}
}
diff --git a/client/src/core-components/modal.js b/client/src/core-components/modal.js
new file mode 100644
index 00000000..612893f5
--- /dev/null
+++ b/client/src/core-components/modal.js
@@ -0,0 +1,19 @@
+import React from 'react';
+
+class Modal extends React.Component {
+ static propTypes = {
+ content: React.PropTypes.node
+ };
+
+ render() {
+ return (
+
+
+ {this.props.content}
+
+
+ );
+ }
+}
+
+export default Modal;
\ No newline at end of file
diff --git a/client/src/core-components/modal.scss b/client/src/core-components/modal.scss
new file mode 100644
index 00000000..123bda25
--- /dev/null
+++ b/client/src/core-components/modal.scss
@@ -0,0 +1,18 @@
+.modal {
+ position: absolute;
+ top: 0;
+ left: 0;
+ background-color: rgba(0, 0, 0, 0.8);
+ width: 100%;
+ height: 100%;
+ display: flex;
+
+ &__content {
+ position: relative;
+ margin: auto;
+ background-color: white;
+ border-radius: 4px;
+ padding: 50px;
+ box-shadow: 0 0 11px white;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/text-editor.js b/client/src/core-components/text-editor.js
index d546d8a0..9c203463 100644
--- a/client/src/core-components/text-editor.js
+++ b/client/src/core-components/text-editor.js
@@ -51,9 +51,9 @@ class TextEditor extends React.Component {
return (
-
)
}
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 6efc2e4b..c4da923d 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -32,6 +32,8 @@ export default {
'NO_ATTACHMENT': 'No file attachment',
'STAFF': 'Staff',
'CUSTOMER': 'Customer',
+ 'YES': 'Yes',
+ 'CANCEL': 'Cancel',
//ERRORS
'EMAIL_NOT_EXIST': 'Email does not exist',
@@ -49,5 +51,6 @@ export default {
'SIGNUP_SUCCESS': 'You have registered successfully in our support system.',
'TICKET_SENT': 'Ticket has been created successfully.',
'VALID_RECOVER': 'Password recovered successfully',
- 'EMAIL_EXISTS': 'Email already exists, please try to log in or recover password'
+ 'EMAIL_EXISTS': 'Email already exists, please try to log in or recover password',
+ 'ARE_YOU_SURE': 'Are you sure?'
};
\ No newline at end of file
diff --git a/client/src/main.scss b/client/src/main.scss
index b7bd9324..9bc26c11 100644
--- a/client/src/main.scss
+++ b/client/src/main.scss
@@ -5,4 +5,5 @@
@import 'scss/font_awesome/font-awesome';
@import 'core-components/*';
+@import 'app-components/*';
@import 'app/*';
diff --git a/client/src/reducers/_reducers.js b/client/src/reducers/_reducers.js
index b5745f14..b63ba602 100644
--- a/client/src/reducers/_reducers.js
+++ b/client/src/reducers/_reducers.js
@@ -3,9 +3,11 @@ import { routerReducer } from 'react-router-redux';
import sessionReducer from 'reducers/session-reducer';
import configReducer from 'reducers/config-reducer';
+import modalReducer from 'reducers/modal-reducer';
export default combineReducers({
session: sessionReducer,
config: configReducer,
+ modal: modalReducer,
routing: routerReducer
});
\ No newline at end of file
diff --git a/client/src/reducers/modal-reducer.js b/client/src/reducers/modal-reducer.js
new file mode 100644
index 00000000..d49459e6
--- /dev/null
+++ b/client/src/reducers/modal-reducer.js
@@ -0,0 +1,36 @@
+import _ from 'lodash';
+
+import Reducer from 'reducers/reducer';
+
+class ModalReducer extends Reducer {
+
+ getInitialState() {
+ return {
+ opened: false,
+ content: null
+ };
+ }
+
+ getTypeHandlers() {
+ return {
+ 'OPEN_MODAL': this.onOpenModal,
+ 'CLOSE_MODAL': this.onCloseModal
+ };
+ }
+
+ onOpenModal(state, payload) {
+ return _.extend({}, state, {
+ opened: true,
+ content: payload
+ });
+ }
+
+ onCloseModal(state) {
+ return _.extend({}, state, {
+ opened: false,
+ content: null
+ });
+ }
+}
+
+export default ModalReducer.getInstance();
\ No newline at end of file