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

add, remove alias functions, modify fields for auto response form completed.

parent e762cb49
......@@ -17,6 +17,13 @@ export function emitEndLoading() {
});
}
export function emitMessage(attrs) {
AppDispatcher.handleViewAction({
type: ActionTypes.NEW_MESSAGE,
attrs
});
}
export function saveUser(user) {
AppDispatcher.handleViewAction({
type: ActionTypes.USER_CHANGED,
......
import React from 'react';
import Datalist from 'react-datalist';
import Button from '../button.jsx';
import * as Utils from '../../utils/utils.jsx';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
import Constants from '../../utils/constants.jsx';
const typeErrors = Constants.MessageType;
export default class FormAliasMailbox extends React.Component {
constructor(props) {
super(props);
this.handleDeleteAlias = this.handleDeleteAlias.bind(this);
this.sortAlias = this.sortAlias.bind(this);
this.addAlias = this.addAlias.bind(this);
this.toggleClass = 'glyphicon-sort-by-attributes';
this.asc = true;
this.state = {
alias: this.getAlias()
};
}
addAlias(e) {
e.preventDefault();
const refs = this.refs;
const newAlias = refs.alias.value + '@' + refs.domain.value;
Utils.validateInputRequired(refs).then(() => {
this.props.data.addAccountAlias(newAlias, () => {
GlobalActions.emitMessage({
message: 'Se ha agregado su nuevo Alias con éxito.',
type: typeErrors.SUCCESS
});
let alias = this.state.alias;
alias.push(newAlias);
this.setState({
alias: alias
});
}, (err) => {
GlobalActions.emitMessage({
message: err.error,
type: typeErrors.ERROR
});
});
}, (error) => {
GlobalActions.emitMessage({
message: error.message,
type: typeErrors.ERROR
});
error.node.focus();
});
}
sortAlias() {
let sort;
if (this.asc) {
sort = this.state.alias;
sort.sort().reverse();
this.setState({
alias: sort
});
this.asc = false;
this.toggleClass = 'glyphicon-sort-by-attributes';
} else {
sort = this.state.alias;
sort.sort();
this.setState({
alias: sort
});
this.asc = true;
this.toggleClass = 'glyphicon-sort-by-attributes-alt';
}
}
handleDeleteAlias(e, alias, index) {
e.preventDefault();
this.props.data.removeAccountAlias(alias, () => {
GlobalActions.emitMessage({
message: 'Se ha eliminado el alias éxitosamente.',
type: typeErrors.SUCCESS
});
const newAlias = Utils.removeIndexFromArray(this.state.alias, index);
this.setState({
alias: newAlias
});
}, (err) => {
GlobalActions.emitMessage({
message: err.error,
type: typeErrors.ERROR
});
});
}
getAlias() {
const data = this.props.data;
if (data.attrs.hasOwnProperty('zimbraMailAlias')) {
if (typeof data.attrs.zimbraMailAlias === 'string') {
return new Array(data.attrs.zimbraMailAlias);
}
return data.attrs.zimbraMailAlias.sort();
}
return [];
}
componentDidMount() {
let refs = this.refs;
refs.domain = refs.domain.refs.theInput;
refs.domain.setAttribute('data-required', 'true');
refs.domain.setAttribute('data-message', 'El dominio es necesario para crear el alias, verifiquelo por favor.');
}
render() {
let tbody;
let results;
// this bellow is just for testing porpuse
let options = ['apple', 'orange', 'pear', 'pineapple', 'melon'];
if (this.state.alias) {
tbody = this.state.alias.map((alias, i) => {
return (
<form
className='simple_form form-horizontal mailbox-form'
onSubmit={(e) => {
this.handleSubmit(e);
<tr
key={`alias-${alias}-${i}`}
>
<td>
<span>{alias}</span>
<Button
btnAttrs={{
className: 'pull-right',
title: `Borrar el siguiente Alias : ${alias}`,
onClick: (e) => {
this.handleDeleteAlias(e, alias, i);
}
}}
id='createAccount'
>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Habilitado'}
</label>
<i className='fa fa-minus-circle text-danger'></i>
</Button>
</td>
</tr>
);
});
}
<div className='col-sm-8'>
<label className='radio-inline pretty-input'>
<div className='pretty-checkbox'>
<input
type='checkbox'
className='pretty'
ref='habilitado'
/>
<span></span>
</div>
results = (
<table className='table table-striped table-bordered table-hover dataTable no-footer'>
<thead>
<tr>
<th>
{'Nombre'}
<span className='pull-right'>
<i
className={`glyphicon ${this.toggleClass} pull-right pointer`}
onClick={() => {
this.sortAlias();
}}
>
</i>
</span>
</th>
</tr>
</thead>
<tbody>
{tbody}
</tbody>
</table>
);
return (
<div className='row'>
<div className='col-xs-6'>
<div className='row'>
<form className='form-inline'>
<div className='col-xs-4'>
<div className='form-group'>
<label>
{'Mostrar'}
<select
ref='shown'
className='form-control input-sm'
>
<option value='10'>10</option>
<option value='25'>25</option>
<option value='50'>50</option>
<option value='100'>100</option>
</select>
</label>
</div>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Termina el'}
</label>
<div className='col-sm-8'>
<div className='col-xs-8 text-right'>
<label>
{'Buscar'}
<input
type='password'
className='form-control'
ref='endsAt'
id='endsAt'
type='search'
className='form-control input-sm'
ref='search'
/>
</label>
</div>
</form>
</div>
<div className='form-group string'>
<label className='string required col-sm-3 control-label'>
{'Respuesta'}
</label>
<div className='row'>
<div className='col-xs-12'>
{results}
</div>
</div>
<div className='col-sm-8'>
<textarea
name='response'
className='form-control'
id='responseBox'
rows='4'
ref='respVacaciones'
<div className='row'>
<div className='col-xs-6'>
<div className='dataTables_info'>
1 al 2 de 2 resultados
</div>
</div>
<div className='col-xs-6 text-right'>
<div className='btn-group'>
<Button
btnAttrs={
{
className: 'btn btn-default'
}
}
>
</textarea>
{'Anterior'}
</Button>
<Button
btnAttrs={
{
className: 'btn btn-default'
}
}
>
{'Siguiente'}
</Button>
</div>
</div>
<div className='form-group'>
<div className='col-xs-8 col-sm-offset-2'>
</div>
</div>
<div className='col-xs-6'>
<div className='input-group'>
<input
type='text'
ref='alias'
className='form-control'
placeholder='Alias'
data-required='true'
data-message='El alias es requerido, compruebelo por favor'
/>
<span className='input-group-addon'>
@
</span>
<Datalist
list='domains'
options={options}
className='form-control'
id='domain'
ref='domain'
placeholder='Dominio'
/>
<span className='input-group-btn'>
<Button
btnAttrs={
{
className: 'btn btn-info',
onClick: () => {
this.handleSaveAutoResp();
className: 'btn btn-default',
onClick: (e) => {
this.addAlias(e);
}
}
}
>
{'Cancelar'}
Agregar alias
</Button>
</span>
</div>
</div>
</div>
</form>
);
}
}
FormAliasMailbox.propTypes = {
data: React.PropTypes.object
};
import React from 'react';
import Button from '../button.jsx';
import DateTimeField from 'react-bootstrap-datetimepicker';
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
import Constants from '../../utils/constants.jsx';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
const messageType = Constants.MessageType;
export default class FormVacacionesMailbox extends React.Component {
constructor(props) {
......@@ -9,7 +17,43 @@ export default class FormVacacionesMailbox extends React.Component {
}
handleSaveAutoResp() {
console.log('save'); //eslint-disable-line no-console
const data = this.props.data;
const refs = this.refs;
let enabled = refs.zimbraPrefOutOfOfficeReplyEnabled.checked.toString().toUpperCase();
let formated = document.getElementById('zimbraPrefOutOfOfficeUntilDate').value.split('/').reverse().join('') + '000000Z';
let attrs = {
zimbraPrefOutOfOfficeReplyEnabled: enabled,
zimbraPrefOutOfOfficeUntilDate: formated,
zimbraPrefOutOfOfficeReply: refs.zimbraPrefOutOfOfficeReply.value
};
Client.modifyAccount(data.id, attrs, () => {
GlobalActions.emitMessage({
message: 'Se ha modificado con éxito',
type: messageType.SUCCESS
});
}, (error) => {
GlobalActions.emitMessage({
message: error.message,
type: messageType.ERROR
});
});
}
componentDidMount() {
const data = this.props.data.attrs;
if (data.hasOwnProperty('zimbraPrefOutOfOfficeReplyEnabled')) {
this.refs.zimbraPrefOutOfOfficeReplyEnabled.checked = data.zimbraPrefOutOfOfficeReplyEnabled.toString().toLowerCase() === 'true';
}
if (data.hasOwnProperty('zimbraPrefOutOfOfficeUntilDate')) {
document.getElementById('zimbraPrefOutOfOfficeUntilDate').value = Utils.dateFormatted(data.zimbraPrefOutOfOfficeUntilDate, true, '/');
}
if (data.hasOwnProperty('zimbraPrefOutOfOfficeReply')) {
this.refs.zimbraPrefOutOfOfficeReply.value = data.zimbraPrefOutOfOfficeReply;
}
}
render() {
......@@ -32,7 +76,7 @@ export default class FormVacacionesMailbox extends React.Component {
<input
type='checkbox'
className='pretty'
ref='habilitado'
ref='zimbraPrefOutOfOfficeReplyEnabled'
/>
<span></span>
</div>
......@@ -46,11 +90,14 @@ export default class FormVacacionesMailbox extends React.Component {
</label>
<div className='col-sm-8'>
<input
type='password'
className='form-control'
ref='endsAt'
id='endsAt'
<DateTimeField
inputFormat='DD/MM/YYYY'
inputProps={
{
id: 'zimbraPrefOutOfOfficeUntilDate',
readOnly: 'readOnly'
}
}
/>
</div>
</div>
......@@ -66,7 +113,7 @@ export default class FormVacacionesMailbox extends React.Component {
id='responseBox'
className='form-control'
rows='4'
ref='respVacaciones'
ref='zimbraPrefOutOfOfficeReply'
>
</textarea>
</div>
......@@ -84,7 +131,7 @@ export default class FormVacacionesMailbox extends React.Component {
}
}
>
{'Cancelar'}
{'Guardar'}
</Button>
</div>
</div>
......@@ -92,3 +139,10 @@ export default class FormVacacionesMailbox extends React.Component {
);
}
}
FormVacacionesMailbox.propTypes = {
data: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.string
])
};
......@@ -204,7 +204,7 @@ export default class Mailboxes extends React.Component {
}
}}
>
{attrs.mail}
{mail.name}
</Button>
</td>
......
......@@ -4,6 +4,8 @@
import $ from 'jquery';
import React from 'react';
import EventStore from '../../stores/event_store.jsx';
import PageInfo from '../page_info.jsx';
import PanelTab from '../panel_tab.jsx';
import Panel from '../panel.jsx';
......@@ -13,6 +15,7 @@ import FormVacacionesMailbox from './form_resp_vacaciones_mailbox.jsx';
import FormAliasMailbox from './form_alias_mailbox.jsx';
import ChangePasswordModal from './change_passwd_modal.jsx';
import ToggleModalButton from '../toggle_modal_button.jsx';
import MessageBar from '../message_bar.jsx';
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
......@@ -24,6 +27,7 @@ export default class MailboxDetails extends React.Component {
this.getMailbox = this.getMailbox.bind(this);
this.handleEdit = this.handleEdit.bind(this);
this.showMessage = this.showMessage.bind(this);
this.state = {};
}
......@@ -32,6 +36,14 @@ export default class MailboxDetails extends React.Component {
Utils.handleLink(e, path, location);
}
showMessage(attrs) {
this.setState({
error: attrs.message,
type: attrs.type.toLowerCase(),
autocloseInSecs: 10
});
}
getMailbox() {
const id = this.props.params.id;
Utils.toggleStatusButtons('.action-info-btns', true);
......@@ -55,11 +67,13 @@ export default class MailboxDetails extends React.Component {
}
componentDidMount() {
EventStore.addMessageListener(this.showMessage);
$('#sidebar-mailboxes').addClass('active');
this.getMailbox();
}
componentWillUnmount() {
EventStore.removeMessageListener(this.showMessage);
$('#sidebar-mailboxes').removeClass('active');
}
......@@ -68,6 +82,18 @@ export default class MailboxDetails extends React.Component {
let statsData;
let btnsGeneralInfo = [];
let btnsStats = [];
let panelTabs;
let message;
if (this.state.error) {
message = (
<MessageBar
message={this.state.error}
type={this.state.type}
autoclose={true}
/>
);
}
if (this.state.data) {
generalData = (
......@@ -118,32 +144,15 @@ export default class MailboxDetails extends React.Component {
label: 'Ver Correos'
}
];
}
const pageInfo = (
<PageInfo
titlePage='Casillas'
descriptionPage='Usuarios de correo electrónico.'
/>
);
if (this.state.notFound) {
return (
<div>
{pageInfo}
<div className='block-center text-center'>
<h3>{this.state.message}</h3>
</div>
</div>
);
}
const formAutoResp = (
<FormVacacionesMailbox/>
<FormVacacionesMailbox data={this.state.data}/>
);
const formAlias = (
<FormAliasMailbox/>
<FormAliasMailbox
data={this.state.data}
/>
);
const tabAdmin = (
......@@ -157,11 +166,12 @@ export default class MailboxDetails extends React.Component {
<Panel
title='Casillas'
hasHeader={false}
classHeader={'reset-panel'}
children={formAlias}
/>
);
const panelTabs = (
panelTabs = (
<PanelTab
tabNames={['Resp Vacaciones', 'Alias']}
tabs={{
......@@ -171,10 +181,30 @@ export default class MailboxDetails extends React.Component {
location={this.props.location}
/>
);
}
const pageInfo = (
<PageInfo
titlePage='Casillas'
descriptionPage='Usuarios de correo electrónico.'
/>
);
if (this.state.notFound) {
return (
<div>
{pageInfo}
<div className='block-center text-center'>
<h3>{this.state.message}</h3>
</div>
</div>
);
}
return (
<div>
{pageInfo}
{message}
<div className='content animate-panel'>
<div className='row'>
<div className='col-md-6 central-content'>
......
{
"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",
......
......@@ -1266,6 +1266,18 @@ label {
text-align: center;
}
&.reset-panel {
margin: 0;
.panel-body {
padding: 0;
.btn {
margin: 0;
}
}
}
&.with-min-height {
.panel-body {
min-height: 200px;
......@@ -1612,3 +1624,7 @@ label {
}
}
}
.pointer {
cursor: pointer;
}
......@@ -32,6 +32,18 @@ class EventStoreClass extends EventEmitter {
removeEndLoadingListener(callback) {
this.removeListener(eventTypes.END_LOADING_EVENT, callback);
}
emitMessage(attrs) {
this.emit(eventTypes.NEW_MESSAGE_EVENT, attrs);
}
addMessageListener(callback) {
this.on(eventTypes.NEW_MESSAGE_EVENT, callback);
}
removeMessageListener(callback) {
this.removeListener(eventTypes.NEW_MESSAGE_EVENT, callback);
}
}
var EventStore = new EventStoreClass();
......@@ -47,6 +59,9 @@ EventStore.dispatchToken = AppDispatcher.register((payload) => {
case ActionTypes.END_LOADING:
EventStore.emitEndLoading();
break;
case ActionTypes.NEW_MESSAGE:
EventStore.emitMessage(action.attrs);
break;
default:
}
});
......
......@@ -362,3 +362,22 @@ export function getDnsInfo(domain, success, error) {
}
});
}
export function addAccountAlias(alias, success, error) {
initZimbra().then(
(zimbra) => {
zimbra.addAccountAlias(alias, (err, data) => {
if (err) {
const e = handleError('addAccountAlias', err);
return error(e);
}
return success(data);
});
},
(err) => {
const e = handleError('addAccountAlias', err);
return error(e);
}
);
}
......@@ -8,7 +8,8 @@ export default {
START_LOADING: null,
END_LOADING: null,
USER_CHANGED: null,
RECEIVED_ERROR: null
RECEIVED_ERROR: null,
NEW_MESSAGE: null
}),
PayloadSources: keyMirror({
......@@ -21,7 +22,14 @@ export default {
DOMAIN_DLS_CHANGE_EVENT: null,
START_LOADING_EVENT: null,
END_LOADING_EVENT: null,
USER_CHANGE_EVENT: null
USER_CHANGE_EVENT: null,
NEW_MESSAGE_EVENT: null
}),
MessageType: keyMirror({
SUCCESS: null,
WARNING: null,
ERROR: null
}),
ZimbraCodes: {
......
......@@ -204,16 +204,26 @@ export function toggleStatusButtons(classNames, isDisabled) {
}
}
export function dateFormatted(dateString) {
export function dateFormatted(dateString, isShortDate, separator) {
if (typeof dateString === 'string') {
const date = dateString.substr(0, 8);
const year = date.substr(0, 4);
const month = parseInt(date.substr(4, 2), 10);
const month = (isShortDate) ? date.substr(4, 2) : parseInt(date.substr(4, 2), 10);
const day = date.substr(6, 2);
const dateFormattedString = `${day} de ${CONSTANTS.MONTHS[month - 1]} de ${year}`;
let dateFormattedString = `${day} de ${CONSTANTS.MONTHS[month - 1]} de ${year}`;
if (isShortDate) {
dateFormattedString = `${day}${separator}${month}${separator}${year}`;
}
return dateFormattedString;
}
return false;
}
export function removeIndexFromArray(array, index, pos) {
array.splice(index, pos || 1);
return array;
}
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