Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Z
zimbra-admin-api-js
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Public
zimbra-admin-api-js
Commits
77e7ab21
Commit
77e7ab21
authored
Apr 20, 2016
by
enahum
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #23 from ZBoxApp/mailboxes
Mailboxes
parents
80a00639
4c27872c
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
775 additions
and
158 deletions
+775
-158
create_mailbox.jsx
src/components/mailbox/create_mailbox.jsx
+106
-46
edit_mailbox.jsx
src/components/mailbox/edit_mailbox.jsx
+183
-44
mailbox.jsx
src/components/mailbox/mailbox.jsx
+267
-43
pagination.jsx
src/components/pagination.jsx
+14
-6
panel.jsx
src/components/panel.jsx
+2
-2
panel_tab.jsx
src/components/panel_tab.jsx
+12
-4
index.jsx
src/index.jsx
+19
-13
tab_state_store.jsx
src/stores/tab_state_store.jsx
+22
-0
client.jsx
src/utils/client.jsx
+95
-0
utils.jsx
src/utils/utils.jsx
+55
-0
No files found.
src/components/mailbox/create_mailbox.jsx
View file @
77e7ab21
import
$
from
'jquery'
;
import
React
from
'react'
;
import
{
browserHistory
}
from
'react-router'
;
import
Panel
from
'../panel.jsx'
;
import
Button
from
'../button.jsx'
;
import
MessageBar
from
'../message_bar.jsx'
;
import
*
as
GlobalActions
from
'../../action_creators/global_actions.jsx'
;
import
*
as
Client
from
'../../utils/client.jsx'
;
import
*
as
Utils
from
'../../utils/utils.jsx'
;
export
default
class
CreateMailBox
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
handleClick
=
this
.
handleClick
.
bind
(
this
);
this
.
handleSubmit
=
this
.
handleSubmit
.
bind
(
this
);
this
.
state
=
{};
}
this
.
state
=
{
notification
:
false
,
notificationMsg
:
''
handleSubmit
(
e
)
{
e
.
preventDefault
();
Utils
.
validateInputRequired
(
this
.
refs
).
then
(()
=>
{
// here assign missing properties.
let
attrs
=
{
givenName
:
this
.
refs
.
givenName
.
value
,
sn
:
this
.
refs
.
sn
.
value
};
Client
.
createAccount
(
this
.
refs
.
mail
.
value
,
this
.
refs
.
mail
.
passwd
,
attrs
,
(
data
)
=>
{
// reset form when all is ok
document
.
getElementById
(
'createAccount'
).
reset
();
this
.
setState
(
{
error
:
`Su cuenta
${
data
.
name
}
ha sido creada con èxito.`
,
typeError
:
'success'
}
);
},
(
error
)
=>
{
this
.
setState
(
{
error
:
error
.
message
,
typeError
:
'warning'
}
);
}
);
}).
catch
((
err
)
=>
{
this
.
setState
(
{
error
:
err
.
message
,
typeError
:
err
.
typeError
}
);
err
.
node
.
focus
();
});
}
componentDidMount
()
{
$
(
'#selectDomains'
).
select2
({
/*
$('#selectDomains').select2({
placeholder: 'Por favor, introduzca 3 caracteres.',
allowClear: true
});
}
});*/
handleClick
(
e
,
path
)
{
e
.
preventDefault
();
$
(
'#sidebar-mailboxes'
).
addClass
(
'active'
);
GlobalActions
.
emitEndLoading
();
}
browserHistory
.
push
(
path
);
componentWillUnmount
()
{
$
(
'#sidebar-mailboxes'
).
removeClass
(
'active'
);
}
render
()
{
let
message
;
if
(
this
.
state
.
error
)
{
message
=
(
<
MessageBar
message=
{
this
.
state
.
error
}
type=
{
this
.
state
.
typeError
}
autoclose=
{
true
}
/>
);
}
let
form
=
(
<
form
className=
'simple_form form-horizontal mailbox-form'
>
<
form
className=
'simple_form form-horizontal mailbox-form'
onSubmit=
{
(
e
)
=>
{
this
.
handleSubmit
(
e
);
}
}
id=
'createAccount'
>
<
div
className=
'form-group string required'
>
<
label
className=
'string required col-sm-3 control-label'
>
<
abbr
title=
'requerido'
>
{
'*'
}
</
abbr
>
...
...
@@ -42,9 +107,9 @@ export default class CreateMailBox extends React.Component {
<
div
className=
'col-xs-6'
>
<
input
type=
'text'
required=
'required'
className=
'form-control'
ref=
'address'
ref=
'mail'
data
-
required=
'true'
/>
</
div
>
<
div
className=
'col-xs-6'
>
...
...
@@ -71,7 +136,7 @@ export default class CreateMailBox extends React.Component {
<
input
type=
'text'
className=
'form-control'
ref=
'
n
ame'
ref=
'
givenN
ame'
/>
</
div
>
</
div
>
...
...
@@ -85,7 +150,7 @@ export default class CreateMailBox extends React.Component {
<
input
type=
'text'
className=
'form-control'
ref=
'
lastname
'
ref=
'
sn
'
/>
</
div
>
</
div
>
...
...
@@ -104,25 +169,6 @@ export default class CreateMailBox extends React.Component {
</
div
>
</
div
>
<
div
className=
'form-group string'
>
<
label
className=
'string required col-sm-3 control-label'
>
{
'Chat'
}
</
label
>
<
div
className=
'col-sm-8'
>
<
label
className=
'radio-inline pretty-input'
>
<
div
className=
'pretty-checkbox'
>
<
input
type=
'checkbox'
className=
'pretty'
ref=
'hasChat'
/>
<
span
></
span
>
</
div
>
</
label
>
</
div
>
</
div
>
<
div
className=
'form-group string'
>
<
label
className=
'string required col-sm-3 control-label'
>
{
'Administrador delegado'
}
...
...
@@ -134,7 +180,7 @@ export default class CreateMailBox extends React.Component {
<
input
type=
'checkbox'
className=
'pretty'
ref=
'
isAdministrator
'
ref=
'
zimbraIsDelegatedAdminAccount
'
/>
<
span
></
span
>
</
div
>
...
...
@@ -200,6 +246,7 @@ export default class CreateMailBox extends React.Component {
<
input
type=
'password'
className=
'form-control'
data
-
required=
'true'
ref=
'passwd'
/>
</
div
>
...
...
@@ -218,7 +265,7 @@ export default class CreateMailBox extends React.Component {
{
className
:
'btn btn-default'
,
onClick
:
(
e
)
=>
{
this
.
handleClick
(
e
,
'/mailboxes'
);
Utils
.
handleLink
(
e
,
'/mailboxes'
,
this
.
props
.
location
);
}
}
}
...
...
@@ -236,13 +283,18 @@ export default class CreateMailBox extends React.Component {
props
:
{
className
:
'btn btn-default btn-xs'
,
onClick
:
(
e
)
=>
{
this
.
handleClick
(
e
,
'/mailboxes'
);
Utils
.
handleLink
(
e
,
'/mailboxes'
,
this
.
props
.
location
);
}
}
}
];
return
(
<
div
>
{
message
}
<
div
className=
'content animate-panel'
>
<
div
className=
'row'
>
<
div
className=
'col-md-12 central-content'
>
<
Panel
title=
{
'Agregar Casilla'
}
btnsHeader=
{
actions
}
...
...
@@ -250,6 +302,14 @@ export default class CreateMailBox extends React.Component {
>
{
form
}
</
Panel
>
</
div
>
</
div
>
</
div
>
</
div
>
);
}
}
CreateMailBox
.
propTypes
=
{
location
:
React
.
PropTypes
.
object
};
src/components/mailbox/edit_mailbox.jsx
View file @
77e7ab21
//import $ from 'jquery';
//import select2 from 'select2';
import
$
from
'jquery'
;
import
React
from
'react'
;
import
{
browserHistory
}
from
'react-router'
;
import
Panel
from
'../panel.jsx'
;
import
Button
from
'../button.jsx'
;
import
MessageBar
from
'../message_bar.jsx'
;
import
*
as
Client
from
'../../utils/client.jsx'
;
import
*
as
GlobalActions
from
'../../action_creators/global_actions.jsx'
;
import
*
as
Utils
from
'../../utils/utils.jsx'
;
export
default
class
EditMailBox
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
handleClick
=
this
.
handleClick
.
bind
(
this
);
this
.
handleClickDelete
=
this
.
handleClickDelete
.
bind
(
this
);
this
.
handleEdit
=
this
.
handleEdit
.
bind
(
this
);
this
.
handleRadioChanged
=
this
.
handleRadioChanged
.
bind
(
this
);
this
.
handleDelete
=
this
.
handleDelete
.
bind
(
this
);
this
.
getMailbox
=
this
.
getMailbox
.
bind
(
this
);
this
.
fillForm
=
this
.
fillForm
.
bind
(
this
);
this
.
state
=
{
notification
:
false
,
notificationMsg
:
''
data
:
false
};
}
handleClick
(
e
,
path
)
{
handleRadioChanged
(
val
)
{
this
.
refs
.
plan
.
value
=
val
;
}
handleEdit
(
e
)
{
e
.
preventDefault
();
Utils
.
toggleStatusButtons
(
'.action-button'
,
true
);
Utils
.
validateInputRequired
(
this
.
refs
).
then
(()
=>
{
let
isAdmin
=
(
this
.
refs
.
zimbraIsDelegatedAdminAccount
.
checked
===
true
).
toString
().
toUpperCase
();
let
attrs
=
{
givenName
:
this
.
refs
.
givenName
.
value
,
sn
:
this
.
refs
.
sn
.
value
,
zimbraIsDelegatedAdminAccount
:
isAdmin
};
Client
.
modifyAccount
(
this
.
state
.
data
.
id
,
attrs
,
(
data
)
=>
{
Utils
.
toggleStatusButtons
(
'.action-button'
,
false
);
this
.
setState
(
{
error
:
`Su cuenta
${
data
.
name
}
ha sido modificada con èxito.`
,
typeError
:
'success'
,
data
:
data
}
);
},
(
error
)
=>
{
this
.
setState
(
{
error
:
error
.
message
,
typeError
:
'warning'
}
);
Utils
.
toggleStatusButtons
(
'.action-button'
,
false
);
}
);
}).
catch
((
err
)
=>
{
this
.
setState
(
{
error
:
err
.
message
,
typeError
:
err
.
typeError
}
);
browserHistory
.
push
(
path
);
err
.
node
.
focus
();
Utils
.
toggleStatusButtons
(
'.action-button'
,
false
);
});
}
handleClickDelete
(
e
)
{
getMailbox
(
id
)
{
Client
.
getAccount
(
id
,
(
data
)
=>
{
this
.
setState
({
data
});
GlobalActions
.
emitEndLoading
();
},
(
error
)
=>
{
this
.
setState
({
error
:
error
.
message
});
GlobalActions
.
emitEndLoading
();
}
);
}
componentDidMount
()
{
$
(
'#sidebar-mailboxes'
).
addClass
(
'active'
);
GlobalActions
.
emitEndLoading
();
this
.
getMailbox
(
this
.
props
.
params
.
id
);
}
componentWillUnmount
()
{
$
(
'#sidebar-mailboxes'
).
removeClass
(
'active'
);
}
handleDelete
(
e
)
{
e
.
preventDefault
();
Client
.
removeAccount
(
this
.
state
.
data
.
id
,
(
data
)
=>
{
console
.
log
(
'success'
,
data
);
//eslint-disable-line no-console
},
(
error
)
=>
{
console
.
log
(
'error'
,
error
);
//eslint-disable-line no-console
}
);
}
fillForm
()
{
let
attrs
=
this
.
state
.
data
.
attrs
;
this
.
refs
.
mail
.
value
=
this
.
state
.
data
.
name
;
this
.
refs
.
givenName
.
value
=
attrs
.
givenName
||
''
;
this
.
refs
.
sn
.
value
=
attrs
.
sn
;
this
.
refs
.
description
.
value
=
attrs
.
description
||
''
;
this
.
refs
.
zimbraIsDelegatedAdminAccount
.
checked
=
attrs
.
zimbraIsDelegatedAdminAccount
===
'true'
;
}
render
()
{
let
message
;
if
(
this
.
state
.
error
)
{
message
=
(
<
MessageBar
message=
{
this
.
state
.
error
}
type=
{
this
.
state
.
typeError
}
autoclose=
{
true
}
/>
);
}
if
(
this
.
state
.
data
)
{
this
.
fillForm
();
}
let
form
=
(
<
form
className=
'simple_form form-horizontal mailbox-form'
>
<
form
className=
'simple_form form-horizontal mailbox-form'
id=
'editAccount'
onSubmit=
{
(
e
)
=>
{
this
.
handleEdit
(
e
);
}
}
>
<
div
className=
'form-group string required'
>
<
label
className=
'string required col-sm-3 control-label'
>
<
abbr
title=
'requerido'
>
{
'*'
}
</
abbr
>
...
...
@@ -42,8 +161,10 @@ export default class EditMailBox extends React.Component {
<
div
className=
'col-xs-6'
>
<
input
type=
'text'
required=
'required'
className=
'form-control'
ref=
'mail'
data
-
required=
'true'
data
-
message=
'El campo direccion es requerido, verifique por favor.'
/>
</
div
>
<
div
className=
'col-xs-6'
>
...
...
@@ -52,6 +173,7 @@ export default class EditMailBox extends React.Component {
<
select
className=
'form-control'
id=
'selectDomains'
ref=
'domain'
>
</
select
>
</
div
>
...
...
@@ -69,6 +191,7 @@ export default class EditMailBox extends React.Component {
<
input
type=
'text'
className=
'form-control'
ref=
'givenName'
/>
</
div
>
</
div
>
...
...
@@ -82,6 +205,7 @@ export default class EditMailBox extends React.Component {
<
input
type=
'text'
className=
'form-control'
ref=
'sn'
/>
</
div
>
</
div
>
...
...
@@ -95,28 +219,11 @@ export default class EditMailBox extends React.Component {
<
input
type=
'text'
className=
'form-control'
ref=
'description'
/>
</
div
>
</
div
>
<
div
className=
'form-group string'
>
<
label
className=
'string required col-sm-3 control-label'
>
{
'Chat'
}
</
label
>
<
div
className=
'col-sm-8'
>
<
label
className=
'radio-inline pretty-input'
>
<
div
className=
'pretty-checkbox'
>
<
input
type=
'checkbox'
className=
'pretty'
/>
<
span
></
span
>
</
div
>
</
label
>
</
div
>
</
div
>
<
div
className=
'form-group string'
>
<
label
className=
'string required col-sm-3 control-label'
>
{
'Administrador delegado'
}
...
...
@@ -128,6 +235,7 @@ export default class EditMailBox extends React.Component {
<
input
type=
'checkbox'
className=
'pretty'
ref=
'zimbraIsDelegatedAdminAccount'
/>
<
span
></
span
>
</
div
>
...
...
@@ -148,6 +256,9 @@ export default class EditMailBox extends React.Component {
type=
'radio'
className=
'pretty'
name=
'mailbox'
onChange=
{
()
=>
{
this
.
handleRadioChanged
(
'basica'
);
}
}
/>
<
span
></
span
>
</
div
>
...
...
@@ -157,9 +268,12 @@ export default class EditMailBox extends React.Component {
<
label
className=
'radio radio-info radio-inline pretty-input'
>
<
div
className=
'pretty-radio'
>
<
input
type=
'radio'
className=
'pretty'
name=
'mailbox'
type=
'radio'
onChange=
{
()
=>
{
this
.
handleRadioChanged
(
'profesional'
);
}
}
/>
<
span
></
span
>
</
div
>
...
...
@@ -172,11 +286,21 @@ export default class EditMailBox extends React.Component {
type=
'radio'
className=
'pretty'
name=
'mailbox'
onChange=
{
()
=>
{
this
.
handleRadioChanged
(
'premium'
);
}
}
/>
<
span
></
span
>
</
div
>
{
'Premium'
}
</
label
>
<
input
type=
'hidden'
ref=
'plan'
data
-
required=
'true'
data
-
message=
'El plan de su cuenta es requerido, por favor verificar.'
/>
</
div
>
</
div
>
...
...
@@ -186,14 +310,15 @@ export default class EditMailBox extends React.Component {
type=
'submit'
name=
'commit'
value=
'Guardar'
className=
'btn btn-primary'
className=
'btn btn-primary action-button'
id=
'modifyButton'
/>
<
Button
btnAttrs=
{
{
className
:
'btn btn-default'
,
className
:
'btn btn-default
action-button
'
,
onClick
:
(
e
)
=>
{
this
.
handleClick
(
e
,
'/mailboxes'
);
Utils
.
handleLink
(
e
,
'/mailboxes'
,
this
.
props
.
location
);
}
}
}
...
...
@@ -209,24 +334,29 @@ export default class EditMailBox extends React.Component {
{
label
:
'Cancelar'
,
props
:
{
className
:
'btn btn-default btn-xs'
,
className
:
'btn btn-default btn-xs
action-button
'
,
onClick
:
(
e
)
=>
{
this
.
handleClick
(
e
,
'/mailboxes'
);
Utils
.
handleLink
(
e
,
'/mailboxes'
,
this
.
props
.
location
);
}
}
},
{
label
:
'Eliminar'
,
props
:
{
className
:
'btn btn-danger btn-xs'
,
className
:
'btn btn-danger btn-xs
action-button
'
,
onClick
:
(
e
)
=>
{
this
.
handle
ClickDelete
(
e
,
'/mailboxes/delete/1'
);
this
.
handle
Delete
(
e
);
}
}
}
];
return
(
<
div
>
{
message
}
<
div
className=
'content animate-panel'
>
<
div
className=
'row'
>
<
div
className=
'col-md-12 central-content'
>
<
Panel
title=
{
'Editar Casilla'
}
btnsHeader=
{
actions
}
...
...
@@ -234,6 +364,15 @@ export default class EditMailBox extends React.Component {
>
{
form
}
</
Panel
>
</
div
>
</
div
>
</
div
>
</
div
>
);
}
}
EditMailBox
.
propTypes
=
{
location
:
React
.
PropTypes
.
object
,
params
:
React
.
PropTypes
.
any
};
src/components/mailbox/mailbox.jsx
View file @
77e7ab21
...
...
@@ -4,25 +4,46 @@
import
$
from
'jquery'
;
import
React
from
'react'
;
import
{
browserHistory
}
from
'react-router'
;
import
Button
from
'../button.jsx'
;
import
MessageBar
from
'../message_bar.jsx'
;
import
PageInfo
from
'../page_info.jsx'
;
import
Panel
from
'../panel.jsx'
;
import
PanelTab
from
'../panel_tab.jsx'
;
import
Pagination
from
'../pagination.jsx'
;
import
statusLabel
from
'../status_label.jsx'
;
import
*
as
Client
from
'../../utils/client.jsx'
;
import
*
as
GlobalActions
from
'../../action_creators/global_actions.jsx'
;
import
Constants
from
'../../utils/constants.jsx'
;
import
*
as
Utils
from
'../../utils/utils.jsx'
;
const
QueryOptions
=
Constants
.
QueryOptions
;
export
default
class
Account
s
extends
React
.
Component
{
export
default
class
Mailboxe
s
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
handleEdit
=
this
.
handleEdit
.
bind
(
this
);
this
.
getMailboxes
=
this
.
getMailboxes
.
bind
(
this
);
this
.
handleAddMailbox
=
this
.
handleAddMailbox
.
bind
(
this
);
this
.
handleExportAsCSV
=
this
.
handleExportAsCSV
.
bind
(
this
);
this
.
handleTabChanged
=
this
.
handleTabChanged
.
bind
(
this
);
const
page
=
parseInt
(
this
.
props
.
location
.
query
.
page
,
10
)
||
1
;
this
.
state
=
{
data
:
null
page
,
offset
:
((
page
-
1
)
*
QueryOptions
.
DEFAULT_LIMIT
)
};
this
.
handleLink
=
this
.
handleLink
.
bind
(
this
);
this
.
getMailboxes
=
this
.
getMailboxes
.
bind
(
this
);
}
getMailboxes
()
{
Client
.
getAllDomains
(
Client
.
getAllAccounts
(
{
limit
:
QueryOptions
.
DEFAULT_LIMIT
,
offset
:
this
.
state
.
offset
},
(
data
)
=>
{
this
.
setState
({
data
...
...
@@ -38,65 +59,268 @@ export default class Accounts extends React.Component {
);
}
handleAddMailbox
(
e
,
path
)
{
e
.
preventDefault
();
if
((
this
.
props
.
location
.
basename
+
this
.
props
.
location
.
pathname
)
!==
path
)
{
browserHistory
.
push
(
path
);
GlobalActions
.
emitStartLoading
();
}
}
handleExportAsCSV
(
e
)
{
e
.
preventDefault
();
}
handleTabChanged
(
tab
)
{
browserHistory
.
push
(
this
.
props
.
location
.
pathname
+
'?tab='
+
tab
);
}
componentWillReceiveProps
(
newProps
)
{
if
(
this
.
props
.
location
.
query
.
page
!==
newProps
.
location
.
query
.
page
)
{
const
page
=
parseInt
(
newProps
.
location
.
query
.
page
,
10
)
||
1
;
GlobalActions
.
emitStartLoading
();
this
.
state
=
{
page
,
offset
:
((
page
-
1
)
*
QueryOptions
.
DEFAULT_LIMIT
)
};
this
.
getMailboxes
();
}
}
componentDidMount
()
{
$
(
'#sidebar-
account
s'
).
addClass
(
'active'
);
GlobalActions
.
emitEndLoading
();
$
(
'#sidebar-
mailboxe
s'
).
addClass
(
'active'
);
this
.
getMailboxes
();
}
componentWillUnmount
()
{
$
(
'#sidebar-
account
s'
).
removeClass
(
'active'
);
$
(
'#sidebar-
mailboxe
s'
).
removeClass
(
'active'
);
}
handle
Link
(
e
,
path
)
{
handle
Edit
(
e
,
path
)
{
e
.
preventDefault
();
if
((
this
.
props
.
location
.
basename
+
this
.
props
.
location
.
pathname
)
!==
path
)
{
GlobalActions
.
emitStartLoading
();
browserHistory
.
push
(
path
);
}
}
render
()
{
const
addMailBoxButton
=
[{
label
:
'+ Agregar Casilla'
,
props
:
{
className
:
'btn btn-success'
,
let
message
;
let
panelTabs
;
if
(
this
.
state
.
error
)
{
message
=
(
<
MessageBar
message=
{
this
.
state
.
error
}
type=
'success'
autoclose=
{
true
}
/>
);
}
let
tableResults
;
let
total
=
0
;
let
arrLocked
=
[];
if
(
this
.
state
.
data
)
{
total
=
this
.
state
.
data
.
account
.
length
;
tableResults
=
this
.
state
.
data
.
account
.
map
((
mail
)
=>
{
let
attrs
=
mail
.
attrs
;
let
statusClass
=
''
;
let
status
=
attrs
.
zimbraAccountStatus
;
let
id
=
mail
.
id
;
switch
(
status
)
{
case
'locked'
:
statusClass
=
'label label-warning'
;
status
=
'Bloqueada'
;
arrLocked
.
push
(
mail
);
break
;
default
:
statusClass
=
'label label-success'
;
status
=
'Activa'
;
break
;
}
return
(
<
tr
key=
{
id
}
className=
{
'mailbox-row'
}
id=
{
id
}
>
<
td
className=
{
'mailbox-name'
}
>
<
statusLabel
className=
{
statusClass
}
>
{
status
}
</
statusLabel
>
{
attrs
.
mail
}
</
td
>
<
td
className=
{
'mailbox-displayname'
}
>
{
mail
.
name
}
</
td
>
<
td
className=
{
'mailbox-cos-plan'
}
>
<
statusLabel
className=
{
'label-plan label-unknown'
}
>
unknown
</
statusLabel
>
</
td
>
<
td
>
<
Button
btnAttrs=
{
{
className
:
'btn btn-xs btn-default'
,
onClick
:
(
e
)
=>
{
this
.
handleLink
(
e
,
'/mailboxes/new'
);
this
.
handleEdit
(
e
,
'/mailboxes/'
+
attrs
.
mail
+
'/edit'
);
}
}
}
}];
>
{
'Editar'
}
</
Button
>
</
td
>
</
tr
>
);
});
const
panelBody
=
(
<
div
className=
'center-block text-center'
>
<
h5
>
{
'Sin resultados para su busqueda.'
}
</
h5
>
<
div
key=
'mailboxes-body'
id=
'index-mailboxes-table'
className=
'table-responsive'
>
<
table
id=
'index-domains'
cellPadding=
'1'
cellSpacing=
'1'
className=
'table table-condensed table-striped vertical-align index-mailbox-table'
>
<
thead
>
<
tr
>
<
th
>
{
'Email'
}
</
th
>
<
th
className=
'td-mbxs text-left'
>
{
'Nombre'
}
</
th
>
<
th
className=
'text-center text-center'
>
{
'Tipo'
}
</
th
>
<
th
className=
'text-center text-center'
>
{
'Acciones'
}
</
th
>
</
tr
>
</
thead
>
<
tbody
>
{
tableResults
}
</
tbody
>
</
table
>
</
div
>
);
const
pageInfo
=
(
<
PageInfo
titlePage=
'Casillas'
descriptionPage=
'Las casillas ...'
const
todas
=
`Todas (
${
total
}
)`
;
const
archiving
=
'Archiving'
;
const
noPlan
=
`Sin Plan (
${
total
}
)`
;
const
locked
=
`Bloqueada (
${
arrLocked
.
length
}
)`
;
const
arrTabNames
=
[
todas
,
archiving
,
noPlan
,
locked
];
let
pagination
;
if
(
this
.
state
.
offset
>
0
||
(
this
.
state
.
data
&&
this
.
state
.
data
.
more
))
{
const
totalPages
=
this
.
state
.
data
?
Math
.
ceil
(
this
.
state
.
data
.
total
/
QueryOptions
.
DEFAULT_LIMIT
)
:
0
;
const
tab
=
this
.
props
.
location
.
query
.
tab
||
Utils
.
slug
(
todas
);
pagination
=
(
<
Pagination
key=
'panelPagination'
url=
{
`mailboxes?tab=${tab}`
}
currentPage=
{
this
.
state
.
page
}
totalPages=
{
totalPages
}
/>
);
}
const
icon
=
(
<
div
>
<
i
className=
'/fa fa-download'
/>
<
span
>
Exportar
</
span
>
</
div
>
);
let
tab1
=
(
<
div
>
<
Panel
title=
''
children=
{
[
panelBody
,
pagination
]
}
btnsHeader=
{
[
{
props
:
{
className
:
'btn btn-default'
,
onClick
:
(
e
)
=>
{
this
.
handleExportAsCSV
(
e
);
}
},
label
:
icon
},
{
props
:
{
className
:
'btn btn-success'
,
onClick
:
(
e
)
=>
{
this
.
handleAddMailbox
(
e
,
'/mailboxes/new'
);
}
},
label
:
'+ Nueva Casilla'
}
]
}
/>
</
div
>
);
const
hasPageInfo
=
(
this
.
props
.
children
)
?
''
:
pageInfo
;
let
tab2
=
(
<
Panel
title=
'Casillas tab2'
children=
{
[
panelBody
,
pagination
]
}
/>
);
let
tab3
=
(
<
Panel
title=
'Casillas tb3'
children=
{
panelBody
}
/>
);
const
indexView
=
(
let
tab4
=
(
<
Panel
btnsHeader=
{
addMailBoxButton
}
title=
'Casillas tab4'
children=
{
panelBody
}
/>
);
const
views
=
this
.
props
.
children
||
indexView
;
let
arrTabs
=
{};
arrTabs
[
Utils
.
slug
(
todas
)]
=
tab1
;
arrTabs
[
Utils
.
slug
(
archiving
)]
=
tab2
;
arrTabs
[
Utils
.
slug
(
noPlan
)]
=
tab3
;
arrTabs
[
Utils
.
slug
(
locked
)]
=
tab4
;
panelTabs
=
(
<
PanelTab
tabNames=
{
arrTabNames
}
tabs=
{
arrTabs
}
location=
{
this
.
props
.
location
}
onClick=
{
this
.
handleTabChanged
}
/>
);
}
const
content
=
panelTabs
||
''
;
return
(
<
div
>
<
PageInfo
titlePage=
'Casillas'
descriptionPage=
'Usuarios de correo electrónico'
/>
{
hasPageInfo
}
{
message
}
<
div
className=
'content animate-panel'
>
<
div
className=
'row'
>
<
div
className=
'col-md-12
central-content
'
>
{
views
}
<
div
className=
'col-md-12
panel-with-tabs
'
>
{
content
}
</
div
>
</
div
>
</
div
>
...
...
@@ -105,6 +329,6 @@ export default class Accounts extends React.Component {
}
}
Account
s
.
propTypes
=
{
children
:
React
.
PropTypes
.
any
Mailboxe
s
.
propTypes
=
{
location
:
React
.
PropTypes
.
object
.
isRequired
};
src/components/pagination.jsx
View file @
77e7ab21
...
...
@@ -10,6 +10,10 @@ export default class Pagination extends React.Component {
this
.
handleNext
=
this
.
handleNext
.
bind
(
this
);
this
.
handleLast
=
this
.
handleLast
.
bind
(
this
);
}
getPageQueryString
(
number
)
{
const
url
=
this
.
props
.
url
;
return
`
${(
url
.
indexOf
(
'?'
)
>
-
1
?
'&'
:
'?'
)}
page=
${
number
}
`
;
}
handleFirst
(
e
)
{
e
.
preventDefault
();
browserHistory
.
push
(
`/
${
this
.
props
.
url
}
`
);
...
...
@@ -17,11 +21,13 @@ export default class Pagination extends React.Component {
handlePrev
(
e
)
{
e
.
preventDefault
();
const
prevPage
=
this
.
props
.
currentPage
-
1
;
const
url
=
this
.
props
.
url
;
if
(
prevPage
>
1
)
{
browserHistory
.
push
(
`/
${
this
.
props
.
url
}
?page=
${
prevPage
}
`
);
const
page
=
this
.
getPageQueryString
(
prevPage
);
browserHistory
.
push
(
`/
${
url
}${
page
}
`
);
}
else
{
browserHistory
.
push
(
`/
${
this
.
props
.
url
}
`
);
browserHistory
.
push
(
`/
${
url
}
`
);
}
}
handleChange
(
e
)
{
...
...
@@ -30,18 +36,20 @@ export default class Pagination extends React.Component {
const
page
=
parseInt
(
e
.
currentTarget
.
innerText
,
10
);
let
pageUrl
=
''
;
if
(
page
>
1
)
{
pageUrl
=
`?page=
${
page
}
`
;
pageUrl
=
this
.
getPageQueryString
(
page
)
;
}
browserHistory
.
push
(
`/
${
this
.
props
.
url
}${
pageUrl
}
`
);
}
handleNext
(
e
)
{
e
.
preventDefault
();
browserHistory
.
push
(
`/
${
this
.
props
.
url
}
?page=
${
this
.
props
.
currentPage
+
1
}
`
);
const
page
=
this
.
getPageQueryString
(
this
.
props
.
currentPage
+
1
);
browserHistory
.
push
(
`/
${
this
.
props
.
url
}${
page
}
`
);
}
handleLast
(
e
)
{
e
.
preventDefault
();
browserHistory
.
push
(
`/
${
this
.
props
.
url
}
?page=
${
this
.
props
.
totalPages
}
`
);
const
page
=
this
.
getPageQueryString
(
this
.
props
.
totalPages
);
browserHistory
.
push
(
`/
${
this
.
props
.
url
}${
page
}
`
);
}
render
()
{
const
total
=
this
.
props
.
totalPages
;
...
...
@@ -114,7 +122,7 @@ export default class Pagination extends React.Component {
}
return
(
<
div
className
=
'pagination'
>
<
div
id
=
'pagination'
>
<
ul
className=
'pagination'
>
{
first
}
{
prev
}
...
...
src/components/panel.jsx
View file @
77e7ab21
...
...
@@ -7,7 +7,7 @@ export default class Panel extends React.Component {
return
(
<
Button
btnAttrs=
{
btn
.
props
}
key=
{
i
}
key=
{
`button-${i}`
}
>
{
btn
.
label
}
</
Button
>
...
...
@@ -17,7 +17,7 @@ export default class Panel extends React.Component {
let
panelHeader
;
if
(
this
.
props
.
hasHeader
)
{
panelHeader
=
(
<
div
className=
'panel-heading hbuilt'
>
<
div
className=
'panel-heading hbuilt
clearfix
'
>
<
div
className=
'pull-right'
>
{
btns
}
</
div
>
<
div
className=
'heading-buttons'
>
{
this
.
props
.
title
}
...
...
src/components/panel_tab.jsx
View file @
77e7ab21
import
React
from
'react'
;
import
*
as
Utils
from
'../utils/utils.jsx'
;
export
default
class
Panel
extends
React
.
Component
{
...
...
@@ -8,14 +7,21 @@ export default class Panel extends React.Component {
this
.
changeTab
=
this
.
changeTab
.
bind
(
this
);
const
tab
=
this
.
props
.
location
.
query
.
tab
||
Object
.
keys
(
this
.
props
.
tabs
)[
0
];
this
.
state
=
{
tab
:
Object
.
keys
(
this
.
props
.
tabs
)[
0
]
tab
};
}
changeTab
(
e
,
tabName
)
{
e
.
preventDefault
();
this
.
setState
({
tab
:
Utils
.
slug
(
tabName
)});
const
tab
=
Utils
.
slug
(
tabName
);
this
.
setState
({
tab
});
if
(
this
.
props
.
onClick
)
{
this
.
props
.
onClick
(
tab
);
}
}
render
()
{
...
...
@@ -61,5 +67,7 @@ export default class Panel extends React.Component {
Panel
.
propTypes
=
{
tabNames
:
React
.
PropTypes
.
arrayOf
(
React
.
PropTypes
.
string
).
isRequired
,
tabs
:
React
.
PropTypes
.
array
.
isRequired
tabs
:
React
.
PropTypes
.
object
.
isRequired
,
location
:
React
.
PropTypes
.
object
.
isRequired
,
onClick
:
React
.
PropTypes
.
func
};
src/index.jsx
View file @
77e7ab21
...
...
@@ -17,7 +17,7 @@ import Domains from './components/domain/domains.jsx';
import
DomainDetails
from
'./components/domain/domain_details.jsx'
;
import
CreateDomains
from
'./components/domain/create_domain.jsx'
;
import
EditDomains
from
'./components/domain/edit_domain.jsx'
;
import
Mail
Box
from
'./components/mailbox/mailbox.jsx'
;
import
Mail
boxes
from
'./components/mailbox/mailbox.jsx'
;
import
CreateMailBox
from
'./components/mailbox/create_mailbox.jsx'
;
import
EditMailBox
from
'./components/mailbox/edit_mailbox.jsx'
;
...
...
@@ -30,6 +30,8 @@ import React from 'react';
import
ReactDOM
from
'react-dom'
;
import
{
Router
,
Route
,
IndexRedirect
,
Redirect
,
browserHistory
}
from
'react-router'
;
import
ZimbraStore
from
'./stores/zimbra_store.jsx'
;
const
notFoundParams
=
{
title
:
'Página no encontrada'
,
message
:
'La página que estás intentando acceder no existe'
,
...
...
@@ -47,7 +49,7 @@ function preRenderSetup(callwhendone) {
global
.
window
.
manager_config
=
data
;
if
(
data
.
debug
)
{
global
.
window
.
Zimbra
=
Client
;
global
.
window
.
Client
=
Client
;
global
.
window
.
Utils
=
Utils
;
}
},
...
...
@@ -71,6 +73,10 @@ function onPreLoggedIn(nextState, replace, callback) {
return
Client
.
getMe
(
()
=>
{
if
(
global
.
window
.
manager_config
.
debug
)
{
global
.
window
.
Zimbra
=
ZimbraStore
.
getCurrent
();
}
return
callback
();
},
(
err
)
=>
{
...
...
@@ -144,18 +150,18 @@ function renderRootComponent() {
<
Route
path=
'mailboxes'
component=
{
MailBox
}
>
component=
{
Mailboxes
}
/>
<
Route
path=
'
new'
path=
'mailboxes/
new'
component=
{
CreateMailBox
}
/>
<
Route
path=
'
:id/edit'
path=
'mailboxes/
:id/edit'
component=
{
EditMailBox
}
/>
</
Route
>
<
Route
path=
'logout'
...
...
src/stores/tab_state_store.jsx
0 → 100644
View file @
77e7ab21
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
class
TabStateStoreClass
{
constructor
()
{
this
.
current
=
null
;
this
.
states
=
{};
}
getCurrent
()
{
return
this
.
current
;
}
setCurrent
(
newTabState
,
newObject
)
{
this
.
current
=
newTabState
;
this
.
states
[
this
.
current
]
=
newObject
;
}
}
const
TabStateStore
=
new
TabStateStoreClass
();
export
{
TabStateStore
as
default
};
src/utils/client.jsx
View file @
77e7ab21
...
...
@@ -178,3 +178,98 @@ export function getDomain(id, success, error) {
}
);
}
export
function
getAllAccounts
(
opts
,
success
,
error
)
{
initZimbra
().
then
(
(
zimbra
)
=>
{
zimbra
.
getAllAccounts
((
err
,
data
)
=>
{
if
(
err
)
{
let
e
=
handleError
(
'getAllAccounts'
,
err
);
return
error
(
e
);
}
return
success
(
data
);
},
opts
);
},
(
err
)
=>
{
let
e
=
handleError
(
'getAllAccounts'
,
err
);
return
error
(
e
);
}
);
}
export
function
getAccount
(
id
,
success
,
error
)
{
initZimbra
().
then
(
(
zimbra
)
=>
{
zimbra
.
getAccount
(
id
,
(
err
,
data
)
=>
{
if
(
err
)
{
let
e
=
handleError
(
'getAccount'
,
err
);
return
error
(
e
);
}
return
success
(
data
);
});
},
(
err
)
=>
{
let
e
=
handleError
(
'getAccount'
,
err
);
return
error
(
e
);
}
);
}
export
function
createAccount
(
mail
,
passwd
,
attrs
,
success
,
error
)
{
initZimbra
().
then
(
(
zimbra
)
=>
{
zimbra
.
createAccount
(
mail
,
passwd
,
attrs
,
(
err
,
data
)
=>
{
if
(
err
)
{
let
e
=
handleError
(
'createAccount'
,
err
);
return
error
(
e
);
}
return
success
(
data
);
});
},
(
err
)
=>
{
let
e
=
handleError
(
'createAccount'
,
err
);
return
error
(
e
);
}
);
}
export
function
modifyAccount
(
idZimbra
,
attrs
,
success
,
error
)
{
initZimbra
().
then
(
(
zimbra
)
=>
{
zimbra
.
modifyAccount
(
idZimbra
,
attrs
,
(
err
,
data
)
=>
{
if
(
err
)
{
let
e
=
handleError
(
'modifyAccount'
,
err
);
return
error
(
e
);
}
return
success
(
data
);
});
},
(
err
)
=>
{
let
e
=
handleError
(
'modifyAccount'
,
err
);
return
error
(
e
);
}
);
}
export
function
removeAccount
(
idZimbra
,
success
,
error
)
{
initZimbra
().
then
(
(
zimbra
)
=>
{
zimbra
.
removeAccount
(
idZimbra
,
(
err
,
data
)
=>
{
if
(
err
)
{
let
e
=
handleError
(
'removeAccount'
,
err
);
return
error
(
e
);
}
return
success
(
data
);
});
},
(
err
)
=>
{
let
e
=
handleError
(
'removeAccount'
,
err
);
return
error
(
e
);
}
);
}
src/utils/utils.jsx
View file @
77e7ab21
...
...
@@ -159,3 +159,58 @@ export function handleLink(e, path, location) {
browserHistory
.
push
(
path
);
}
}
export
function
isObjectEmpty
(
value
)
{
for
(
const
key
in
value
)
{
if
(
value
.
hasOwnProperty
(
key
))
{
return
false
;
}
}
return
true
;
}
export
function
validateInputRequired
(
refs
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
refs
||
isObjectEmpty
(
refs
)
||
Array
.
isArray
(
refs
))
{
reject
({
message
:
'No se puede validar un arreglo o un objeto vacio o indefinido'
,
typeError
:
'warning'
});
}
for
(
const
ref
in
refs
)
{
if
(
refs
.
hasOwnProperty
(
ref
))
{
if
(
refs
[
ref
].
hasAttribute
(
'data-required'
)
&&
refs
[
ref
].
getAttribute
(
'data-required'
)
===
'true'
&&
refs
[
ref
].
value
===
''
)
{
let
message
;
if
(
refs
[
ref
].
getAttribute
(
'data-message'
)
&&
refs
[
ref
].
getAttribute
(
'data-message'
).
length
>
0
)
{
message
=
refs
[
ref
].
getAttribute
(
'data-message'
);
}
else
{
message
=
'Algunos Campos son requeridos, verificar por favor.'
;
}
const
Error
=
{
message
,
typeError
:
'warning'
,
node
:
refs
[
ref
]
};
return
reject
(
Error
);
}
}
}
return
resolve
(
null
);
});
}
export
function
toggleStatusButtons
(
classNames
,
isDisabled
)
{
let
elements
=
document
.
querySelectorAll
(
classNames
);
if
(
elements
.
length
>
0
)
{
let
l
=
elements
.
length
;
for
(;
l
--
>
0
;)
{
if
(
isDisabled
)
{
elements
[
l
].
setAttribute
(
'disabled'
,
'disabled'
);
}
else
{
elements
[
l
].
removeAttribute
(
'disabled'
);
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment