Commit 2384b73a authored by Juorder Gonzalez's avatar Juorder Gonzalez Committed by Juorder Antonio

add resend account of mailbox from admin domain and make visible delete...

add resend account of mailbox from admin domain and make visible delete massive for global admin only

add notification for domain migrating mailboxes
parents 0d526cdb 8b6f65ae
module.exports = {"main":{"js":"/142926bundle.js"}}
\ No newline at end of file
module.exports = {"main":{"js":"/222915bundle.js"}}
\ No newline at end of file
......@@ -42,6 +42,7 @@ export default class DomainMailboxPlans extends React.Component {
);
}
render() {
const countAccounts = this.state.plans;
if (!this.state.plans) {
return <div/>;
}
......@@ -72,127 +73,142 @@ export default class DomainMailboxPlans extends React.Component {
const mailboxPlans = [];
let panelBody = null;
const cos = Utils.getEnabledPlansByCosId(ZimbraStore.getAllCos());
const planKeys = Object.keys(cos).map((c) => {
return cos[c];
});
const domain = this.props.domain;
const domainCos = domain.maxAccountsByCos();
const domainPlans = Utils.getPlansFromDomain(domain);
const plans = {};
let noLimitError;
let totalUsed = 0;
let totalLimit = 0;
planKeys.forEach((key) => {
plans[key] = {
limit: 0,
used: 0
};
});
let used = 0;
if (domainCos) {
Object.keys(domainCos).forEach((id) => {
const limit = domainCos[id];
used = domainPlans[cos[id]].used;
plans[cos[id]].limit += limit;
plans[cos[id]].used += used;
const isNotMigrating = !countAccounts.migracion;
if (isNotMigrating) {
const cos = Utils.getEnabledPlansByCosId(ZimbraStore.getAllCos());
const planKeys = Object.keys(cos).map((c) => {
return cos[c];
});
}
for (const key in plans) {
if (plans.hasOwnProperty(key) && plans[key].limit !== 0) {
const plan = plans[key];
totalUsed += (parseInt(plan.used, 10)) ? parseInt(plan.used, 10) : 0;
if (plan.limit === 0) {
//totalLimit = '\u221e';
if (!noLimitError) {
noLimitError = (
<MessageBar
message='Existen dominios sin límites asignados'
type='WARNING'
autoclose={true}
/>
);
const domain = this.props.domain;
const domainCos = domain.maxAccountsByCos();
const domainPlans = Utils.getPlansFromDomain(domain);
const plans = {};
let totalUsed = 0;
let totalLimit = 0;
planKeys.forEach((key) => {
plans[key] = {
limit: 0,
used: 0
};
});
let used = 0;
if (domainCos) {
Object.keys(domainCos).forEach((id) => {
const limit = domainCos[id];
used = domainPlans[cos[id]].used;
plans[cos[id]].limit += limit;
plans[cos[id]].used += used;
});
}
for (const key in plans) {
if (plans.hasOwnProperty(key) && plans[key].limit !== 0) {
const plan = plans[key];
totalUsed += (parseInt(plan.used, 10)) ? parseInt(plan.used, 10) : 0;
if (plan.limit === 0) {
//totalLimit = '\u221e';
if (!noLimitError) {
noLimitError = (
<MessageBar
message='Existen dominios sin límites asignados'
type='WARNING'
autoclose={true}
/>
);
}
} else {
totalLimit += plan.limit;
}
} else {
totalLimit += plan.limit;
mailboxPlans.push(
<tr key={`plan-${key}`}>
<td className='mbx-plan'
style={{borderTop: 0}}
>
{key}
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
{plan.limit || '\u221e'}
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
{plan.used}
</td>
</tr>
);
}
}
if (mailboxPlans.length > 0) {
mailboxPlans.push(
<tr key={`plan-${key}`}>
<tr key='totalizacion-planes'>
<td className='mbx-plan'
style={{borderTop: 0}}
>
{key}
<strong>{'Total'}</strong>
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
{plan.limit || '\u221e'}
<strong>{totalLimit}</strong>
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
{plan.used}
<strong>{totalUsed}</strong>
</td>
</tr>
);
}
}
if (mailboxPlans.length > 0) {
mailboxPlans.push(
<tr key='totalizacion-planes'>
<td className='mbx-plan'
style={{borderTop: 0}}
panelBody = (
<table
id='domain-mbxs'
cellPadding='1'
cellSpacing='1'
className='table'
style={{marginBottom: '0px'}}
>
<strong>{'Total'}</strong>
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
<strong>{totalLimit}</strong>
</td>
<td
className='text-center'
style={{borderTop: 0}}
>
<strong>{totalUsed}</strong>
</td>
</tr>
);
panelBody = (
<table
id='domain-mbxs'
cellPadding='1'
cellSpacing='1'
className='table'
style={{marginBottom: '0px'}}
>
<thead>
<tr>
<th style={{width: '50%'}}></th>
<th className='text-center'>{'Límite'}</th>
<th className='text-center'>{'Usadas'}</th>
</tr>
</thead>
<tbody>
{mailboxPlans}
</tbody>
</table>
);
<thead>
<tr>
<th style={{width: '50%'}}></th>
<th className='text-center'>{'Límite'}</th>
<th className='text-center'>{'Usadas'}</th>
</tr>
</thead>
<tbody>
{mailboxPlans}
</tbody>
</table>
);
} else {
panelBody = (
<div className='text-center'>
<h4 className='text-danger'>{'No se han asignado límites de casillas.'}</h4>
</div>
);
}
} else {
panelBody = (
<div className='text-center'>
<h4 className='text-danger'>{'No se han asignado límites de casillas.'}</h4>
<h4 className='text-danger'>{'Se esta realizando una migracion.'}</h4>
<blockquote>
{`Limite : ${countAccounts.migracion.limit || 'No definido'}`}
<br/>
{`Usadas : ${countAccounts.migracion.used || 'No definido'}`}
</blockquote>
</div>
);
}
......
......@@ -19,6 +19,7 @@ import ToggleModalButton from '../toggle_modal_button.jsx';
import MessageBar from '../message_bar.jsx';
import Promise from 'bluebird';
import MailboxStore from '../../stores/mailbox_store.jsx';
import ResendForm from './reenvios_form.jsx';
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
......@@ -343,7 +344,7 @@ export default class MailboxDetails extends React.Component {
/>
);
const tab2 = (
const tabAlias = (
<Panel
title='Casillas'
hasHeader={false}
......@@ -352,12 +353,17 @@ export default class MailboxDetails extends React.Component {
/>
);
const reenvios = (
<ResendForm mailbox={this.state.data}/>
);
panelTabs = (
<PanelTab
tabNames={['Resp Vacaciones', 'Alias']}
tabNames={['Resp Vacaciones', 'Alias', 'Reenvios']}
tabs={{
resp_vacaciones: tabAdmin,
alias: tab2
alias: tabAlias,
reenvios
}}
location={this.props.location}
/>
......
import React from 'react';
import * as Client from '../../utils/client.jsx';
import EventStore from '../../stores/event_store.jsx';
import Constants from '../../utils/constants.jsx';
const messageType = Constants.MessageType;
export default class ResendForm extends React.Component {
constructor(props) {
super(props);
this.onUpdateAttrs = this.onUpdateAttrs.bind(this);
const {attrs} = this.props.mailbox;
this.state = {
zimbraPrefMailForwardingAddress: attrs.zimbraPrefMailForwardingAddress || '',
zimbraMailForwardingAddress: attrs.zimbraMailForwardingAddress || ''
};
}
onUpdateAttrs(e) {
e.preventDefault();
const {mailbox} = this.props;
const attrs = {};
let zimbraMailForwardingAddressTextarea = this.refs.zimbraMailForwardingAddress.value.trim();
let zimbraPrefMailForwardingAddressInput = this.refs.zimbraPrefMailForwardingAddress.value.trim();
let hasError = false;
const pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (zimbraMailForwardingAddressTextarea !== '') {
const arrayMailboxes = zimbraMailForwardingAddressTextarea.split(/\r?\n/gi);
zimbraMailForwardingAddressTextarea = [];
if (arrayMailboxes && arrayMailboxes.length > 0) {
arrayMailboxes.forEach((mailbox) => {
if (mailbox !== '') {
const cleanEmail = mailbox.trim();
const isNotRightEmail = !pattern.test(cleanEmail);
if (isNotRightEmail) {
hasError = true;
} else {
zimbraMailForwardingAddressTextarea.push(mailbox);
}
}
});
}
}
if (zimbraPrefMailForwardingAddressInput !== '') {
if (!pattern.test(zimbraPrefMailForwardingAddressInput)) {
hasError = true;
}
}
if (hasError) {
return EventStore.emitToast({
body: 'Algunas de las cuentas de correo, no tiene el formato de un correo electrónico, verifique por favor.',
title: 'Reenvios',
type: messageType.ERROR.toLowerCase()
});
}
attrs.zimbraMailForwardingAddress = zimbraMailForwardingAddressTextarea;
attrs.zimbraPrefMailForwardingAddress = zimbraPrefMailForwardingAddressInput;
Client.modifyAccount(mailbox.id, attrs, () => {
//MailboxStore.updateMailbox(data.id, mailbox, this.domain_id);
EventStore.emitToast({
title: 'Reenvios',
body: 'Se han modificado los correos de reenvio éxitosamente.',
type: messageType.SUCCESS.toLowerCase()
});
this.setState(attrs);
}, (error) => {
EventStore.emitToast({
title: 'Reenvios',
body: error.message,
type: messageType.ERROR.toLowerCase()
});
});
}
renderMailbox(mailboxes) {
const accounts = mailboxes.constructor.name === 'Array' ? mailboxes.join('\r\n') : mailboxes;
return accounts;
}
render() {
const {zimbraPrefMailForwardingAddress, zimbraMailForwardingAddress} = this.state;
return (
<div>
<div className='row margin-bottom'>
<div className='col-xs-12'>
<blockquote className='custom-blockquote'>
<p>
<i>
{'Direcciones de reenvío especificadas por el usuario'}
</i>
</p>
</blockquote>
</div>
<div className='col-xs-8'>
<input
type='text'
ref='zimbraPrefMailForwardingAddress'
className='form-control'
id='forwardingAddress'
defaultValue={this.renderMailbox(zimbraPrefMailForwardingAddress)}
/>
</div>
</div>
<div className='row margin-bottom'>
<div className='col-xs-12'>
<blockquote className='custom-blockquote'>
<p>
<i>
{'Direcciones de reenvío ocultas para el usuario'}
</i>
</p>
<p>
<i>
<small>
{'Separe las cuentas de correo con una nueva linea (Tecla Enter)'}
</small>
</i>
</p>
</blockquote>
</div>
<div className='col-xs-12'>
<textarea
ref='zimbraMailForwardingAddress'
id='forwardingAddressHidden'
rows='10'
className='form-control noresize'
defaultValue={this.renderMailbox(zimbraMailForwardingAddress)}
>
</textarea>
</div>
</div>
<div className='row'>
<div className='col-xs-12 text-right'>
<button
className='btn btn-info'
onClick={this.onUpdateAttrs}
>
{'Guardar'}
</button>
</div>
</div>
</div>
);
}
}
ResendForm.propTypes = {
mailbox: React.PropTypes.object
};
......@@ -5,6 +5,7 @@ import * as GlobalActions from '../../action_creators/global_actions.jsx';
import * as Utils from '../../utils/utils.jsx';
import ErrorStore from '../../stores/error_store.jsx';
import UserStore from '../../stores/user_store.jsx';
import PageInfo from '../page_info.jsx';
import Panel from '../panel.jsx';
......@@ -39,8 +40,13 @@ export default class MassiveDelete extends React.Component {
}
}
componentWillReceiveProps() {
GlobalActions.emitEndLoading();
}
componentDidMount() {
this.handleCommands();
GlobalActions.emitEndLoading();
}
handleDelete(e) {
......@@ -55,13 +61,13 @@ export default class MassiveDelete extends React.Component {
}
const preMailboxes = consoleText.split(/\r?\n/gi);
const pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const getAccountByBatch = [];
const deleteAccountByBatch = [];
const wrongEmails = [];
const emailsNotFound = [];
preMailboxes.forEach((email) => {
const pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const cleanEmail = email.trim();
const condition = pattern.test(cleanEmail) && cleanEmail !== '';
......@@ -246,21 +252,38 @@ export default class MassiveDelete extends React.Component {
}
render() {
const consoleText = (
<div
className='row'
key='deleteConsole'
>
<div className='col-xs-12'>
<blockquote className='custom-blockquote'>
<p>
<i>
{'Escribir el nombre de las casillas a la cual se quiere eliminar, cada casilla debe ser separada por un salto de linea (Tecla Enter).'}
</i>
</p>
</blockquote>
let buttons = null;
let consoleText = null;
if (!UserStore.isGlobalAdmin()) {
consoleText = (
<div
className='text-center'
key='notAllowed'
>
<h3 className='page-header'>
{'Usted no tiene permisos para ingresar a esta area'}
</h3>
</div>
<div className='col-xs-12 wrapper-console'>
);
}
if (UserStore.isGlobalAdmin()) {
consoleText = (
<div
className='row'
key='deleteConsole'
>
<div className='col-xs-12'>
<blockquote className='custom-blockquote'>
<p>
<i>
{'Escribir el nombre de las casillas a la cual se quiere eliminar, cada casilla debe ser separada por un salto de linea (Tecla Enter).'}
</i>
</p>
</blockquote>
</div>
<div className='col-xs-12 wrapper-console'>
<textarea
className='form-control consoleText'
ref='console'
......@@ -274,25 +297,26 @@ export default class MassiveDelete extends React.Component {
</code>
{'PARA EJECUTAR'}
</span>
</div>
</div>
</div>
);
const buttons = (
<div
key={'btn-actions'}
className='row'
>
<div className='col-xs-12 text-right'>
<button
className='btn btn-danger'
onClick={this.handleDelete}
>
{'Borrar Casillas'}
</button>
);
buttons = (
<div
key={'btn-actions'}
className='row'
>
<div className='col-xs-12 text-right'>
<button
className='btn btn-danger'
onClick={this.handleDelete}
>
{'Borrar Casillas'}
</button>
</div>
</div>
</div>
);
);
}
return (
<div>
......
......@@ -13,6 +13,7 @@ export default class SidebarMenu extends React.Component {
this.handleLink = this.handleLink.bind(this);
this.openSupportModal = this.openSupportModal.bind(this);
}
handleLink(e, path) {
e.preventDefault();
if (`/${this.props.location.pathname}` !== path) {
......@@ -93,6 +94,17 @@ export default class SidebarMenu extends React.Component {
{'Soporte'}
</a>
</li>
{UserStore.isGlobalAdmin() && (
<li>
<a
className='nav-label'
href='#'
onClick={(e) => this.handleLink(e, '/deleteMassive')}
>
{'Borrado Masivo'}
</a>
</li>
)}
<li>
<Link
to='/logout'
......
......@@ -25,6 +25,7 @@ import EditDistributionList from './components/distribution/edit_distribution_li
import SearchView from './components/search/search.jsx';
import SalesForm from './components/sales/sales.jsx';
import TemplateError from './components/404/404.jsx';
import DeleteMassive from './components/massive/masive_delete.jsx';
import * as Client from './utils/client.jsx';
import * as Utils from './utils/utils.jsx';
......@@ -216,6 +217,11 @@ function renderRootComponent() {
path='sales/:domainId/mailboxes'
component={SalesForm}
/>
<Route
path='/deleteMassive'
component={DeleteMassive}
/>
</Route>
<Route component={NotLoggedIn}>
<IndexRedirect to='login'/>
......
......@@ -1855,6 +1855,14 @@ label {
}
}
.noresize {
resize: none;
}
.margin-bottom {
margin-bottom: 20px;
}
// Error Page
// scss-lint:enable all
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