Commit d68765d9 authored by Elias Nahum's avatar Elias Nahum Committed by Juorder Antonio

finish trello tasks, add multi form to create domain, add zone dns tab into domain details.

parent fe727adf
...@@ -101,7 +101,6 @@ http { ...@@ -101,7 +101,6 @@ http {
} }
} }
# HTTPS server # HTTPS server
# #
#server { #server {
......
...@@ -70,9 +70,8 @@ export default class AddAdminModal extends React.Component { ...@@ -70,9 +70,8 @@ export default class AddAdminModal extends React.Component {
e.preventDefault(); e.preventDefault();
this.props.domain.addAdmin( this.props.domain.addAdmin(
user.name, user.id,
(error, success) => { (error) => {
console.log(error, success);
if (error) { if (error) {
return this.setState({ return this.setState({
error: { error: {
......
...@@ -7,6 +7,10 @@ import * as Client from '../../utils/client.jsx'; ...@@ -7,6 +7,10 @@ import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx'; import * as Utils from '../../utils/utils.jsx';
import Promise from 'bluebird'; import Promise from 'bluebird';
import DomainStore from '../../stores/domain_store.jsx'; import DomainStore from '../../stores/domain_store.jsx';
import EventStore from '../../stores/event_store.jsx';
import Constants from '../../utils/constants.jsx';
const MessageType = Constants.MessageType;
export default class AntiSpam extends React.Component { export default class AntiSpam extends React.Component {
constructor(props) { constructor(props) {
...@@ -15,13 +19,18 @@ export default class AntiSpam extends React.Component { ...@@ -15,13 +19,18 @@ export default class AntiSpam extends React.Component {
this.handleDelete = this.handleDelete.bind(this); this.handleDelete = this.handleDelete.bind(this);
this.handleSave = this.handleSave.bind(this); this.handleSave = this.handleSave.bind(this);
this.alterDomain = this.alterDomain.bind(this); this.alterDomain = this.alterDomain.bind(this);
this.domain = DomainStore.getCurrent(); this.domain = DomainStore.getCurrent();
console.log(this.domain); this.blackList = null;
this.whiteList = null;
if (this.domain.attrs.amavisBlacklistSender) {
this.blackList = Array.isArray(this.domain.attrs.amavisBlacklistSender) ? this.domain.attrs.amavisBlacklistSender : this.domain.attrs.amavisBlacklistSender.trim().split(' '); this.blackList = Array.isArray(this.domain.attrs.amavisBlacklistSender) ? this.domain.attrs.amavisBlacklistSender : this.domain.attrs.amavisBlacklistSender.trim().split(' ');
}
if (this.domain.attrs.amavisWhitelistSender) {
this.whiteList = Array.isArray(this.domain.attrs.amavisWhitelistSender) ? this.domain.attrs.amavisWhitelistSender : this.domain.attrs.amavisWhitelistSender.trim().split(' '); this.whiteList = Array.isArray(this.domain.attrs.amavisWhitelistSender) ? this.domain.attrs.amavisWhitelistSender : this.domain.attrs.amavisWhitelistSender.trim().split(' ');
} }
}
handleDelete(e, item, action) { handleDelete(e, item, action) {
e.preventDefault(); e.preventDefault();
...@@ -56,20 +65,27 @@ export default class AntiSpam extends React.Component { ...@@ -56,20 +65,27 @@ export default class AntiSpam extends React.Component {
const attrs = {}; const attrs = {};
const isEmail = /^(([^<>()\[\]\\.,;:\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 isEmail = /^(([^<>()\[\]\\.,;:\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 isDomain = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/; const isDomain = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/;
const target = action === 'black' ? 'lista negra' : 'lista blanca';
e.preventDefault(); e.preventDefault();
const input = this.refs[`${action}-item`]; const input = this.refs[`${action}-item`];
const value = input.value.trim(); const value = input.value.trim();
if (!value || value === '') { if (!value || value === '') {
console.log('no hay valores'); EventStore.emitMessage({
message: `No puede agregar una ${target} vacia.`,
typeError: MessageType.ERROR
});
return false; return false;
} }
const isValid = isEmail.test(value) || isDomain.test(value); const isValid = isEmail.test(value) || isDomain.test(value);
if (!isValid) { if (!isValid) {
console.log('es invalido'); EventStore.emitMessage({
message: `Solo es posible agregar dominios o email en ${target}`,
typeError: MessageType.ERROR
});
return false; return false;
} }
...@@ -84,7 +100,7 @@ export default class AntiSpam extends React.Component { ...@@ -84,7 +100,7 @@ export default class AntiSpam extends React.Component {
break; break;
} }
this.alterDomain(attrs, e.target, input); return this.alterDomain(attrs, e.target, input);
} }
alterDomain(attrs, button, input) { alterDomain(attrs, button, input) {
...@@ -99,7 +115,6 @@ export default class AntiSpam extends React.Component { ...@@ -99,7 +115,6 @@ export default class AntiSpam extends React.Component {
id = `#${button.getAttribute('id')}`; id = `#${button.getAttribute('id')}`;
} }
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (hasButton) { if (hasButton) {
Utils.toggleStatusButtons(id, true); Utils.toggleStatusButtons(id, true);
...@@ -117,7 +132,10 @@ export default class AntiSpam extends React.Component { ...@@ -117,7 +132,10 @@ export default class AntiSpam extends React.Component {
update: true update: true
}); });
}).catch((err) => { }).catch((err) => {
console.log(err); EventStore.emitMessage({
message: err.message || err.reason,
typeError: MessageType.ERROR
});
}).finally(() => { }).finally(() => {
if (hasButton) { if (hasButton) {
Utils.toggleStatusButtons(id, false); Utils.toggleStatusButtons(id, false);
...@@ -134,7 +152,7 @@ export default class AntiSpam extends React.Component { ...@@ -134,7 +152,7 @@ export default class AntiSpam extends React.Component {
let whiteList = null; let whiteList = null;
let blackList = null; let blackList = null;
if (this.blackList.length > 0) { if (this.blackList && this.blackList.length > 0) {
blackList = this.blackList.map((black, i) => { blackList = this.blackList.map((black, i) => {
return ( return (
<tr <tr
...@@ -169,7 +187,7 @@ export default class AntiSpam extends React.Component { ...@@ -169,7 +187,7 @@ export default class AntiSpam extends React.Component {
); );
} }
if (this.whiteList.length > 0) { if (this.whiteList && this.whiteList.length > 0) {
whiteList = this.whiteList.map((white, i) => { whiteList = this.whiteList.map((white, i) => {
return ( return (
<tr <tr
......
//import * as Utils from '../../utils/utils.jsx';
import React from 'react'; import React from 'react';
import {browserHistory} from 'react-router';
import MessageBar from '../message_bar.jsx';
import Panel from '../panel.jsx'; import Panel from '../panel.jsx';
import CreateDomainForm from './multiform/create_domain_form.jsx';
import CompanyStore from '../../stores/company_store.jsx'; import MailCleanerForm from './multiform/mailcleaner_form.jsx';
import DNSZoneForm from './multiform/dns_form.jsx';
import DomainStore from '../../stores/domain_store.jsx'; import DomainStore from '../../stores/domain_store.jsx';
import ZimbraStore from '../../stores/zimbra_store.jsx'; import EventStore from '../../stores/event_store.jsx';
import MessageBar from '../message_bar.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 Constants from '../../utils/constants.jsx';
export default class CreateDomain extends React.Component { export default class CreateDomain extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.planSize = this.planSize.bind(this); this.getNextStep = this.getNextStep.bind(this);
this.getCompanies = this.getCompanies.bind(this); this.showMessage = this.showMessage.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {}; this.multiform = window.manager_config.multiFormDomain;
} let total = 1;
planSize(e) {
e.preventDefault();
let total = 0;
const plans = Object.keys(this.state.plans);
plans.forEach((p) => { if (this.multiform) {
total += parseInt(this.refs[`plan-${p}`].value, 10) || 0; if (this.multiform.hasMailCleaner) {
}); total++;
this.refs.mailboxLimit.value = total;
} }
getCompanies() { if (this.multiform.hasDNSZone) {
const companyId = this.props.params.id; total++;
const companies = CompanyStore.getCompanies();
if (companies) {
this.setState({
plans: Utils.getEnabledPlansByCos(ZimbraStore.getAllCos()),
companies,
companyId
});
return GlobalActions.emitEndLoading();
} }
return Client.getAllCompanies().
then((data) => {
this.setState({
plans: Utils.getEnabledPlansByCos(ZimbraStore.getAllCos()),
companies: data,
companyId
});
}).
catch((error) => {
error.type = Constants.MessageType.ERROR;
this.setState({error});
}).
finally(() => {
GlobalActions.emitEndLoading();
});
} }
handleSubmit(e) { this.state = {
e.preventDefault(); step: 1,
GlobalActions.emitStartLoading(); total
};
}
const elementList = document.querySelectorAll('.has-error'); getNextStep(attrs) {
Array.from(elementList).forEach((el) => el.classList.remove('has-error')); const states = {};
Utils.validateInputRequired(this.refs). if (attrs.domain) {
then(() => { states.domain = attrs.domain;
const plans = Object.keys(this.state.plans); }
const zimbraDomainCOSMaxAccounts = [];
const name = this.refs.domainName.value.trim();
const businessCategory = this.refs.company.value.trim();
plans.forEach((p) => { states.step = attrs.step;
zimbraDomainCOSMaxAccounts.push(`${this.refs[`plan-${p}`].getAttribute('data-id')}:${this.refs[`plan-${p}`].value || 0}`);
});
const domain = { this.setState(states);
name,
attrs: {
zimbraDomainCOSMaxAccounts,
businessCategory
} }
};
Client.createDomain( showMessage(attrs) {
domain, this.setState({
(data) => { error: attrs.message,
CompanyStore.addDomain(businessCategory, data); type: attrs.typeError
DomainStore.setCurrent(data);
browserHistory.push(`/domains/${data.id}`);
},
(error) => {
GlobalActions.emitEndLoading();
return this.setState({error});
}
);
}).
catch((error) => {
GlobalActions.emitEndLoading();
error.refs = true;
error.type = error.typeError;
error.node.closest('.form-group').classList.add('has-error');
return this.setState({error});
}); });
} }
componentDidMount() { componentDidMount() {
this.getCompanies(); DomainStore.addNextStepListener(this.getNextStep);
EventStore.addMessageListener(this.showMessage);
} }
render() { componentWillUnmount() {
const companies = this.state.companies; DomainStore.removeNextStepListener(this.getNextStep);
const error = this.state.error; EventStore.removeMessageListener(this.showMessage);
if (companies || error) {
let backUrl = '/domains';
if (this.state.companyId) {
backUrl = `/companies/${this.state.companyId}`;
} }
let errorBar; render() {
if (error) { let form = null;
errorBar = ( let titleForm = null;
const progress = `${this.state.step}/${this.state.total}`;
let progressForm = null;
const width = ((100 / this.state.total) * this.state.step);
const progressSize = {
width: `${width}%`
};
let error = null;
if (this.state.error) {
error = (
<MessageBar <MessageBar
message={error.message} message={this.state.error}
type={error.type} type={this.state.type}
autoclose={true} autoclose={true}
/> />
); );
} }
const companiesOptions = companies.map((c) => { let step = this.state.step;
return (
<option
key={`company-${c.id}`}
value={c.id}
>
{c.name}
</option>
);
});
const statePlans = this.state.plans;
const enabledPlans = Object.keys(statePlans);
const plans = enabledPlans.map((p) => {
return (
<div
key={`plan-${statePlans[p]}`}
className='col-md-4 form-group required'
>
<label
htmlFor={`plan-${p}`}
clasName='label-top control-label'
>
<abbr title='Requerido'>{'*'}</abbr><br/>
{Utils.titleCase(p)}
</label>
<br/>
<div className='row'>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
defaultValue='0'
data-required='true'
data-message={`Debe asignar la cantidad de casillas del tipo ${Utils.titleCase(p)}`}
data-id={statePlans[p]}
ref={`plan-${p}`}
onKeyUp={this.planSize}
/>
</div>
</div>
</div>
);
});
const form = (
<form
className='simple_form form-horizontal mailbox-form'
onSubmit={this.handleSubmit}
>
<div className='form-group string required'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Nombre'}
</label>
<div className='col-sm-8'>
<input
type='text'
data-required='true'
data-message='El nombre del dominio es obligatorio'
className='form-control'
ref='domainName'
placeholder='example.com'
/>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Empresa'}
</label>
<div className='col-sm-8'>
<select
className='form-control select required'
data-required='true'
data-message='Debe especificar a que empresa corresponde el dominio'
ref='company'
defaultValue={this.state.companyId}
>
{companiesOptions}
</select>
</div>
</div>
<div className='form-group row'>
<div className='col-md-8 col-md-offset-3'>
<div className='box-content'>
{plans}
</div>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Límite de casillas'}
</label>
<div className='col-sm-8'> if (!this.multiform.hasMailCleaner && step > 1) {
<input ++step;
type='text' }
className='form-control'
ref='mailboxLimit'
value='0'
disabled='disabled'
/>
</div>
</div>
<div className='form-group'> switch (step) {
<div className='col-sm-8 col-sm-offset-3'> case 1:
<input form = (
type='submit' <CreateDomainForm
name='commit' params={this.props.params}
value='Guardar' state={this.state}
className='btn btn-info'
/> />
<a
href='#'
className='btn btn-default'
onClick={(e) => Utils.handleLink(e, backUrl)}
>
{'Cancelar'}
</a>
</div>
</div>
</form>
); );
titleForm = 'Creación de Dominio';
break;
case 2:
form = <MailCleanerForm state={this.state}/>;
titleForm = 'Asignación del Dominio al MailCleaner';
break;
case 3:
form = <DNSZoneForm state={this.state}/>;
titleForm = 'Asignación de la Zona DNS';
break;
}
//onClick: (e) => Utils.handleLink(e, backUrl)
const actions = [ const actions = [
{ {
label: 'Cancelar', label: 'Cancelar',
props: { props: {
className: 'btn btn-default btn-xs', className: 'btn btn-default btn-xs'
onClick: (e) => Utils.handleLink(e, backUrl)
} }
} }
]; ];
if (this.state.total > 1) {
progressForm = (
<div className='progress'>
<div
className={'progress-bar progress-bar-info progress-bar-striped active text-center step'}
style={progressSize}
>
<span className='progress-text'>{`${titleForm} - ${progress}`}</span>
</div>
</div>
);
}
return ( return (
<Panel <Panel
title={'Agregar Dominio'} title={'Agregar Dominio'}
btnsHeader={actions}
error={errorBar}
classHeader={'forum-box'} classHeader={'forum-box'}
btnsHeader={actions}
> >
{error}
{progressForm}
{form} {form}
</Panel> </Panel>
); );
} }
return <div/>;
}
} }
CreateDomain.propTypes = { CreateDomain.propTypes = {
params: React.PropTypes.object.isRequired params: React.PropTypes.object.isRequired
}; };
import React from 'react';
import * as Utils from '../../utils/utils.jsx';
import Constants from '../../utils/constants.jsx';
import EventStore from '../../stores/event_store.jsx';
import DomainStore from '../../stores/domain_store.jsx';
const Labels = Constants.Labels;
const MessageType = Constants.MessageType;
export default class DNSZoneForm extends React.Component {
constructor(props) {
super(props);
this.addDNSRow = this.addDNSRow.bind(this);
this.removeRow = this.removeRow.bind(this);
this.handleChangeInput = this.handleChangeInput.bind(this);
this.addDNSRequest = this.addDNSRequest.bind(this);
this.zoneDNSChange = this.zoneDNSChange.bind(this);
this.zoneDNS = DomainStore.getZoneDNS();
this.instanceRow = {
name: '',
type: Constants.typesOfDNS[0],
content: '',
priority: 10,
ttl: 86400,
disabled: false
};
this.defaultRows = this.getRecords();
this.types = Constants.typesOfDNS;
this.state = {
fields: this.defaultRows
};
}
getRecords() {
const records = [];
const zoneRecords = this.zoneDNS;
if (zoneRecords) {
zoneRecords.records.forEach((zone) => {
const newObject = {};
Object.assign(newObject, this.instanceRow, zone);
records.push(newObject);
});
}
return records;
}
addDNSRequest() {
const records = this.defaultRows;
const zoneDNS = this.zoneDNS;
Utils.toggleStatusButtons('.savedns', true);
const button = this.refs.savedns;
const oldContent = button.innerHTML;
button.innerHTML = '<i class=\'fa fa-spinner fa-spin\'></i> Creando Zona DNS';
if (zoneDNS) {
zoneDNS.createOrModifyRecords(records, (err, data) => {
if (err) {
Utils.toggleStatusButtons('.savedns', false);
button.innerHTML = oldContent;
return EventStore.emitMessage({
message: err.reason,
typeError: MessageType.ERROR
});
}
DomainStore.setZoneDNS(data);
Utils.toggleStatusButtons('.savedns', false);
button.innerHTML = oldContent;
return EventStore.emitMessage({
message: 'Se ha registrado su nuevo DNS éxitoxamente.',
typeError: MessageType.SUCCESS
});
});
} else {
EventStore.emitMessage({
message: 'Ha ocurrido un error general al intentar agregar un registro DNS',
typeError: MessageType.ERROR
});
}
}
addDNSRow() {
const copy = Object.assign({}, this.instanceRow);
copy.enabled = true;
this.defaultRows.push(copy);
this.setState({
fields: this.defaultRows
});
}
removeRow(e, index) {
e.preventDefault();
const zoneDNS = this.zoneDNS;
const button = e.target;
const old = button.innerHTML;
button.innerHTML = '<i class=\'fa fa-spinner fa-spin\'></i>';
button.setAttribute('disabled', 'disabled');
if (this.defaultRows[index]) {
if (zoneDNS && zoneDNS.records[index]) {
return zoneDNS.deleteRecords(this.defaultRows[index], (error, success) => {
if (error) {
button.removeAttribute('disabled');
button.innerHTML = old;
return EventStore.emitMessage({
message: error.message,
typeError: MessageType.ERROR
});
}
const name = this.defaultRows[index].name;
DomainStore.setZoneDNS(success);
return EventStore.emitMessage({
message: `Se ha borrado su DNS ${name} éxitoxamente.`,
typeError: MessageType.ERROR
});
});
}
this.defaultRows.splice(index, 1);
this.setState({
fields: this.defaultRows
});
}
return false;
}
handleChangeInput(e, index, ref) {
const value = e.target.value;
if (this.defaultRows[index]) {
this.defaultRows[index][ref] = value;
return true;
}
return false;
}
zoneDNSChange() {
this.zoneDNS = DomainStore.getZoneDNS();
this.defaultRows = this.getRecords();
this.setState({
fields: this.defaultRows
});
}
componentDidMount() {
DomainStore.addZoneDNSChangeListener(this.zoneDNSChange);
}
componentWillUnmount() {
DomainStore.addZoneDNSChangeListener(this.zoneDNSChange);
}
render() {
let isVisible = false;
let fields = null;
let header = null;
const types = this.types.map((item) => {
return (
<option
key={item}
value={item}
>
{item}
</option>
);
});
fields = (
<div className='text-center'>
<h4>No existen Zonas DNS para su dominio : <strong>{this.props.domain.name}</strong></h4>
</div>
);
if (this.defaultRows.length > 0) {
isVisible = true;
header = (
<div className='row'>
<div className='col-xs-3'>
<strong>Nombre</strong>
</div>
<div className='col-xs-1'>
<strong>Tipo</strong>
</div>
<div className='col-xs-3'>
<strong>Contenido</strong>
</div>
<div className='col-xs-2'>
<strong>Prioridad</strong>
</div>
<div className='col-xs-2'>
<strong>TTL</strong>
</div>
<div className='col-xs-1'>
<strong>Acciones</strong>
</div>
</div>
);
fields = this.defaultRows.map((element, i) => {
const isDisabled = element.enabled ? null : true;
return (
<div
className='row set-margin-up'
key={`row-${new Date().getTime()}-${i}`}
id={`row-dns-${new Date().getTime()}-${i}`}
>
<div className='col-xs-3'>
<input
type='text'
defaultValue={element.name}
className='form-control'
onChange={(e) => {
this.handleChangeInput(e, i, Labels.name);
}}
disabled={isDisabled}
/>
</div>
<div className='col-xs-1'>
<select
className='form-control'
defaultValue={element.type}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.type);
}}
disabled={isDisabled}
>
{types}
</select>
</div>
<div className='col-xs-3'>
<input
type='text'
className='form-control'
defaultValue={element.content}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.content);
}}
/>
</div>
<div className='col-xs-2'>
<input
type='number'
className='form-control'
defaultValue={element.priority}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.priority);
}}
/>
</div>
<div className='col-xs-2'>
<input
type='number'
className='form-control'
defaultValue={element.ttl}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.ttl);
}}
/>
</div>
<div className='col-xs-1'>
<button
className='btn btn-danger'
onClick={(e) => {
this.removeRow(e, i);
}}
>
<i
className='fa fa-trash-o'
title='Delete'
>
</i>
</button>
</div>
</div>
);
});
}
return (
<div>
<blockquote className='clearfix'>
<p>
<button
className='btn btn-info pull-right'
onClick={this.addDNSRow}
>
<i className='fa fa-plus-circle fa-lg'></i> Agregar otro registro
</button>
</p>
</blockquote>
<form>
{header}
{fields}
<br/>
<br/>
<div className='col-xs-12 text-right'>
{(isVisible &&
<button
type='button'
className='btn btn-info savedns'
onClick={this.addDNSRequest}
ref='savedns'
>
{'Guardar'}
</button>
)}
</div>
</form>
</div>
);
}
}
DNSZoneForm.propTypes = {
domain: React.PropTypes.object
};
...@@ -8,7 +8,6 @@ import MessageBar from '../message_bar.jsx'; ...@@ -8,7 +8,6 @@ import MessageBar from '../message_bar.jsx';
import PageInfo from '../page_info.jsx'; import PageInfo from '../page_info.jsx';
import PanelTab from '../panel_tab.jsx'; import PanelTab from '../panel_tab.jsx';
import Button from '../button.jsx';
import DomainGeneralInfo from './domain_general_info.jsx'; import DomainGeneralInfo from './domain_general_info.jsx';
import DomainMailboxPlans from './domain_mailbox_plans.jsx'; import DomainMailboxPlans from './domain_mailbox_plans.jsx';
import DomainAdmins from './domain_admin_list.jsx'; import DomainAdmins from './domain_admin_list.jsx';
...@@ -16,6 +15,8 @@ import DomainDistributionList from './domain_distribution_list.jsx'; ...@@ -16,6 +15,8 @@ import DomainDistributionList from './domain_distribution_list.jsx';
import ToggleModalButton from '../toggle_modal_button.jsx'; import ToggleModalButton from '../toggle_modal_button.jsx';
import MultipleTaskModal from './multiple_task_modal.jsx'; import MultipleTaskModal from './multiple_task_modal.jsx';
import AntiSpamComponent from './antispam.jsx'; import AntiSpamComponent from './antispam.jsx';
import ZonaDNS from './domain_admin_dns.jsx';
import EventStore from '../../stores/event_store.jsx';
import DomainStore from '../../stores/domain_store.jsx'; import DomainStore from '../../stores/domain_store.jsx';
...@@ -27,27 +28,63 @@ export default class DomainDetails extends React.Component { ...@@ -27,27 +28,63 @@ export default class DomainDetails extends React.Component {
super(props); super(props);
this.getDomain = this.getDomain.bind(this); this.getDomain = this.getDomain.bind(this);
this.showMessage = this.showMessage.bind(this);
this.state = {}; this.state = {};
} }
showMessage(attrs) {
this.setState({
error: {
message: attrs.message,
type: attrs.typeError
}
});
}
getDomain() { getDomain() {
const domain = DomainStore.getCurrent(); const domain = DomainStore.getCurrent();
if (domain && domain.id === this.props.params.id) { if (domain && domain.id === this.props.params.id) {
GlobalActions.emitEndLoading(); GlobalActions.emitEndLoading();
Client.getZone(domain.name, (zone) => {
DomainStore.setZoneDNS(zone);
this.setState({
domain
});
GlobalActions.emitEndLoading();
}, () => {
DomainStore.setZoneDNS(null);
this.setState({ this.setState({
domain domain
}); });
GlobalActions.emitEndLoading();
});
} else { } else {
Client.getDomain( Client.getDomain(
this.props.params.id, this.props.params.id,
(data) => { (data) => {
DomainStore.setCurrent(data); DomainStore.setCurrent(data);
Client.getZone(data.name, (zone) => {
DomainStore.setZoneDNS(zone);
this.setState({
domain: data
});
GlobalActions.emitEndLoading();
}, () => {
this.setState({ this.setState({
domain: data domain: data
}); });
GlobalActions.emitEndLoading(); GlobalActions.emitEndLoading();
});
}, },
(error) => { (error) => {
this.setState({ this.setState({
...@@ -60,12 +97,14 @@ export default class DomainDetails extends React.Component { ...@@ -60,12 +97,14 @@ export default class DomainDetails extends React.Component {
} }
componentDidMount() { componentDidMount() {
EventStore.addMessageListener(this.showMessage);
$('#sidebar-domains').addClass('active'); $('#sidebar-domains').addClass('active');
this.getDomain(); this.getDomain();
} }
componentWillUnmount() { componentWillUnmount() {
$('#sidebar-domains').removeClass('active'); $('#sidebar-domains').removeClass('active');
EventStore.removeMessageListener(this.showMessage);
} }
render() { render() {
...@@ -125,14 +164,21 @@ export default class DomainDetails extends React.Component { ...@@ -125,14 +164,21 @@ export default class DomainDetails extends React.Component {
</div> </div>
); );
const zonaDNS = (
<ZonaDNS
domain={domain}
/>
);
const panelTabs = ( const panelTabs = (
<PanelTab <PanelTab
tabNames={['Administradores', 'AntiSpam', 'Listas De Distribución', 'Tareas Masivas']} tabNames={['Administradores', 'AntiSpam', 'Listas De Distribución', 'Tareas Masivas', 'Zona DNS']}
tabs={{ tabs={{
administradores: tabAdmin, administradores: tabAdmin,
antispam: tabAntiSpam, antispam: tabAntiSpam,
listas_de_distribución: tabDistribution, listas_de_distribución: tabDistribution,
tareas_masivas: tabTareasMasivas tareas_masivas: tabTareasMasivas,
zona_dns: zonaDNS
}} }}
location={this.props.location} location={this.props.location}
/> />
......
...@@ -56,13 +56,11 @@ export default class DomainGeneralInfo extends React.Component { ...@@ -56,13 +56,11 @@ export default class DomainGeneralInfo extends React.Component {
company: company.name company: company.name
}); });
} else { } else {
Client.getCompany(id). Client.getCompany(id, (data) => {
then((data) => {
this.setState({ this.setState({
company: data.name company: data.name
}); });
}). }, (error) => {
catch((error) => {
this.setState({ this.setState({
error: { error: {
message: error.message, message: error.message,
......
import React from 'react';
import {browserHistory} from 'react-router';
import CompanyStore from '../../../stores/company_store.jsx';
import DomainStore from '../../../stores/domain_store.jsx';
import ZimbraStore from '../../../stores/zimbra_store.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 Constants from '../../../utils/constants.jsx';
const MessageType = Constants.MessageType;
export default class CreateDomainForm extends React.Component {
constructor(props) {
super(props);
this.planSize = this.planSize.bind(this);
this.getCompanies = this.getCompanies.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {};
}
planSize(e) {
e.preventDefault();
let total = 0;
const plans = Object.keys(this.state.plans);
plans.forEach((p) => {
total += parseInt(this.refs[`plan-${p}`].value, 10) || 0;
});
this.refs.mailboxLimit.value = total;
}
getCompanies() {
const companyId = this.props.params.id;
const companies = CompanyStore.getCompanies();
if (companies) {
this.setState({
plans: Utils.getEnabledPlansByCos(ZimbraStore.getAllCos()),
companies,
companyId
});
return GlobalActions.emitEndLoading();
}
return Client.getAllCompanies().
then((data) => {
this.setState({
plans: Utils.getEnabledPlansByCos(ZimbraStore.getAllCos()),
companies: data,
companyId
});
}).
catch((error) => {
GlobalActions.emitMessage({
message: error.message,
typeError: MessageType.ERROR
});
}).
finally(() => {
GlobalActions.emitEndLoading();
});
}
handleSubmit(e) {
e.preventDefault();
const button = this.refs.createdomainbtn;
const oldContent = button.innerHTML;
if (this.props.state.total === this.props.state.step) {
GlobalActions.emitStartLoading();
}
const elementList = document.querySelectorAll('.has-error');
Array.from(elementList).forEach((el) => el.classList.remove('has-error'));
Utils.validateInputRequired(this.refs).
then(() => {
const plans = Object.keys(this.state.plans);
const zimbraDomainCOSMaxAccounts = [];
const name = this.refs.domainName.value.trim();
const businessCategory = this.refs.company.value.trim();
const zimbraDomainStatus = this.refs.zimbraDomainStatus.value.trim();
plans.forEach((p) => {
zimbraDomainCOSMaxAccounts.push(`${this.refs[`plan-${p}`].getAttribute('data-id')}:${this.refs[`plan-${p}`].value || 0}`);
});
const domain = {
name,
attrs: {
zimbraDomainCOSMaxAccounts,
businessCategory,
zimbraDomainStatus
}
};
button.innerHTML = '<i class=\'fa fa-spinner fa-spin\'></i> Creando Dominio';
Utils.toggleStatusButtons('.action-create-domain', true);
Client.createDomain(
domain,
(data) => {
CompanyStore.addDomain(businessCategory, data);
DomainStore.setCurrent(data);
if (this.props.state.total === this.props.state.step) {
browserHistory.push(`/domains/${data.id}`);
} else {
DomainStore.emitNextStep({
step: ++this.props.state.step,
domain: data
});
}
button.innerHTML = oldContent;
Utils.toggleStatusButtons('.action-create-domain', false);
},
(error) => {
if (this.props.state.total === this.props.state.step) {
GlobalActions.emitEndLoading();
}
button.innerHTML = oldContent;
Utils.toggleStatusButtons('.action-create-domain', false);
return GlobalActions.emitMessage({
message: error.message,
typeError: MessageType.ERROR
});
}
);
}).
catch((error) => {
if (this.props.state.total === this.props.state.step) {
GlobalActions.emitEndLoading();
}
error.refs = true;
error.type = error.typeError;
error.node.closest('.form-group').classList.add('has-error');
return GlobalActions.emitMessage({
message: error.message,
typeError: error.type
});
});
}
componentDidMount() {
Client.initPowerDNS();
this.getCompanies();
}
render() {
const companies = this.state.companies;
const error = this.state.error;
if (companies || error) {
let backUrl = '/domains';
if (this.state.companyId) {
backUrl = `/companies/${this.state.companyId}`;
}
const companiesOptions = companies.map((c) => {
return (
<option
key={`company-${c.id}`}
value={c.id}
>
{c.name}
</option>
);
});
const statePlans = this.state.plans;
const enabledPlans = Object.keys(statePlans);
const plans = enabledPlans.map((p) => {
return (
<div
key={`plan-${statePlans[p]}`}
className='col-md-4 form-group required'
>
<label
htmlFor={`plan-${p}`}
clasName='label-top control-label'
>
<abbr title='Requerido'>{'*'}</abbr><br/>
{Utils.titleCase(p)}
</label>
<br/>
<div className='row'>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
defaultValue='0'
data-required='true'
data-message={`Debe asignar la cantidad de casillas del tipo ${Utils.titleCase(p)}`}
data-id={statePlans[p]}
ref={`plan-${p}`}
onKeyUp={this.planSize}
/>
</div>
</div>
</div>
);
});
const form = (
<form
className='simple_form form-horizontal mailbox-form'
onSubmit={this.handleSubmit}
>
<div className='form-group string required'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Nombre'}
</label>
<div className='col-sm-8'>
<input
type='text'
data-required='true'
data-message='El nombre del dominio es obligatorio'
className='form-control'
ref='domainName'
placeholder='example.com'
/>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Empresa'}
</label>
<div className='col-sm-8'>
<select
className='form-control select required'
data-required='true'
data-message='Debe especificar a que empresa corresponde el dominio'
ref='company'
defaultValue={this.state.companyId}
>
{companiesOptions}
</select>
</div>
</div>
<div className='form-group row'>
<div className='col-md-8 col-md-offset-3'>
<div className='box-content'>
{plans}
</div>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
<abbr title='requerido'>{'*'}</abbr>
{'Status'}
</label>
<div className='col-sm-8'>
<select
className='form-control select'
data-required='true'
data-message='Debe especificar el status del dominio'
ref='zimbraDomainStatus'
>
<option value='active'>Activo</option>
<option value='closed'>Cerrado</option>
<option value='locked'>Bloqueado</option>
<option value='maintenance'>En Mantención</option>
<option value='suspended'>Suspendido</option>
</select>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Límite de casillas'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
ref='mailboxLimit'
value='0'
disabled='disabled'
/>
</div>
</div>
<div className='form-group'>
<div className='col-sm-8 col-sm-offset-3'>
<button
className='btn btn-info action-create-domain'
ref='createdomainbtn'
>
{'Guardar'}
</button>
<a
href='#'
className='btn btn-default'
onClick={(e) => Utils.handleLink(e, backUrl)}
>
{'Cancelar'}
</a>
</div>
</div>
</form>
);
return (
<div>
{form}
</div>
);
}
return <div/>;
}
}
CreateDomainForm.propTypes = {
params: React.PropTypes.object.isRequired,
state: React.PropTypes.object
};
import React from 'react';
import {browserHistory} from 'react-router';
import * as Utils from '../../../utils/utils.jsx';
import Constants from '../../../utils/constants.jsx';
import * as Client from '../../../utils/client.jsx';
import EventStore from '../../../stores/event_store.jsx';
import DomainStore from '../../../stores/domain_store.jsx';
const Labels = Constants.Labels;
const MessageType = Constants.MessageType;
export default class DNSZoneForm extends React.Component {
constructor(props) {
super(props);
this.nextStep = this.nextStep.bind(this);
this.addDNSRow = this.addDNSRow.bind(this);
this.removeRow = this.removeRow.bind(this);
this.handleChangeInput = this.handleChangeInput.bind(this);
this.addDNSRequest = this.addDNSRequest.bind(this);
this.instanceRow = {
name: '',
type: Constants.typesOfDNS[0],
content: '',
priority: 10,
ttl: 86400,
disabled: false
};
this.defaultRows = [
Object.assign({}, this.instanceRow),
Object.assign({}, this.instanceRow),
Object.assign({}, this.instanceRow)
];
this.types = Constants.typesOfDNS;
this.state = {
fields: this.defaultRows,
emptyValue: ''
};
}
nextStep() {
if (this.props.state.step === this.props.state.total) {
browserHistory.push(`/domains/${this.props.state.domain.id}`);
} else {
DomainStore.emitNextStep({
step: ++this.props.state.step
});
}
}
addDNSRequest() {
const request = {
name: this.props.state.domain.name,
kind: 'Master',
nameservers: []
};
const records = this.defaultRows;
Utils.toggleStatusButtons('.savedns', true);
const button = this.refs.savedns;
const oldContent = button.innerHTML;
button.innerHTML = '<i class=\'fa fa-spinner fa-spin\'></i> Creando Zona DNS';
Client.getZone(this.props.state.domain.name, (zona) => {
zona.createOrModifyRecords(records, (err) => {
if (err) {
EventStore.emitMessage({
message: err.reason,
typeError: MessageType.ERROR
});
button.innerHTML = oldContent;
return Utils.toggleStatusButtons('.savedns', false);
}
return this.nextStep();
});
}, () => {
Client.createZoneWithRecords(request, records, () => {
this.nextStep();
}, (error) => {
EventStore.emitMessage({
message: error.reason,
typeError: MessageType.ERROR
});
Utils.toggleStatusButtons('.savedns', false);
button.innerHTML = oldContent;
});
});
}
addDNSRow() {
const copy = Object.assign({}, this.instanceRow);
this.defaultRows.push(copy);
this.setState({
fields: this.defaultRows
});
}
removeRow(e, index) {
e.preventDefault();
if (this.defaultRows[index]) {
this.defaultRows.splice(index, 1);
this.setState({
fields: this.defaultRows
});
}
return false;
}
clearInputsFromParent(parentID) {
const parent = document.getElementById(parentID);
if (parent) {
const elements = parent.querySelectorAll('input, select');
let size = elements.length;
if (size > 0) {
for (;size-- > 0;) {
if (elements[size].nodeName.toLowerCase() === 'input') {
elements[size].value = '';
} else {
elements[size].selectedIndex = 0;
}
}
}
}
}
handleChangeInput(e, index, ref) {
const value = e.target.value;
if (this.defaultRows[index]) {
this.defaultRows[index][ref] = value;
return true;
}
return false;
}
render() {
const textButton = this.props.state.step === this.props.state.total ? 'Saltar y Finalizar' : 'Saltar este paso';
let fields = null;
let header = null;
const types = this.types.map((item) => {
return (
<option
key={item}
value={item}
>
{item}
</option>
);
});
fields = (
<div className='text-center'>
<h4>No existen Zonas DNS para su dominio : <strong>{this.props.state.domain.name}</strong></h4>
</div>
);
if (Array.isArray(this.defaultRows) && this.defaultRows.length > 0) {
header = (
<div className='row'>
<div className='col-xs-3'>
<strong>Nombre</strong>
</div>
<div className='col-xs-1'>
<strong>Tipo</strong>
</div>
<div className='col-xs-3'>
<strong>Contenido</strong>
</div>
<div className='col-xs-2'>
<strong>Prioridad</strong>
</div>
<div className='col-xs-2'>
<strong>TTL</strong>
</div>
<div className='col-xs-1'>
<strong>Acciones</strong>
</div>
</div>
);
fields = this.defaultRows.map((element, i) => {
return (
<div
className='row set-margin-up'
key={`row-${new Date().getTime()}-${i}`}
id={`row-dns-${new Date().getTime()}-${i}`}
>
<div className='col-xs-3'>
<input
type='text'
defaultValue={element.name}
className='form-control'
ref={`${Labels.name}-${i}`}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.name);
}}
/>
</div>
<div className='col-xs-1'>
<select
className='form-control'
defaultValue={element.type}
ref={`${Labels.type}-${i}`}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.type);
}}
>
{types}
</select>
</div>
<div className='col-xs-3'>
<input
type='text'
className='form-control'
defaultValue={element.content}
ref={`${Labels.content}-${i}`}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.content);
}}
/>
</div>
<div className='col-xs-2'>
<input
type='number'
className='form-control'
defaultValue={element.priority}
ref={`${Labels.priority}-${i}`}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.priority);
}}
/>
</div>
<div className='col-xs-2'>
<input
type='number'
className='form-control'
defaultValue={element.ttl}
ref={`${Labels.ttl}-${i}`}
onChange={(e) => {
this.handleChangeInput(e, i, Labels.ttl);
}}
/>
</div>
<div className='col-xs-1'>
<button
className='btn btn-danger'
onClick={(e) => {
this.removeRow(e, i);
}}
>
<i
className='fa fa-trash-o'
title='Delete'
>
</i>
</button>
</div>
</div>
);
});
}
return (
<div>
<blockquote className='clearfix'>
<p>
{'Editar Zona DNS para '}<strong>{this.props.state.domain.name}</strong>
<button
className='btn btn-info pull-right'
onClick={this.addDNSRow}
>
<i className='fa fa-plus-circle fa-lg'></i> Agregar otro registro
</button>
</p>
</blockquote>
<form>
{header}
{fields}
<br/>
<br/>
<div className='col-xs-12 text-right'>
<button
type='button'
className='btn btn-info savedns'
onClick={this.addDNSRequest}
ref='savedns'
>
{'Guardar'}
</button>
<button
type='button'
className='btn btn-info'
onClick={this.nextStep}
>
{textButton}
</button>
</div>
</form>
</div>
);
}
}
DNSZoneForm.propTypes = {
state: React.PropTypes.object
};
import React from 'react';
import * as Utils from '../../../utils/utils.jsx';
import {browserHistory} from 'react-router';
import DomainStore from '../../../stores/domain_store.jsx';
export default class MailCleanerForm extends React.Component {
constructor(props) {
super(props);
this.addMailCleaner = this.addMailCleaner.bind(this);
this.nextStep = this.nextStep.bind(this);
this.handleChangeOption = this.handleChangeOption.bind(this);
this.state = {};
}
nextStep() {
if (this.props.state.step === this.props.state.total) {
browserHistory.push(`/domains/${this.props.state.domain.id}`);
} else {
DomainStore.emitNextStep({
step: ++this.props.state.step
});
}
}
handleChangeOption() {
const isEnabledMailCleaner = this.refs.enableMailcleaner.checked;
Utils.toggleStatusButtons('.saveMC', !isEnabledMailCleaner);
}
addMailCleaner() {
const isEnabledMailCleaner = this.refs.enableMailcleaner.checked;
return isEnabledMailCleaner;
}
componentDidMount() {
Utils.toggleStatusButtons('.saveMC', true);
}
render() {
const textButton = this.props.state.step === this.props.state.total ? 'Saltar y Finalizar' : 'Saltar este paso';
return (
<div>
<blockquote>
<p>{'¿ Desea agregar su dominio '}<strong>{this.props.state.domain.name}</strong>{' a MailCleaner ?'}</p>
</blockquote>
<form>
<div className='col-xs-12'>
<label
className='radio radio-info radio-inline pretty-input'
>
<div className='pretty-checkbox'>
<input
type='checkbox'
className='pretty'
name='mailbox'
ref='enableMailcleaner'
onChange={this.handleChangeOption}
/>
<span></span>
</div>
{'Desea usar MailCleaner en su dominio: '} <strong>{this.props.state.domain.name}</strong>
</label>
</div>
<br/>
<br/>
<div className='col-xs-12 text-right'>
<button
type='button'
className='btn btn-info saveMC'
onClick={this.addMailCleaner}
>
{'Guardar'}
</button>
<button
type='button'
className='btn btn-info'
onClick={this.nextStep}
>
{textButton}
</button>
</div>
</form>
</div>
);
}
}
MailCleanerForm.propTypes = {
state: React.PropTypes.object
};
...@@ -69,8 +69,7 @@ export default class MultipleTaskModal extends React.Component { ...@@ -69,8 +69,7 @@ export default class MultipleTaskModal extends React.Component {
if (this.props.show) { if (this.props.show) {
this.props.onHide(); this.props.onHide();
} }
}, (err) => { }, () => {
console.log('err',err);
if (this.props.show) { if (this.props.show) {
this.props.onHide(); this.props.onHide();
} }
...@@ -93,8 +92,7 @@ export default class MultipleTaskModal extends React.Component { ...@@ -93,8 +92,7 @@ export default class MultipleTaskModal extends React.Component {
accounts: res accounts: res
}); });
}).catch((error) => { }).catch((error) => {
console.log('err', error); return error;
}).finally(() => {
}); });
} }
......
...@@ -11,7 +11,6 @@ import * as Utils from '../utils/utils.jsx'; ...@@ -11,7 +11,6 @@ import * as Utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
import MailboxStore from '../stores/mailbox_store.jsx'; import MailboxStore from '../stores/mailbox_store.jsx';
export default class ImportMassiveModal extends React.Component { export default class ImportMassiveModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -35,7 +34,6 @@ export default class ImportMassiveModal extends React.Component { ...@@ -35,7 +34,6 @@ export default class ImportMassiveModal extends React.Component {
this.uploaded = null; this.uploaded = null;
this.disabled = {}; this.disabled = {};
this.plans = Utils.getEnabledPlansByCos(ZimbraStore.getAllCos()); this.plans = Utils.getEnabledPlansByCos(ZimbraStore.getAllCos());
this.state = { this.state = {
...@@ -90,14 +88,17 @@ export default class ImportMassiveModal extends React.Component { ...@@ -90,14 +88,17 @@ export default class ImportMassiveModal extends React.Component {
} else { } else {
return this.setState({ return this.setState({
alert: true, alert: true,
alertMessage: 'Su archvio esta vacio, verifiquelo, por favor', alertMessage: 'Su archvio esta vacio, verifiquelo, por favor'
}); });
} }
return null;
}; };
fileReader.readAsText(file); fileReader.readAsText(file);
} }
return null;
} }
onChangeColumn(e, option, key) { onChangeColumn(e, option, key) {
...@@ -149,6 +150,8 @@ export default class ImportMassiveModal extends React.Component { ...@@ -149,6 +150,8 @@ export default class ImportMassiveModal extends React.Component {
if (pos === '') { if (pos === '') {
return true; return true;
} }
return null;
}); });
if (isEmpty) { if (isEmpty) {
...@@ -204,7 +207,7 @@ export default class ImportMassiveModal extends React.Component { ...@@ -204,7 +207,7 @@ export default class ImportMassiveModal extends React.Component {
if (!ul[c]) { if (!ul[c]) {
if (col.indexOf('@') > -1) { if (col.indexOf('@') > -1) {
if (isEmail.test(col)) { if (isEmail.test(col)) {
ul[c] = {} ul[c] = {};
ul[c][flagDefault] = []; ul[c][flagDefault] = [];
this.disabled[flagDefault] = { this.disabled[flagDefault] = {
col: c col: c
...@@ -246,8 +249,8 @@ export default class ImportMassiveModal extends React.Component { ...@@ -246,8 +249,8 @@ export default class ImportMassiveModal extends React.Component {
counter++; counter++;
} }
const length = (Array.isArray(this.uploaded[current])) ? this.uploaded[current].length : this.uploaded[current]['email'].length; const length = (Array.isArray(this.uploaded[current])) ? this.uploaded[current].length : this.uploaded[current].email.length;
const data = (Array.isArray(this.uploaded[current])) ? this.uploaded[current] : this.uploaded[current]['email']; const data = (Array.isArray(this.uploaded[current])) ? this.uploaded[current] : this.uploaded[current].email;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
if (!padre[i]) { if (!padre[i]) {
...@@ -267,10 +270,11 @@ export default class ImportMassiveModal extends React.Component { ...@@ -267,10 +270,11 @@ export default class ImportMassiveModal extends React.Component {
return this.createMassiveAccounts(padre); return this.createMassiveAccounts(padre);
} }
return this.setState({ this.setState({
alert: true, alert: true,
alertMessage: 'Faltan columnas que son obligatorias, verifique por favor.' alertMessage: 'Faltan columnas que son obligatorias, verifique por favor.'
}); });
return null;
} }
createMassiveAccounts(accounts) { createMassiveAccounts(accounts) {
...@@ -324,9 +328,15 @@ export default class ImportMassiveModal extends React.Component { ...@@ -324,9 +328,15 @@ export default class ImportMassiveModal extends React.Component {
//Aqui va error batchrequest //Aqui va error batchrequest
GlobalActions.emitEndTask({ GlobalActions.emitEndTask({
id: 'casillamasiva' id: 'casillamasiva',
toast: {
message: 'Se han importado todas las casillas.',
title: 'Mailbox - Carga Masiva'
}
}); });
}); });
return null;
} }
render() { render() {
...@@ -339,7 +349,6 @@ export default class ImportMassiveModal extends React.Component { ...@@ -339,7 +349,6 @@ export default class ImportMassiveModal extends React.Component {
); );
} }
if (this.state.cols) { if (this.state.cols) {
const columns = this.state.cols; const columns = this.state.cols;
ul = []; ul = [];
......
...@@ -70,6 +70,8 @@ export default class ConfirmDeleteModal extends React.Component { ...@@ -70,6 +70,8 @@ export default class ConfirmDeleteModal extends React.Component {
}); });
}); });
} }
return null;
} }
render() { render() {
......
...@@ -182,6 +182,8 @@ export default class CreateMailBox extends React.Component { ...@@ -182,6 +182,8 @@ export default class CreateMailBox extends React.Component {
if (currentDomainId === domain.id) { if (currentDomainId === domain.id) {
return domain; return domain;
} }
return null;
}); });
} }
...@@ -481,5 +483,6 @@ export default class CreateMailBox extends React.Component { ...@@ -481,5 +483,6 @@ export default class CreateMailBox extends React.Component {
} }
CreateMailBox.propTypes = { CreateMailBox.propTypes = {
location: React.PropTypes.object location: React.PropTypes.object,
params: React.PropTypes.object
}; };
...@@ -92,7 +92,7 @@ export default class EditMailBox extends React.Component { ...@@ -92,7 +92,7 @@ export default class EditMailBox extends React.Component {
return false; return false;
} }
this.handleRenameAccount(mail); return this.handleRenameAccount(mail);
} }
handleRenameAccount(email) { handleRenameAccount(email) {
...@@ -139,7 +139,7 @@ export default class EditMailBox extends React.Component { ...@@ -139,7 +139,7 @@ export default class EditMailBox extends React.Component {
}); });
} }
GlobalActions.emitMessage({ return GlobalActions.emitMessage({
message: 'Error, no existe instancia de la casilla.', message: 'Error, no existe instancia de la casilla.',
typeError: messageType.ERROR typeError: messageType.ERROR
}); });
......
...@@ -132,6 +132,8 @@ export default class Mailboxes extends React.Component { ...@@ -132,6 +132,8 @@ export default class Mailboxes extends React.Component {
componentWillReceiveProps(newProps) { componentWillReceiveProps(newProps) {
const condition = this.props.location.query.page !== newProps.location.query.page; const condition = this.props.location.query.page !== newProps.location.query.page;
let domainId = null;
if (condition) { if (condition) {
const page = parseInt(newProps.location.query.page, 10) || 1; const page = parseInt(newProps.location.query.page, 10) || 1;
...@@ -142,13 +144,16 @@ export default class Mailboxes extends React.Component { ...@@ -142,13 +144,16 @@ export default class Mailboxes extends React.Component {
offset: ((page - 1) * QueryOptions.DEFAULT_LIMIT) offset: ((page - 1) * QueryOptions.DEFAULT_LIMIT)
}; };
this.getAllMailboxes(); domainId = this.props.params.domain_id;
this.getAllMailboxes(domainId);
} else { } else {
GlobalActions.emitStartLoading(); GlobalActions.emitStartLoading();
let domainId;
if (newProps.params.domain_id !== this.props.params.domain_id) { if (newProps.params.domain_id !== this.props.params.domain_id) {
domainId = newProps.params.domain_id; domainId = newProps.params.domain_id;
} }
this.getAllMailboxes(domainId); this.getAllMailboxes(domainId);
} }
} }
...@@ -221,8 +226,8 @@ export default class Mailboxes extends React.Component { ...@@ -221,8 +226,8 @@ export default class Mailboxes extends React.Component {
notMatches: true, notMatches: true,
domain: domainName domain: domainName
}); });
}).catch(() => { }).catch((error) => {
console.log('error',error); return error;
}).finally(() => { }).finally(() => {
GlobalActions.emitEndLoading(); GlobalActions.emitEndLoading();
}); });
...@@ -493,7 +498,7 @@ export default class Mailboxes extends React.Component { ...@@ -493,7 +498,7 @@ export default class Mailboxes extends React.Component {
className='form-control plans' className='form-control plans'
onChange={this.handleChangeFilter} onChange={this.handleChangeFilter}
> >
<option value=''>Todoas los planes</option> <option value=''>Todos los planes</option>
<option value='basic'>Básico</option> <option value='basic'>Básico</option>
<option value='professional'>Profesional</option> <option value='professional'>Profesional</option>
<option value='premium'>Premium</option> <option value='premium'>Premium</option>
...@@ -572,7 +577,6 @@ export default class Mailboxes extends React.Component { ...@@ -572,7 +577,6 @@ export default class Mailboxes extends React.Component {
onClick={this.handleTabChanged} onClick={this.handleTabChanged}
/> />
); );
} }
return ( return (
......
...@@ -97,7 +97,7 @@ export default class MailboxDetails extends React.Component { ...@@ -97,7 +97,7 @@ export default class MailboxDetails extends React.Component {
}); });
} }
this.setState({ return this.setState({
data: account, data: account,
alias: items, alias: items,
webmail: false webmail: false
...@@ -132,7 +132,7 @@ export default class MailboxDetails extends React.Component { ...@@ -132,7 +132,7 @@ export default class MailboxDetails extends React.Component {
}); });
} }
this.setState({ return this.setState({
data: result, data: result,
alias: items, alias: items,
webmail: false webmail: false
......
...@@ -39,12 +39,12 @@ export default class Pagination extends React.Component { ...@@ -39,12 +39,12 @@ export default class Pagination extends React.Component {
pageUrl = this.getPageQueryString(page); pageUrl = this.getPageQueryString(page);
} }
browserHistory.push(`/${this.props.url}${pageUrl}`); browserHistory.push(`${this.props.url}${pageUrl}`);
} }
handleNext(e) { handleNext(e) {
e.preventDefault(); e.preventDefault();
const page = this.getPageQueryString(this.props.currentPage + 1); const page = this.getPageQueryString(this.props.currentPage + 1);
browserHistory.push(`/${this.props.url}${page}`); browserHistory.push(`${this.props.url}${page}`);
} }
handleLast(e) { handleLast(e) {
e.preventDefault(); e.preventDefault();
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import EventStore from '../stores/event_store.jsx'; import EventStore from '../stores/event_store.jsx';
import * as GlobalActions from '../action_creators/global_actions.jsx';
export default class ProgressTask extends React.Component { export default class ProgressTask extends React.Component {
constructor(props) { constructor(props) {
......
{ {
"debug": false, "debug": true,
"zimbraUrl": "http://zimbra.zboxapp.dev:8000/service/admin/soap", "zimbraUrl": "http://zimbra.zboxapp.dev:8000/service/admin/soap",
"zimbraProxy": "https://zimbra.zboxapp.dev:7071", "zimbraProxy": "https://zimbra.zboxapp.dev:7071",
"dnsApiUrl": "http://zimbra.zboxapp.dev:3000", "dnsApiUrl": "http://zimbra.zboxapp.dev:3000",
"webMailUrl": "https://zimbra.zboxapp.dev", "webMailUrl": "https://zimbra.zboxapp.dev",
"dns": {
"url": "http://192.168.1.8:8081",
"token": "otto"
},
"plans": { "plans": {
"basic": true, "basic": true,
"premium": true, "premium": true,
"professional": true, "professional": true,
"default": false "default": false
}, },
"multiFormDomain": {
"hasMailCleaner": false,
"hasDNSZone": true
},
"webmailLifetime": 3600, "webmailLifetime": 3600,
"companiesEndPoints": { "companiesEndPoints": {
"list": "http://zimbra.zboxapp.dev:8001/list", "list": "http://zimbra.zboxapp.dev:8001/list",
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
} }
.taskboard { .taskboard {
height: 100%;
max-height: 0; max-height: 0;
overflow: hidden; overflow: hidden;
height: 100%;
transition: max-height 1s; transition: max-height 1s;
.alert { .alert {
...@@ -48,3 +48,9 @@ ...@@ -48,3 +48,9 @@
width: 100%; width: 100%;
} }
} }
.flash {
+ .progress {
margin-top: 10px;
}
}
...@@ -102,3 +102,32 @@ ...@@ -102,3 +102,32 @@
} }
} }
} }
.progress-text {
color: $white;
font-weight: bold;
text-align: center;
text-shadow: 0 1px 2px $black;
}
.progress-bar.step {
background-color: $bg-progresss-bar;
border-right: 0;
text-align: center;
&.first-step {
width: 33.33%;
}
&.second-step {
width: 66.66%;
}
&.third-step {
width: 100%;
}
}
.set-margin-up {
margin-top: 10px;
}
...@@ -93,3 +93,7 @@ $color-new-fields: #e4e5e7; ...@@ -93,3 +93,7 @@ $color-new-fields: #e4e5e7;
$bg-import-ok: rgba(78, 165, 224, .2); $bg-import-ok: rgba(78, 165, 224, .2);
$border-color-ok: #4ea5e0; $border-color-ok: #4ea5e0;
$bg-import-error: #ffe8e8; $bg-import-error: #ffe8e8;
// color ProgressBar
$bg-progresss-bar: #5bc0de;
...@@ -12,6 +12,7 @@ class DomainStoreClass extends EventEmitter { ...@@ -12,6 +12,7 @@ class DomainStoreClass extends EventEmitter {
this.current = null; this.current = null;
this.distributionListOwners = null; this.distributionListOwners = null;
this.distributionListMembers = null; this.distributionListMembers = null;
this.zoneDNS = null;
} }
getCurrent() { getCurrent() {
...@@ -241,6 +242,19 @@ class DomainStoreClass extends EventEmitter { ...@@ -241,6 +242,19 @@ class DomainStoreClass extends EventEmitter {
return false; return false;
} }
setZoneDNS(zone) {
this.zoneDNS = zone;
return this.emitZoneDNSChange(zone);
}
getZoneDNS() {
if (this.zoneDNS) {
return this.zoneDNS;
}
return null;
}
removeDistributionList(listId) { removeDistributionList(listId) {
if (this.current.lists) { if (this.current.lists) {
Reflect.deleteProperty(this.current.lists, listId); Reflect.deleteProperty(this.current.lists, listId);
...@@ -248,6 +262,18 @@ class DomainStoreClass extends EventEmitter { ...@@ -248,6 +262,18 @@ class DomainStoreClass extends EventEmitter {
this.emitDistributionListsChange(); this.emitDistributionListsChange();
} }
emitZoneDNSChange(zone) {
this.emit(eventTypes.ZONE_DNS_CHANGE_EVENT, zone);
}
addZoneDNSChangeListener(zone) {
this.on(eventTypes.ZONE_DNS_CHANGE_EVENT, zone);
}
removeZoneDNSChangeListener(zone) {
this.removeListener(eventTypes.ZONE_DNS_CHANGE_EVENT, zone);
}
emitDistributionListsChange() { emitDistributionListsChange() {
this.emit(eventTypes.DOMAIN_DLS_CHANGE_EVENT); this.emit(eventTypes.DOMAIN_DLS_CHANGE_EVENT);
} }
...@@ -259,6 +285,18 @@ class DomainStoreClass extends EventEmitter { ...@@ -259,6 +285,18 @@ class DomainStoreClass extends EventEmitter {
removeDistributionListsChangeListener(callback) { removeDistributionListsChangeListener(callback) {
this.removeListener(eventTypes.DOMAIN_DLS_CHANGE_EVENT, callback); this.removeListener(eventTypes.DOMAIN_DLS_CHANGE_EVENT, callback);
} }
emitNextStep(attrs) {
this.emit(eventTypes.NEXT_STEP_EVENT, attrs);
}
addNextStepListener(callback) {
this.on(eventTypes.NEXT_STEP_EVENT, callback);
}
removeNextStepListener(callback) {
this.removeListener(eventTypes.NEXT_STEP_EVENT, callback);
}
} }
const DomainStore = new DomainStoreClass(); const DomainStore = new DomainStoreClass();
......
...@@ -5,6 +5,7 @@ import $ from 'jquery'; ...@@ -5,6 +5,7 @@ import $ from 'jquery';
import Promise from 'bluebird'; import Promise from 'bluebird';
import ZimbraAdminApi from 'zimbra-admin-api-js'; import ZimbraAdminApi from 'zimbra-admin-api-js';
import Powerdns from 'js-powerdns';
import ZimbraStore from '../stores/zimbra_store.jsx'; import ZimbraStore from '../stores/zimbra_store.jsx';
import * as GlobalActions from '../action_creators/global_actions.jsx'; import * as GlobalActions from '../action_creators/global_actions.jsx';
...@@ -160,21 +161,19 @@ export function getAllCompanies() { ...@@ -160,21 +161,19 @@ export function getAllCompanies() {
}); });
} }
export function getCompany(id) { export function getCompany(id, success, error) {
const url = global.window.manager_config.companiesEndPoints.detail.replace('{id}', id); const url = global.window.manager_config.companiesEndPoints.detail.replace('{id}', id);
return new Promise((resolve, reject) => {
return $.ajax({ return $.ajax({
url, url,
dataType: 'json', dataType: 'json',
success: function onSuccess(data) { success: function onSuccess(data) {
resolve(data); success(data);
}, },
error: function onError(xhr, status, err) { error: function onError(xhr) {
reject(err); error(xhr.responseJSON);
} }
}); });
});
} }
export function getInvoices(id, success, error) { export function getInvoices(id, success, error) {
...@@ -665,3 +664,93 @@ export function renameAccount(account, success, error) { ...@@ -665,3 +664,93 @@ export function renameAccount(account, success, error) {
} }
); );
} }
export function initPowerDNS() {
return new Promise((resolve, reject) => {
const powerAttrs = window.manager_config.dns;
const api = new Powerdns({url: powerAttrs.url, token: powerAttrs.token});
if (api) {
return resolve(api);
}
return reject({
type: Constants.MessageType.ERROR,
message: 'PowerDNS no instanciado'
});
});
}
export function createZoneWithRecords(zoneData, records, success, error) {
initPowerDNS().then(
(api) => {
api.createZoneWithRecords(zoneData, records, (er, data) => {
if (er) {
return error(er);
}
return success(data);
});
},
(err) => {
const e = handleError('createZoneWithRecords', err);
return error(e);
}
);
}
export function getZone(domain, success, error) {
initPowerDNS().then(
(api) => {
api.getZone(domain, (er, data) => {
if (er) {
return error(er);
}
return success(data);
});
},
(err) => {
const e = handleError('getZone', err);
return error(e);
}
);
}
export function modifyOrCreateRecords(record, success, error) {
initPowerDNS().then(
(api) => {
api.modifyOrCreateRecords(record, (err, data) => {
if (err) {
const e = handleError('modifyOrCreateRecords', err);
return error(e);
}
return success(data);
});
},
(err) => {
const e = handleError('modifyOrCreateRecords', err);
return error(e);
}
);
}
export function deleteRecords(zoneUrl, record, success, error) {
initPowerDNS().then(
(api) => {
api.deleteRecords(zoneUrl, record, (err, data) => {
if (err) {
const e = handleError('deleteRecords', err);
return error(e);
}
return success(data);
});
},
(err) => {
const e = handleError('deleteRecords', err);
return error(e);
}
);
}
...@@ -31,7 +31,9 @@ export default { ...@@ -31,7 +31,9 @@ export default {
USER_CHANGE_EVENT: null, USER_CHANGE_EVENT: null,
NEW_MESSAGE_EVENT: null, NEW_MESSAGE_EVENT: null,
NEW_TOAST_EVENT: null, NEW_TOAST_EVENT: null,
MAILBOX_ADD_MASSIVE_EVENT: null MAILBOX_ADD_MASSIVE_EVENT: null,
NEXT_STEP_EVENT: null,
ZONE_DNS_CHANGE_EVENT: null
}), }),
MessageType: keyMirror({ MessageType: keyMirror({
...@@ -54,5 +56,50 @@ export default { ...@@ -54,5 +56,50 @@ export default {
MONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Juio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'], MONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Juio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
QueryOptions: { QueryOptions: {
DEFAULT_LIMIT: 10 DEFAULT_LIMIT: 10
} },
Labels: keyMirror({
name: null,
type: null,
content: null,
priority: null,
ttl: null
}),
typesOfDNS: [
'AAAA',
'AFSDB',
'CERT',
'CNAME',
'A',
'DLV',
'DNSKEY',
'DS',
'EUI48',
'EUI64',
'HINFO',
'IPSECKEY',
'KEY',
'KX',
'LOC',
'MINFO',
'MR',
'MX',
'NAPTR',
'NS',
'NSEC',
'NSEC3',
'NSEC3PARAM',
'OPT',
'PTR',
'RKEY',
'RP',
'RRSIG',
'SOA',
'SPF',
'SRV',
'SSHFP',
'TLSA',
'TSIG',
'TXT',
'WKS'
]
}; };
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