2018-01-22 13:01:38 -08:00
<!-- Modal add user -->
< div class = "modal fade" id = "userAddModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Add User< / h4 >
< / div >
< div class = "modal-body" >
< form name = "useradd_form" role = "form" ng-submit = "useradd.submit()" autocomplete = "off" >
< input type = "password" style = "display: none;" >
< div class = "form-group" ng-class = "{ 'has-error': (useradd_form.email.$dirty && useradd_form.email.$invalid) || (!useradd_form.email.$dirty && useradd.error.email) }" >
< label class = "control-label" > Email< / label >
< div class = "control-label" ng-show = "(!useradd_form.email.$dirty && useradd.error.email) || (useradd_form.email.$dirty && useradd_form.email.$invalid) || (!useradd_form.email.$dirty && useradd.error.email)" >
< small ng-show = "useradd_form.email.$error.required" > An email is required< / small >
< small ng-show = "useradd_form.email.$error.email" > This is not a valid email< / small >
< small ng-show = "!useradd_form.email.$dirty && useradd.error.email" > {{ useradd.error.email }}< / small >
< / div >
< input type = "email" class = "form-control" ng-model = "useradd.email" name = "email" id = "inputUserAddEmail" required autofocus >
< / div >
< div class = "form-group" ng-class = "{ 'has-error': (useradd_form.username.$dirty && useradd_form.username.$invalid) || (!useradd_form.username.$dirty && useradd.error.username) }" >
< label class = "control-label" > Username< / label >
< div class = "control-label" ng-show = "(!useradd_form.username.$dirty && useradd.error.username) || (useradd_form.username.$dirty && useradd_form.username.$invalid) || (!useradd_form.username.$dirty && useradd.error.username)" >
< small ng-show = "useradd_form.username.$error.username" > This is not a valid username< / small >
< small ng-show = "!useradd_form.username.$dirty && useradd.error.username" > {{ useradd.error.username }}< / small >
< / div >
< input type = "text" class = "form-control" ng-model = "useradd.username" name = "username" id = "inputUserAddUsername" placeholder = "Optional" >
< / div >
< div class = "form-group" ng-class = "{ 'has-error': (useradd_form.displayName.$dirty && useradd_form.displayName.$invalid) || (!useradd_form.displayName.$dirty && useradd.error.displayName) }" >
< label class = "control-label" > Display Name< / label >
< div class = "control-label" ng-show = "(!useradd_form.displayName.$dirty && useradd.error.displayName) || (useradd_form.displayName.$dirty && useradd_form.displayName.$invalid) || (!useradd_form.displayName.$dirty && useradd.error.displayName)" >
< small ng-show = "useradd_form.displayName.$error.displayName" > This is not a valid displayName< / small >
< small ng-show = "!useradd_form.displayName.$dirty && useradd.error.displayName" > {{ useradd.error.displayName }}< / small >
< / div >
< input type = "text" class = "form-control" ng-model = "useradd.displayName" name = "displayName" id = "inputUserAddDisplayName" placeholder = "Optional" >
< / div >
< div class = "checkbox" >
< label >
< input type = "checkbox" ng-model = "useradd.sendInvite" id = "inputUserAddSendInvite" > Send an invitation email now
< / label >
< / div >
< input class = "ng-hide" type = "submit" ng-disabled = "useradd_form.$invalid || useradd.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-success" ng-click = "useradd.submit()" ng-disabled = "useradd_form.$invalid || useradd.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "useradd.busy" > < / i > Add User< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Modal remove user -->
< div class = "modal fade" id = "userRemoveModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Delete user {{ userremove.userInfo.username || userremove.userInfo.email }}< / h4 >
< / div >
< div class = "modal-body" >
< form name = "userremove_form" role = "form" ng-submit = "userremove.submit()" autocomplete = "off" >
< input type = "password" style = "display: none;" >
< div class = "form-group" ng-class = "{ 'has-error': (userremove_form.password.$dirty && userremove_form.password.$invalid) || (!userremove_form.password.$dirty && userremove.error.password)}" >
< label class = "control-label" > Give your password to verify this action< / label >
< input type = "password" class = "form-control" ng-model = "userremove.password" id = "inputUserRemovePassword" name = "password" placeholder = "Your Password" required autofocus >
< div class = "control-label" ng-show = "(!userremove_form.password.$dirty && userremove.error.password) || (userremove_form.password.$dirty && userremove_form.password.$invalid)" >
< small ng-show = "userremove_form.password.$error.required && !userremove.error.password" > A password is required< / small >
< small ng-show = "!useradd_form.email.$dirty && userremove.error.password" > {{ userremove.error.password }}< / small >
< / div >
< / div >
< input class = "hide" type = "submit" ng-disabled = "userremove_form.$invalid || userremove.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Close< / button >
< button type = "button" class = "btn btn-danger" ng-click = "userremove.submit()" ng-disabled = "userremove_form.$invalid || userremove.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "userremove.busy" > < / i > Delete< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Modal edit user -->
< div class = "modal fade" id = "userEditModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Edit user {{ useredit.userInfo.username }}< / h4 >
< / div >
< div class = "modal-body" >
< form name = "useredit_form" role = "form" ng-submit = "useredit.submit()" autocomplete = "off" >
< input type = "password" style = "display: none;" >
< div class = "form-group" ng-class = "{ 'has-error': (useredit_form.email.$dirty && useredit_form.email.$invalid) || (!useredit_form.email.$dirty && useredit.error.email) }" >
2018-01-24 16:20:56 +01:00
< label class = "control-label" > Email< / label >
2018-01-22 13:01:38 -08:00
< div class = "control-label" ng-show = "(!useredit_form.email.$dirty && useredit.error.email) || (useredit_form.email.$dirty && useredit_form.email.$invalid) || (!useredit_form.email.$dirty && useredit.error.email)" >
< small ng-show = "useredit_form.email.$error.required" > An email is required< / small >
< small ng-show = "useredit_form.email.$error.email" > This is not a valid email< / small >
< small ng-show = "!useredit_form.email.$dirty && useredit.error.email" > {{ useredit.error.email }}< / small >
< / div >
< input type = "email" class = "form-control" ng-model = "useredit.email" name = "email" required >
< / div >
2018-01-24 16:20:56 +01:00
< div class = "form-group" ng-class = "{ 'has-error': (useredit_form.fallbackEmail.$dirty && useredit_form.fallbackEmail.$invalid) || (!useredit_form.fallbackEmail.$dirty && useredit.error.fallbackEmail) }" >
< label class = "control-label" > Password recovery email< / label >
< div class = "control-label" ng-show = "(!useredit_form.fallbackEmail.$dirty && useredit.error.fallbackEmail) || (useredit_form.fallbackEmail.$dirty && useredit_form.fallbackEmail.$invalid) || (!useredit_form.fallbackEmail.$dirty && useredit.error.fallbackEmail)" >
< small ng-show = "useredit_form.fallbackEmail.$error.required" > An email is required< / small >
< small ng-show = "useredit_form.fallbackEmail.$error.fallbackEmail" > This is not a valid email< / small >
< small ng-show = "!useredit_form.fallbackEmail.$dirty && useredit.error.fallbackEmail" > {{ useredit.error.fallbackEmail }}< / small >
< / div >
< input type = "fallbackEmail" class = "form-control" ng-model = "useredit.fallbackEmail" name = "fallbackEmail" required >
< / div >
2018-01-22 13:01:38 -08:00
< div class = "form-group" >
< label class = "control-label" > Groups< / label >
< div >
< span ng-repeat = "group in groups | ignoreAdminGroup" ng-show = "group.id !== 'admin'" >
< button class = "btn btn-default" type = "button" ng-click = "useredit.toggleGroup(group);" ng-class = "{ 'btn-primary': (useredit.groupIds.indexOf(group.id) !== -1) }" > {{ group.name }}< / button >
< / span >
< / div >
< div ng-show = "groups.length <= 1" > No groups available.< / div >
< / div >
2018-01-25 18:28:11 +01:00
< h2 ng-show = "useredit.busyFetching" > < center > < i class = "fa fa-circle-o-notch fa-spin" > < / i > < / center > < / h2 >
< div ng-hide = "useredit.busyFetching" class = "form-group" >
< label class = "control-label" > Email address on domains< / label >
2018-01-24 16:20:56 +01:00
< div >
2018-01-26 15:39:35 +01:00
< multiselect ng-model = "useredit.selectedEmailDomains" options = "d.address for d in useredit.availableEmailDomains" data-multiple = "true" > < / multiselect >
2018-01-24 16:20:56 +01:00
< / div >
< / div >
2018-01-25 18:28:11 +01:00
< div class = "form-group" ng-show = "!useredit.busyFetching && useredit.userInfo.username" ng-class = "{ 'has-error': useredit.error.aliases }" >
2018-01-22 13:01:38 -08:00
< label class = "control-label" > Email aliases< / label >
< div class = "control-label" ng-show = "useredit.error.aliases" >
< small > {{ useredit.error.aliases }}< / small >
< / div >
2018-01-26 15:39:35 +01:00
< div class = "input-group form-inline" ng-repeat = "emailDomain in useredit.selectedEmailDomains" style = "margin-top: 10px;" >
< tag-input class = "form-group form-control" placeholder = "Separate aliases by comma" taglist = "useredit.aliases[emailDomain.address]" name = "aliases" > < / tag-input >
2018-01-22 13:01:38 -08:00
< div class = "input-group-addon" >
2018-01-26 15:39:35 +01:00
@{{ emailDomain.domain.domain }}
2018-01-22 13:01:38 -08:00
< / div >
< / div >
< / div >
< br / >
< div class = "form-group" ng-hide = "isMe(useredit.userInfo)" >
< div class = "checkbox" >
< label >
< input type = "checkbox" ng-model = "useredit.superuser" > Make this user a Cloudron admin
< / label >
< / div >
< / div >
< input class = "hide" type = "submit" ng-disabled = "useredit_form.$invalid || useredit.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Close< / button >
< button type = "button" class = "btn btn-success" ng-click = "useredit.submit()" ng-disabled = "useredit_form.$invalid || useredit.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "useredit.busy" > < / i > Save< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Modal add group -->
< div class = "modal fade" id = "groupAddModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Add Group< / h4 >
< / div >
< div class = "modal-body" >
< form name = "groupAddForm" role = "form" novalidate ng-submit = "groupAdd.submit()" autocomplete = "off" >
< div class = "form-group" ng-class = "{ 'has-error': (groupAddForm.name.$dirty && groupAddForm.name.$invalid) || (!groupAddForm.name.$dirty && groupAdd.error.name) }" >
< label class = "control-label" for = "groupAddName" > Name< / label >
< div class = "control-label" ng-show = "(!groupAddForm.name.$dirty && groupAdd.error.name) || (groupAddForm.name.$dirty && groupAddForm.name.$invalid) || (!groupAddForm.name.$dirty && groupAdd.error.name)" >
< small ng-show = "groupAddForm.name.$error.required" > A name is required< / small >
< small ng-show = "groupAddForm.name.$error.minlength" > The name is too short< / small >
< small ng-show = "groupAddForm.name.$error.maxlength" > The name is too long< / small >
< small ng-show = "!groupAddForm.name.$dirty && groupAdd.error.name" > {{ groupAdd.error.name }}< / small >
< / div >
< input type = "text" class = "form-control" ng-model = "groupAdd.name" id = "groupAddName" name = "name" ng-maxlength = "200" ng-minlength = "1" required autofocus >
< / div >
< input class = "hide" type = "submit" ng-disabled = "groupAddForm.$invalid || groupAdd.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-success" ng-click = "groupAdd.submit()" ng-disabled = "groupAddForm.$invalid || groupAdd.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "groupAdd.busy" > < / i > Add Group< / button >
< / div >
< / div >
< / div >
< / div >
2018-01-26 11:31:43 +01:00
<!-- Modal edit group -->
< div class = "modal fade" id = "groupEditModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Edit group {{ groupEdit.group.name }}< / h4 >
< / div >
< div class = "modal-body" ng-show = "groupEdit.busyFetching" >
< h2 > < center > < i class = "fa fa-circle-o-notch fa-spin" > < / i > < / center > < / h2 >
< / div >
< div class = "modal-body" ng-hide = "groupEdit.busyFetching" >
< form name = "groupEditForm" role = "form" ng-submit = "groupEdit.submit()" autocomplete = "off" >
< input type = "password" style = "display: none;" >
< div class = "form-group" >
< label class = "control-label" > Email mailinglists on domains< / label >
< p > Each user in this group will receive the mails sent to this group's email address.< / p >
< div >
< multiselect ng-model = "groupEdit.selectedLists" options = "l.address for l in groupEdit.availableLists" data-multiple = "true" > < / multiselect >
< / div >
< / div >
< input class = "hide" type = "submit" ng-disabled = "groupEditForm.$invalid || groupEdit.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Close< / button >
< button type = "button" class = "btn btn-success" ng-click = "groupEdit.submit()" ng-disabled = "groupEditForm.$invalid || groupEdit.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "groupEdit.busy" > < / i > Save< / button >
< / div >
< / div >
< / div >
< / div >
2018-01-22 13:01:38 -08:00
<!-- Modal remove group -->
< div class = "modal fade" id = "groupRemoveModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Delete group {{ groupRemove.group.name }}< / h4 >
< / div >
< div class = "modal-body" >
< div ng-show = "groupRemove.memberCount" class = "text-danger" >
< b > This group still has {{ groupRemove.memberCount }} member(s). Are you sure this group is not used?< / b >
< br / >
< br / >
< / div >
< form name = "groupRemoveForm" role = "form" novalidate ng-submit = "groupRemove.submit()" autocomplete = "off" >
< input type = "password" style = "display: none;" >
< div class = "form-group" ng-class = "{ 'has-error': (groupRemoveForm.password.$dirty && groupRemoveForm.password.$invalid) || (!groupRemoveForm.password.$dirty && groupRemove.error.password)}" >
< label class = "control-label" for = "groupRemovePasswordInput" > Give your password to verify this action< / label >
< div class = "control-label" ng-show = "(!groupRemoveForm.password.$dirty && groupRemove.error.password) || (groupRemoveForm.password.$dirty && groupRemoveForm.password.$invalid)" >
< small ng-show = "groupRemoveForm.password.$error.required && !groupRemove.error.password" > A password is required< / small >
< small ng-show = "!groupRemoveForm.password.$dirty && groupRemove.error.password" > {{ groupRemove.error.password }}< / small >
< / div >
< input type = "password" class = "form-control" ng-model = "groupRemove.password" id = "groupRemovePasswordInput" name = "password" placeholder = "Password" required autofocus >
< / div >
< input class = "hide" type = "submit" ng-disabled = "groupRemoveForm.$invalid || groupRemove.busy" / >
< / form >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Close< / button >
< button type = "button" class = "btn btn-danger" ng-click = "groupRemove.submit()" ng-disabled = "groupRemoveForm.$invalid || groupRemove.busy" > < i class = "fa fa-circle-o-notch fa-spin" ng-show = "groupRemove.busy" > < / i > Delete< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Modal invite sent -->
< div class = "modal fade" id = "inviteSentModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Invite Sent< / h4 >
< / div >
< div class = "modal-body" >
< p > An email has been sent to < b > {{ inviteSent.email }}< / b > .< / p >
< p > You can also share this invite link directly:< / p >
< div class = "input-group" >
< input type = "text" id = "setupLinkInput" class = "form-control" ng-value = "inviteSent.setupLink" readonly / >
< span class = "input-group-btn" >
< button class = "btn btn-default" id = "setupLinkButton" type = "button" data-clipboard-target = "#setupLinkInput" > < i class = "fa fa-clipboard" > < / i > < / button >
< / span >
< / div >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-primary" data-dismiss = "modal" > OK< / button >
< / div >
< / div >
< / div >
< / div >
< div class = "content content-large" >
< div class = "text-left" >
< h1 > Users < button class = "btn btn-primary btn-outline pull-right" ng-click = "useradd.show()" > < i class = "fa fa-user-plus" > < / i > New User< / button > < / h1 >
< / div >
< div class = "card card-large" >
< div class = "grid-item-top" >
< div class = "row ng-hide" ng-show = "!ready" >
< div class = "col-lg-12 text-center" >
< h2 > < i class = "fa fa-circle-o-notch fa-spin" > < / i > < / h2 >
< / div >
< / div >
< div class = "row animateMeOpacity ng-hide" ng-show = "ready" >
< div class = "col-lg-12" >
2018-01-29 14:35:47 -08:00
< span >
For email enabled domains, each user has a mailbox at < b > < i > username@domain< / i > < / b > .
2018-01-22 13:01:38 -08:00
Please refer to the < a ng-href = "{{ config.webServerOrigin + '/documentation/email/#imap-settings-for-cloudron-email' }}" target = "_blank" > user documentation< / a > on how to use Cloudron email accounts.
< br / >
< br / >
< / span >
< table class = "table table-hover" >
< thead >
< tr >
< th style = "width: 1px;" > < / th >
2018-01-26 11:31:43 +01:00
< th > User< / th >
< th class = "text-left hidden-xs hidden-sm" > Groups< / th >
2018-01-22 13:01:38 -08:00
< th style = "width: 100px" class = "text-right" > Actions< / th >
< / tr >
< / thead >
< tbody >
< tr ng-repeat = "user in users" >
< td >
< i class = "fa fa-briefcase arrow" ng-show = "user.admin" uib-tooltip = "This user is an admin and can manage apps, groups and other users" > < / i >
< / td >
< td class = "hand elide-table-cell" ng-click = "useredit.show(user)" ng-show = "user.username" >
2018-01-29 14:35:47 -08:00
{{ user.username }} < span class = "text-muted" > {{ user.email }}< / span >
2018-01-22 13:01:38 -08:00
< / td >
< td class = "hand elide-table-cell" ng-click = "useredit.show(user)" ng-hide = "user.username" >
< span class = "text-muted" uib-tooltip = "User is not activated yet" > {{ user.fallbackEmail }}< / span >
< / td >
< td class = "text-left hand elide-table-cell hidden-xs hidden-sm" ng-click = "useredit.show(user)" >
< span class = "group-badge" ng-repeat = "groupId in user.groupIds | ignoreAdminGroup" >
{{ groupsById[groupId].name }}
< / span >
< / td >
< / td >
< td class = "text-right no-wrap" style = "vertical-align: bottom" >
< button ng-show = "!isMe(user)" class = "btn btn-xs btn-default" ng-click = "sendInvite(user)" title = "Send invitation email" > < i class = "fa fa-paper-plane-o" > < / i > < / button >
< button class = "btn btn-xs btn-default" ng-click = "useredit.show(user)" title = "Edit User Profile" > < i class = "fa fa-pencil" > < / i > < / button >
< button ng-show = "!isMe(user)" class = "btn btn-xs btn-danger" ng-click = "userremove.show(user)" title = "Remove User" > < i class = "fa fa-trash-o" > < / i > < / button >
< / td >
< / tr >
< / tbody >
< / table >
< / div >
< / div >
< / div >
< / div >
< br / >
< div class = "text-left" >
< h1 > Groups < button class = "btn btn-primary btn-outline pull-right" ng-click = "groupAdd.show()" > < i class = "fa fa-plus" > < / i > New Group< / button > < / h1 >
< / div >
< div class = "card card-large" >
< div class = "grid-item-top" >
< div class = "row ng-hide" ng-show = "!ready" >
< div class = "col-lg-12 text-center" >
< h2 > < i class = "fa fa-circle-o-notch fa-spin" > < / i > < / h2 >
< / div >
< / div >
< div class = "row animateMeOpacity ng-hide" ng-show = "ready" >
< div class = "col-lg-12" >
2018-01-29 14:35:47 -08:00
Groups can be used to control access to an app. When Cloudron email is enabled, each group also serves as an email list at < b > < i > groupname@domain< / i > < / b > . Any email sent to this address will be forwarded to each group member.< / span >
2018-01-22 13:01:38 -08:00
< br / >
< br / >
< table class = "table table-hover" >
< thead >
< tr >
2018-01-26 11:31:43 +01:00
< th > Name< / th >
2018-01-22 13:01:38 -08:00
< th style = "width: 300px" class = "text-right" > Actions< / th >
< / tr >
< / thead >
< tbody >
< tr ng-repeat = "group in groups | ignoreAdminGroup" >
2018-01-26 11:31:43 +01:00
< td class = "hand" style = "text-overflow: ellipsis; white-space: nowrap;" ng-click = "groupEdit.show(group)" >
2018-01-22 13:01:38 -08:00
{{ group.name }}
< / td >
< td class = "text-right" style = "vertical-align: bottom" >
2018-01-26 11:31:43 +01:00
< button class = "btn btn-xs btn-default" ng-click = "groupEdit.show(group)" title = "Edit Group" > < i class = "fa fa-pencil" > < / i > < / button >
2018-01-22 13:01:38 -08:00
< button class = "btn btn-xs btn-danger" ng-click = "groupRemove.show(group)" title = "Remove Group" > < i class = "fa fa-trash-o" > < / i > < / button >
< / td >
< / tr >
< / tbody >
< / table >
< / div >
< / div >
< / div >
< / div >
< / div >