Files
cloudron-box/src/views/users.html

392 lines
26 KiB
HTML
Raw Normal View History

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">
2018-06-11 14:16:52 -07:00
<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">Full 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 name</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" ng-required autofocus autocomplete="off">
</div>
2018-01-22 13:01:38 -08:00
<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>
2018-06-11 14:16:52 -07:00
<input type="email" class="form-control" ng-model="useradd.email" name="email" id="inputUserAddEmail" required>
2018-01-22 13:01:38 -08:00
</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>
2018-06-11 14:16:52 -07:00
<input type="text" class="form-control" ng-model="useradd.username" name="username" id="inputUserAddUsername" placeholder="Optional. If not provided, user can pick during sign up">
2018-01-22 13:01:38 -08:00
</div>
2018-07-24 22:38:53 -07:00
<div class="form-group">
<label class="control-label">Groups</label>
<div class="control-label">
2018-07-26 23:42:38 -07:00
<div ng-show="groups.length === 0">No groups available.</div>
<multiselect ng-show="groups.length !== 0" ng-model="useradd.selectedGroups" options="group.name for group in groups" data-compare-by="name" data-multiple="true"></multiselect>
2018-07-24 22:38:53 -07:00
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
2018-07-26 15:45:52 -07:00
<input type="checkbox" ng-model="useradd.admin"> User is an <a href="https://cloudron.io/documentation/user-management/#administrators" target="_blank">administrator</a>
2018-07-24 22:38:53 -07:00
</label>
</div>
</div>
2018-01-22 13:01:38 -08:00
<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 || useredit.userInfo.email }}</h4>
2018-01-22 13:01:38 -08:00
</div>
<div class="modal-body">
<form name="useredit_form" role="form" ng-submit="useredit.submit()" autocomplete="off">
2018-07-24 15:17:51 -07:00
<div class="form-group" ng-class="{ 'has-error': (useredit_form.displayName.$dirty && useredit_form.displayName.$invalid) || (!useredit_form.displayName.$dirty && useredit.error.displayName) }">
<label class="control-label">Full Name</label>
<div class="control-label" ng-show="(!useredit_form.displayName.$dirty && useredit.error.displayName) || (useredit_form.displayName.$dirty && useredit_form.displayName.$invalid) || (!useredit_form.displayName.$dirty && useredit.error.displayName)">
<small ng-show="useredit_form.displayName.$error.required">Name is required</small>
<small ng-show="!useredit_form.displayName.$dirty && useredit.error.displayName">{{ useredit.error.displayName }}</small>
</div>
<input type="text" class="form-control" ng-model="useredit.displayName" name="displayName" required autofocus autocomplete="off">
</div>
2018-01-22 13:01:38 -08:00
<div class="form-group" ng-class="{ 'has-error': (useredit_form.email.$dirty && useredit_form.email.$invalid) || (!useredit_form.email.$dirty && useredit.error.email) }">
<label class="control-label">Primary 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>
<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 class="control-label">
2018-07-26 23:42:38 -07:00
<div ng-show="groups.length === 0">No groups available.</div>
<multiselect ng-show="groups.length !== 0" ng-model="useredit.selectedGroups" options="group.name for group in groups" data-compare-by="name" data-multiple="true"></multiselect>
2018-01-22 13:01:38 -08:00
</div>
</div>
<div class="form-group" ng-hide="isMe(useredit.userInfo)">
<div class="checkbox">
<label>
2018-07-26 15:45:52 -07:00
<input type="checkbox" ng-model="useredit.admin"> User is an <a href="https://cloudron.io/documentation/user-management/#administrators" target="_blank">administrator</a>
2018-01-22 13:01:38 -08:00
</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>
2018-08-05 22:19:54 -07:00
<div class="form-group">
<label class="control-label">Users</label>
<div class="control-label">
<multiselect ng-model="groupAdd.selectedUsers" options="(user.username || user.email) for user in users" data-compare-by="email" data-multiple="true"></multiselect>
</div>
</div>
2018-01-22 13:01:38 -08:00
<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>
<!-- 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.groupInfo.name }}</h4>
</div>
<div class="modal-body">
<form name="groupEdit_form" role="form" ng-submit="groupEdit.submit()" autocomplete="off">
<div class="form-group" ng-class="{ 'has-error': groupEditForm.groupName.$invalid }">
<label class="control-label">Group name</label>
<input type="text" class="form-control" ng-model="groupEdit.name" name="groupName" ng-disabled="groupEdit.busy" autofocus>
</div>
<div class="form-group">
<label class="control-label">Users</label>
<div class="control-label">
2018-07-26 23:42:38 -07:00
<multiselect ng-model="groupEdit.selectedUsers" options="(user.username || user.email) for user in users" data-compare-by="email" data-multiple="true"></multiselect>
</div>
</div>
<input class="hide" type="submit" ng-disabled="groupEdit_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="groupEdit.submit()" ng-disabled="groupEdit_form.$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 -->
<div class="modal fade" id="invitationModal" tabindex="-1" role="dialog">
2018-01-22 13:01:38 -08:00
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
2018-08-27 15:08:09 -07:00
<h4 class="modal-title">Setup link for User {{invitation.user.username || invitation.user.email}}</h4>
2018-01-22 13:01:38 -08:00
</div>
<div class="modal-body">
<p>Use the link below to setup {{ invitation.user.username || invitation.user.email }}'s account or reset their password:</p>
2018-01-22 13:01:38 -08:00
<div class="input-group">
<input type="text" id="setupLinkInput" class="form-control" ng-value="invitation.setupLink" readonly/>
2018-01-22 13:01:38 -08:00
<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>
2018-08-27 15:40:23 -07:00
</div>
<br/>
2018-01-22 13:01:38 -08:00
</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="invitation.email()" ng-disabled="invitation.busy"><i class="fa fa-circle-o-notch fa-spin" ng-show="invitation.busy"></i> Email link to user</button>
2018-01-22 13:01:38 -08:00
</div>
</div>
</div>
</div>
<div class="content content-large">
<div class="text-left">
2018-03-13 00:29:10 -07:00
<h1>Users
<sup><a ng-href="{{ config.webServerOrigin }}/documentation/user-management/#users" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup>
<button class="btn btn-primary btn-outline pull-right" ng-click="useradd.show()">
<i class="fa fa-user-plus"></i> New User
</button>
</h1>
2018-01-22 13:01:38 -08:00
</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">
<table class="table table-hover">
<thead>
<tr>
2018-08-05 22:10:45 -07:00
<th style="width: 0.5%;"></th>
<th style="width:45%">User</th>
<th style="width:49.5%" class="hidden-xs hidden-sm">Groups</th>
<th style="width: 5%" class="text-right">Actions</th>
2018-01-22 13:01:38 -08:00
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users">
<td>
2018-08-03 10:09:04 -07:00
<i class="fa fa-briefcase arrow" ng-show="user.admin" uib-tooltip="This user can manage apps, groups and other users"></i>
2018-01-22 13:01:38 -08:00
</td>
<td class="hand elide-table-cell" ng-click="useredit.show(user)" ng-show="user.username">
2018-07-24 15:20:25 -07:00
{{ user.displayName }} &nbsp; <span class="text-muted">{{ user.username }}</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)">
2018-07-26 15:45:52 -07:00
<span class="group-badge" ng-repeat="groupId in user.groupIds">
2018-01-22 13:01:38 -08:00
{{ groupsById[groupId].name }}
</span>
</td>
<td class="text-right no-wrap" style="vertical-align: bottom">
2018-11-15 18:07:18 +01:00
<button ng-show="!isMe(user)" class="btn btn-xs btn-default" ng-click="invitation.show(user)" title="Create setup link"><i class="fa fa-paper-plane"></i></button>
<button class="btn btn-xs btn-default" ng-click="useredit.show(user)" title="Edit User"><i class="fa fa-pencil-alt"></i></button>
<button ng-show="!isMe(user)" class="btn btn-xs btn-danger" ng-click="userremove.show(user)" title="Remove User"><i class="far fa-trash-alt"></i></button>
2018-01-22 13:01:38 -08:00
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<br/>
<div class="text-left">
2018-03-13 00:29:10 -07:00
<h1>Groups
<sup><a ng-href="{{ config.webServerOrigin }}/documentation/user-management/#groups" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup>
<button class="btn btn-primary btn-outline pull-right" ng-click="groupAdd.show()"><i class="fa fa-plus"></i> New Group</button>
</h1>
2018-01-22 13:01:38 -08:00
</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">
<table class="table table-hover">
<thead>
<tr>
2018-08-05 22:10:45 -07:00
<th style="width: 45%">Name</th>
<th style="width: 50%">Users</th>
<th style="width: 5%" class="text-right">Actions</th>
2018-01-22 13:01:38 -08:00
</tr>
</thead>
<tbody>
2018-07-26 15:45:52 -07:00
<tr ng-repeat="group in groups">
<td class="hand elide-table-cell" style="text-overflow: ellipsis; white-space: nowrap;" ng-click="groupEdit.show(group)">
2018-01-22 13:01:38 -08:00
{{ group.name }}
</td>
2018-07-26 23:58:25 -07:00
<td class="hand elide-table-cell" style="text-overflow: ellipsis; white-space: nowrap;" ng-click="groupEdit.show(group)">
{{ groupMembers(group) }}
</td>
2018-01-22 13:01:38 -08:00
<td class="text-right" style="vertical-align: bottom">
2018-11-15 18:07:18 +01:00
<button class="btn btn-xs btn-default" ng-click="groupEdit.show(group)" title="Edit Group"><i class="fa fa-pencil-alt"></i></button>
<button class="btn btn-xs btn-danger" ng-click="groupRemove.show(group)" title="Remove Group"><i class="far fa-trash-alt"></i></button>
2018-01-22 13:01:38 -08:00
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>