Commit 91a2ec23 authored by Patricio Bruna's avatar Patricio Bruna

Merge pull request #42 from ZBoxApp/distribution_lists

apply store in distribution list and mailbox, and add, edit, remove, distribution list, add pagination mailbox
parents 33df3db4 f190b8af
This diff is collapsed.
import $ from 'jquery';
import React from 'react';
import Button from '../button.jsx';
import MessageBar from '../message_bar.jsx';
import Panel from '../panel.jsx';
import * as Client from '../../utils/client.jsx';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
import * as Utils from '../../utils/utils.jsx';
import EventStore from '../../stores/event_store.jsx';
import Promise from 'bluebird';
import Constants from '../../utils/constants.jsx';
const messageType = Constants.MessageType;
export default class EditDistributionList extends React.Component {
constructor(props) {
super(props);
this.showMessage = this.showMessage.bind(this);
this.saveChanges = this.saveChanges.bind(this);
this.state = {};
}
showMessage(attrs) {
this.setState({
error: attrs.error,
type: attrs.typeError
});
}
saveChanges(e) {
e.preventDefault();
Utils.toggleStatusButtons('.action-edit-dl', true);
Utils.validateInputRequired(this.refs).then(() => {
const id = this.props.params.id;
const attrs = {};
const mail = this.refs.mail.value;
attrs.displayName = this.refs.displayName.value;
Client.modifyDistributionList(id, attrs, (dl) => {
const domain = dl.name.split('@').pop();
const newNameDL = `${mail}@${domain}`;
dl.rename(newNameDL, (err) => {
Utils.toggleStatusButtons('.action-edit-dl', false);
if (err) {
return GlobalActions.emitMessage({
error: err.extra.reason,
typeError: messageType.ERROR
});
}
return GlobalActions.emitMessage({
error: 'Se han actualizado sus datos éxitosamente.',
typeError: messageType.SUCCESS
});
});
}, (err) => {
GlobalActions.emitMessage({
error: err.message,
typeError: messageType.ERROR
});
Utils.toggleStatusButtons('.action-edit-dl', false);
});
}).catch((error) => {
GlobalActions.emitMessage({
error: error.message,
type: messageType.ERROR
});
error.node.focus();
Utils.toggleStatusButtons('.action-edit-dl', false);
});
}
getDistributionList() {
const id = this.props.params.id;
new Promise((resolve, reject) => {
Client.getDistributionList(id, (success) => {
resolve(success);
}, (error) => {
reject(error);
});
}).then((res) => {
const domain = this.refs.domain;
const displayName = this.refs.displayName;
const mail = this.refs.mail;
const dl = res.name.split('@');
domain.innerHTML = dl.pop();
if (res.attrs.displayName) {
displayName.value = res.attrs.displayName;
}
mail.value = dl.shift();
}).catch((err) => {
GlobalActions.emitMessage({
error: err.message,
type: messageType.ERROR
});
Utils.toggleStatusButtons('.action-edit-dl', true);
}).finally(() => {
GlobalActions.emitEndLoading();
});
}
componentDidMount() {
EventStore.addMessageListener(this.showMessage);
GlobalActions.emitEndLoading();
$('#sidebar-domain').removeClass('active');
this.getDistributionList();
}
componentWillUnmount() {
EventStore.removeMessageListener(this.showMessage);
$('#sidebar-domain').removeClass('active');
}
render() {
let message;
let form;
let actions;
if (this.state.error) {
message = (
<MessageBar
message={this.state.error}
type={this.state.type}
autoclose={true}
/>
);
}
form = (
<form
className='simple_form form-horizontal mailbox-form'
id='editAccount'
>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Dirección'}
</label>
<div className='col-sm-8'>
<div className='input-group'>
<input
type='text'
className='form-control'
ref='mail'
data-required='true'
data-message='La dirección de correo es requerida, por favor verifique.'
placeholder='Dirección'
/>
<span
className='input-group-addon'
ref='domain'
>
</span>
</div>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Nombre'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
ref='displayName'
placeholder='Nombre mostrado en contactos'
/>
</div>
</div>
<div className='form-group'>
<div className='col-sm-3'></div>
<div className='col-sm-8'>
<Button
btnAttrs={
{
className: 'btn btn-info action-edit-dl',
onClick: (e) => {
this.saveChanges(e);
}
}
}
>
{'Guardar'}
</Button>
<Button
btnAttrs={
{
className: 'btn btn-default action-button',
onClick: (e) => {
Utils.handleLink(e, `/domains/${this.props.params.domain_id}/distribution_lists/${this.props.params.id}`);
}
}
}
>
{'Cancelar'}
</Button>
</div>
</div>
</form>
);
actions = [
{
label: 'Guardar',
props: {
className: 'btn btn-info btn-xs action-edit-dl',
onClick: (e) => {
this.saveChanges(e);
}
}
},
{
label: 'Cancelar',
props: {
className: 'btn btn-default btn-xs action-button',
onClick: (e) => {
Utils.handleLink(e, `/domains/${this.props.params.domain_id}/distribution_lists/${this.props.params.id}`);
}
}
}
];
return (
<div>
<div className='content animate-panel'>
{message}
<div className='row'>
<div className='col-md-12 central-content'>
<Panel
title={'Editar Lista de Distribución'}
btnsHeader={actions}
classHeader={'forum-box'}
>
{form}
</Panel>
</div>
</div>
</div>
</div>
);
}
}
EditDistributionList.propTypes = {
location: React.PropTypes.object,
params: React.PropTypes.any
};
......@@ -23,6 +23,7 @@ export default class DomainDistributionList extends React.Component {
}
getStateFromStores() {
const lists = DomainStore.getDistributionLists(this.props.domain);
return {
lists
};
......@@ -107,7 +108,7 @@ export default class DomainDistributionList extends React.Component {
<td className='distribution-list-actions'>
<a
href='#'
onClick={(e) => Utils.handleLink(e, `/distribution_lists/${dl.id}`)}
onClick={(e) => Utils.handleLink(e, `/domains/${domain.id}/distribution_lists/${dl.id}`)}
>
{'Ver'}
</a>
......
......@@ -36,7 +36,10 @@ export default class ConfirmDeleteModal extends React.Component {
message: 'Su contraseña se ha sido cambiada éxitosamente.',
typeError: 'text-success'
});
this.forceLogout('/logout');
if (this.props.data.name === this.state.currentUser.name) {
this.forceLogout('/logout');
}
}, (error) => {
this.setState({
alert: true,
......
......@@ -5,6 +5,9 @@ import {browserHistory} from 'react-router';
import {Modal} from 'react-bootstrap';
import * as Utils from './../../utils/utils.jsx';
import * as Client from './../../utils/client.jsx';
import Promise from 'bluebird';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
import MailboxStore from '../../stores/mailbox_store.jsx';
import React from 'react';
......@@ -30,31 +33,45 @@ export default class ConfirmDeleteModal extends React.Component {
}
handleDelete() {
Client.removeAccount(
this.props.data.id,
() => {
this.setState(
{
alert: true,
message: `Su cuenta ${this.props.data.attrs.mail}, ha sido eliminada éxitosamente. Sera redirigido en ${this.state.timeToRedirect} seg`,
typeError: 'text-success'
}
);
this.redirect();
},
() => {
this.setState(
{
alert: true,
message: `Hubo un error, al intentar eliminar su cuenta : ${this.props.data.attrs.mail}`,
typeError: 'text-danger'
}
);
}
);
new Promise((resolve, reject) => {
// start loading
GlobalActions.emitStartLoading();
Client.removeAccount(
this.props.data.id,
() => {
return resolve(true);
},
(error) => {
return reject(error);
}
);
}).then(() => {
MailboxStore.removeAccount(this.props.data);
this.setState(
{
alert: true,
message: `Su cuenta ${this.props.data.attrs.mail}, ha sido eliminada éxitosamente. Sera redirigido en ${this.state.timeToRedirect} seg`,
typeError: 'text-warning'
}
);
Utils.toggleStatusButtons('.close-modal', true);
this.redirect();
}).catch((error) => {
this.setState(
{
alert: true,
message: error.message,
typeError: 'text-edanger'
}
);
}).finally(() => {
GlobalActions.emitEndLoading();
});
}
redirect() {
const redirectAt = 1000;
setTimeout(() => {
if (this.timetoRedict-- < 1) {
browserHistory.replace('/mailboxes');
......@@ -65,7 +82,7 @@ export default class ConfirmDeleteModal extends React.Component {
this.redirect();
}
}, 1000);
}, redirectAt);
}
handleKeyUp() {
......@@ -120,7 +137,7 @@ export default class ConfirmDeleteModal extends React.Component {
<Modal.Footer>
<button
type='button'
className='btn btn-default'
className='btn btn-default close-modal'
onClick={this.props.onHide}
>
{'Cancelar'}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -30,12 +30,12 @@ export default class FormVacacionesMailbox extends React.Component {
Client.modifyAccount(data.id, attrs, () => {
GlobalActions.emitMessage({
message: 'Se ha modificado con éxito',
error: 'Se ha modificado su respuesta de vacaciones con éxito.',
type: messageType.SUCCESS
});
}, (error) => {
GlobalActions.emitMessage({
message: error.message,
error: error.message,
type: messageType.ERROR
});
});
......
import React from 'react';
import Button from '../button.jsx';
import StatusLabel from '../status_label.jsx';
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
import ZimbraStore from '../../stores/zimbra_store.jsx';
export default class BlockGeneralInfoMailbox extends React.Component {
constructor(props) {
......@@ -16,24 +19,22 @@ export default class BlockGeneralInfoMailbox extends React.Component {
this.state = {};
}
componentWillMount() {
this.domain = this.props.data.name.split('@');
this.domain = this.domain[this.domain.length - 1];
}
componentDidMount() {
this.getDomain();
}
getDomain() {
Client.getDomain(this.domain, (data) => {
const domain = Utils.getDomainFromString(this.data.name);
Client.getDomain(domain, (data) => {
this.setState({
hasDomain: true,
domainData: data
});
}, (error) => {
this.setState({
error: error.message
GlobalActions.emitMessage({
error: error.message,
typeError: error.type
});
});
}
......@@ -44,25 +45,64 @@ export default class BlockGeneralInfoMailbox extends React.Component {
render() {
let blockInfo = null;
let statusCos = null;
const cosID = Utils.getEnabledPlansObjectByCos(ZimbraStore.getAllCos(), this.props.data.attrs.zimbraCOSId);
let cosName = null;
switch (cosID.name) {
case 'premium':
cosName = Utils.titleCase(cosID.name);
statusCos = 'label btn-primary2 btn-xs';
break;
case 'professional':
cosName = Utils.titleCase(cosID.name);
statusCos = 'label btn-primary btn-xs';
break;
case 'basic':
cosName = Utils.titleCase(cosID.name);
statusCos = 'label btn-success btn-xs';
break;
default:
cosName = 'Sin Plan';
statusCos = 'label noplan btn-xs';
break;
}
if (this.state.hasDomain) {
const data = this.props.data;
const attrs = this.props.data.attrs;
const owner = (!attrs.givenName || !attrs.sn) ? null : attrs.givenName + ' ' + attrs.sn;
const mail = data.name;
//properties
const description = attrs.description;
const mailhost = attrs.zimbraMailHost;
const archive = attrs.zimbraArchiveAccount;
blockInfo = (
<article>
<article className='account-info'>
<div>
<h4>
<span className='mailbox-name text-success'>{this.data.name}</span>
<span className='mailbox-name text-success'>{mail}</span>
</h4>
{owner && (
<h5>
{owner}
</h5>
)}
</div>
<div>
<p>
{this.data.attrs.description}
</p>
</div>
{description && (
<div>
<p>
{description}
</p>
</div>
)}
<div>
<p>
<strong>{'Dominio'}: </strong>
<strong>{'Dominio: '}</strong>
<Button
btnAttrs={{
onClick: (e) => {
......@@ -70,10 +110,36 @@ export default class BlockGeneralInfoMailbox extends React.Component {
}
}}
>
{this.domain}
{this.state.domainData.name}
</Button>
</p>
</div>
{archive && (
<div>
<p>
<strong>{'Archive: '}</strong>
{archive}
</p>
</div>
)}
{mailhost && (
<div>
<p>
<strong>{'Mail Host'}: </strong>
{mailhost}
</p>
</div>
)}
<div>
<p>
<StatusLabel classes={statusCos}>
{cosName}
</StatusLabel>
</p>
</div>
</article>
);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -7,7 +7,23 @@ export default class BlockGeneralInfoMailbox extends React.Component {
this.date = null;
this.status = null;
this.className = null;
this.lastConection = 'no se ha conectado';
this.lastConection = 'No se ha conectado';
this.getMailSize = this.getMailSize.bind(this);
this.state = {};
}
getMailSize() {
this.props.data.getMailboxSize((err, bytes) => {
let currentSize = '0 MB';
if (bytes) {
currentSize = Utils.bytesToMegas(bytes);
}
this.setState({
size: currentSize
});
});
}
componentWillMount() {
......@@ -16,24 +32,32 @@ export default class BlockGeneralInfoMailbox extends React.Component {
switch (this.props.data.attrs.zimbraAccountStatus) {
case 'inactive':
this.status = 'Desactivada';
this.className = 'btn btn-md btn-default';
this.className = 'btn-default mailbox-status';
break;
case 'locked':
this.status = 'Bloqueada';
this.className = 'btn btn-md btn-primary2';
this.className = 'btn-primary2 mailbox-status';
break;
default:
this.status = 'Activa';
this.className = 'btn btn-md btn-info';
this.className = 'btn-info mailbox-status';
break;
}
if (this.props.data.attrs.zimbraLastLogonTimestamp) {
this.lastConection = Utils.dateFormatted(this.props.data.attrs.zimbraLastLogonTimestamp);
}
this.getMailSize();
}
render() {
let size = null;
if (this.state.size) {
size = this.state.size;
}
return (
<div>
<div className='row'>
......@@ -59,7 +83,7 @@ export default class BlockGeneralInfoMailbox extends React.Component {
<div>
<p>
<span className='center-block'>Espacio Usado</span>
<strong>0 Bytes</strong>
<strong>{size}</strong>
</p>
</div>
</div>
......
......@@ -112,7 +112,7 @@ MessageBar.defaultProps = {
MessageBar.propTypes = {
message: React.PropTypes.string.isRequired,
type: React.PropTypes.oneOf(['SUCCESS', 'ERROR', 'WARNING', 'INFO']),
type: React.PropTypes.oneOf(['SUCCESS', 'ERROR', 'WARNING', 'INFO', 'LOCKED']),
position: React.PropTypes.oneOf(['absolute', 'fixed', 'relative', 'static', 'inherit']),
canClose: React.PropTypes.bool,
autoclose: React.PropTypes.bool,
......
......@@ -123,7 +123,7 @@ export default class Pagination extends React.Component {
return (
<div id='pagination'>
<ul className='pagination'>
<ul className='pagination pagination-sm'>
{first}
{prev}
{pages}
......
This diff is collapsed.
This diff is collapsed.
{
"debug": true,
"debug": false,
"zimbraUrl": "http://zimbra.zboxapp.dev:8000/service/admin/soap",
"zimbraProxy": "https://zimbra.zboxapp.dev:7071",
"dnsApiUrl": "http://zimbra.zboxapp.dev:3000",
......
This diff is collapsed.
......@@ -18,4 +18,9 @@
background: $bg-warning-color;
color: $white;
}
.flash-locked {
background: $color-violet;
color: $white;
}
}
......@@ -9,6 +9,7 @@
@import 'lists';
@import 'loader';
@import 'modal';
@import 'panel_add';
@import 'panels';
@import 'progress_bar';
@import 'tabs';
......
.new-fields {
border-top: 1px solid $color-new-fields;
margin-top: 30px;
h5 {
margin: 5px 0;
}
.new-fields-list {
.listed-field {
margin: 8px 0 0 10px;
input {
margin-right: 5px;
}
}
}
}
.actions-buttons {
margin-top: 20px;
a {
margin-left: 5px;
&:first-child {
margin-left: 0;
}
}
}
.as-table {
display: table;
.as-cell {
display: table-cell;
padding-right: 10px;
vertical-align: middle;
}
}
.margin-left {
margin-left: 5px;
}
This diff is collapsed.
......@@ -54,3 +54,8 @@
}
}
}
.domain-name {
font-size: 22px;
font-weight: 600;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment