Merge remote-tracking branch 'upstream/new-ui-with-sync-image' into author

This commit is contained in:
wemeya 2016-06-21 16:17:12 +08:00
commit e1ed055d8a
11 changed files with 151 additions and 58 deletions

View File

@ -110,4 +110,5 @@ body {
.page-content { .page-content {
margin: 0 20px 0 20px; margin: 0 20px 0 20px;
text-align: left;
} }

View File

@ -1,4 +1,4 @@
<h4 class="page-header title-color underlined">// 'top_10_repositories' | tr //</h4> <h4 class="page-header title-color underlined">// 'popular_repositories' | tr //</h4>
<div class="col-xs-4 col-md-12 up-table-pane"> <div class="col-xs-4 col-md-12 up-table-pane">
<table class="table"> <table class="table">
<thead> <thead>
@ -9,7 +9,7 @@
<td colspan="5" height="120px" class="empty-hint" ng-if="vm.top10Repositories.length === 0"><h3 class="text-muted">// 'no_top_repositories' | tr //</h3></td> <td colspan="5" height="120px" class="empty-hint" ng-if="vm.top10Repositories.length === 0"><h3 class="text-muted">// 'no_top_repositories' | tr //</h3></td>
</tr> </tr>
<tr ng-if="vm.top10Repositories.length > 0" ng-repeat="t in vm.top10Repositories"> <tr ng-if="vm.top10Repositories.length > 0" ng-repeat="t in vm.top10Repositories">
<td>//t.name//</td><td>//t.count//</td><td>//t.creator//</td> <td>//t.name//</td><td>//t.count//</td><td>//t.creator === '' ? 'N/A' : t.creator //</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -13,7 +13,11 @@
<div class="sub-pane"> <div class="sub-pane">
<table class="table"> <table class="table">
<thead> <thead>
<th>// 'username' | tr //</th><th>// 'email' | tr //</th><th>// 'registration_time' | tr //</th><th>// 'operation' | tr //</th> <th>// 'username' | tr //</th>
<th>// 'email' | tr //</th>
<th>// 'registration_time' | tr //</th>
<th>// 'administrator' | tr //</th>
<th>// 'operation' | tr //</th>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="u in vm.users"> <tr ng-repeat="u in vm.users">
@ -21,7 +25,9 @@
<td>//u.email//</td> <td>//u.email//</td>
<td>//u.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td> <td>//u.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td> <td>
<toggle-admin has-admin-role="u.has_admin_role == 1" user-id="//u.user_id//"></toggle-admin>&nbsp;&nbsp; <toggle-admin has-admin-role="u.has_admin_role == 1" user-id="//u.user_id//"></toggle-admin>
</td>
<td>
&nbsp;&nbsp;<a href="javascript:void(0)" data-toggle="modal" data-target="#myModal" ng-click="vm.confirmToDelete(u.user_id)"><span class="glyphicon glyphicon-trash"></span></a> &nbsp;&nbsp;<a href="javascript:void(0)" data-toggle="modal" data-target="#myModal" ng-click="vm.confirmToDelete(u.user_id)"><span class="glyphicon glyphicon-trash"></span></a>
</td> </td>
</tr> </tr>

View File

@ -6,26 +6,27 @@
.module('harbor.layout.account.setting') .module('harbor.layout.account.setting')
.controller('AccountSettingController', AccountSettingController); .controller('AccountSettingController', AccountSettingController);
AccountSettingController.$inject = ['ChangePasswordService', '$scope', '$window', 'currentUser']; AccountSettingController.$inject = ['ChangePasswordService', 'UpdateUserService', '$filter', 'trFilter', '$scope', '$window', 'currentUser'];
function AccountSettingController(ChangePasswordService, $scope, $window, currentUser) { function AccountSettingController(ChangePasswordService, UpdateUserService, $filter, trFilter, $scope, $window, currentUser) {
var vm = this; var vm = this;
vm.isOpen = false; vm.isOpen = false;
vm.user = {};
vm.hasError = false; vm.hasError = false;
vm.errorMessage = ''; vm.errorMessage = '';
vm.reset = reset; vm.reset = reset;
vm.toggleChangePassword = toggleChangePassword; vm.toggleChangePassword = toggleChangePassword;
vm.changeProfile = changeProfile; vm.confirmToUpdate = confirmToUpdate;
vm.changePassword= changePassword; vm.updateUser = updateUser;
vm.cancel = cancel; vm.cancel = cancel;
$scope.user = currentUser.get();
vm.user = currentUser.get(); var userId = $scope.user.user_id;
function reset() { function reset() {
$scope.form.$setUntouched();
$scope.form.$setPristine();
vm.hasError = false; vm.hasError = false;
vm.errorMessage = ''; vm.errorMessage = '';
} }
@ -38,24 +39,43 @@
} }
} }
function getCurrentUserFailed(data) { function confirmToUpdate(user) {
console.log('Failed get current user:' + data); vm.user = user;
if(vm.isOpen) {
if(vm.user && angular.isDefined(user.oldPassword) && angular.isDefined(user.password)) {
vm.modalTitle = $filter('tr')('change_password', []);
vm.modalMessage = $filte('tr')('confirm_to_change_password', []);
return true;
}
}else{
if(vm.user && angular.isDefined(vm.user.username) && angular.isDefined(vm.user.password) &&
angular.isDefined(vm.user.realname)) {
vm.modalTitle = $filter('tr')('change_profile', []);
vm.modalMessage = $filter('tr')('confirm_to_change_profile', []);
return true;
}
} }
function changeProfile(user) { vm.modalTitle = $filter('tr')('form_is_invalid');
console.log(user); vm.modalMessage = $filter('tr')('form_is_invalid_message', []);
return false;
} }
function changePassword(user) { function updateUser() {
if(user && angular.isDefined(user.oldPassword) && angular.isDefined(user.password)) { if(vm.isOpen){
ChangePasswordService(vm.user.user_id, user.oldPassword, user.password) ChangePasswordService(userId, vm.user.oldPassword, vm.user.password)
.success(changePasswordSuccess) .success(changePasswordSuccess)
.error(changePasswordFailed); .error(changePasswordFailed);
}else{
UpdateUserService(userId, vm.user)
.success(updateUserSuccess)
.error(updateUserFailed);
currentUser.set(vm.user);
} }
} }
function changePasswordSuccess(data, status) { function changePasswordSuccess(data, status) {
$window.location.href = '/project'; $window.location.href = '/dashboard';
} }
function changePasswordFailed(data, status) { function changePasswordFailed(data, status) {
@ -66,11 +86,16 @@
} }
} }
function cancel(form) { function updateUserSuccess(data, status) {
if(form) { $window.location.href = '/dashboard';
form.$setPristine();
} }
$window.location.href = '/project';
function updateUserFailed(data, status) {
console.log('Failed update user.');
}
function cancel(form) {
$window.location.href = '/dashboard';
} }
} }

View File

@ -6,7 +6,28 @@
.module('harbor.layout.index') .module('harbor.layout.index')
.controller('IndexController', IndexController); .controller('IndexController', IndexController);
function IndexController() { IndexController.$inject = ['$filter', 'trFilter'];
function IndexController($filter, trFilter) {
var vm = this;
var indexDesc = $filter('tr')('index_desc', []);
var indexDesc1 = $filter('tr')('index_desc_1', []);
var indexDesc2 = $filter('tr')('index_desc_2', []);
var indexDesc3 = $filter('tr')('index_desc_3', []);
var indexDesc4 = $filter('tr')('index_desc_4', []);
var indexDesc5 = $filter('tr')('index_desc_5', []);
vm.message = '<p class="page-content text-justify">' +
indexDesc +
'</p>' +
'<ul>' +
'<li class="long-line">▪︎ ' + indexDesc1 + '</li>' +
'<li class="long-line">▪︎ ' + indexDesc2 + '</li>' +
'<li class="long-line">▪︎ ' + indexDesc3 + '</li>' +
'<li class="long-line">▪︎ ' + indexDesc4 + '</li>' +
'<li class="long-line">▪︎ ' + indexDesc5 + '</li>' +
'</ul>';
} }

View File

@ -14,7 +14,7 @@ var locale_messages = {
'index_desc_3': 'Access Control: RBAC (Role Based Access Control) is provided. User management can be integrated with existing enterprise identity services like AD/LDAP. ', 'index_desc_3': 'Access Control: RBAC (Role Based Access Control) is provided. User management can be integrated with existing enterprise identity services like AD/LDAP. ',
'index_desc_4': 'Audit: All access to the registry are logged and can be used for audit purpose.', 'index_desc_4': 'Audit: All access to the registry are logged and can be used for audit purpose.',
'index_desc_5': 'GUI: User friendly single-pane-of-glass management console.', 'index_desc_5': 'GUI: User friendly single-pane-of-glass management console.',
'learn_more': 'Learn more...', 'view_all': 'View all...',
'repositories': 'Repositories', 'repositories': 'Repositories',
'project_repo_name': 'Project/Repository Name', 'project_repo_name': 'Project/Repository Name',
'creation_time': 'Creation Time', 'creation_time': 'Creation Time',
@ -51,8 +51,8 @@ var locale_messages = {
'public_projects': 'Public Projects', 'public_projects': 'Public Projects',
'public': 'Public', 'public': 'Public',
'public_repositories': 'Public Repositories', 'public_repositories': 'Public Repositories',
'my_project_count': 'Projects', 'my_project_count': 'My Projects',
'my_repo_count': 'Repositories', 'my_repo_count': 'My Repositories',
'public_project_count': 'Public Projects', 'public_project_count': 'Public Projects',
'public_repo_count': 'Public Repositories', 'public_repo_count': 'Public Repositories',
'total_project_count': 'Total Projects', 'total_project_count': 'Total Projects',
@ -160,5 +160,13 @@ var locale_messages = {
'destination_setting': 'Destination Setting', 'destination_setting': 'Destination Setting',
'endpoint': 'Endpoint', 'endpoint': 'Endpoint',
'test_connection': 'Test connection', 'test_connection': 'Test connection',
'add_new_destination': 'New Destination' 'add_new_destination': 'New Destination',
'confirm_to_change_password': 'Are you sure to change your password?',
'change_profile': 'Change Profile',
'confirm_to_change_profile': 'Are you sure to change your profile?',
'form_is_invalid': 'Form content is invalid',
'form_is_invalid_message': 'Form content is invalid, please fill the required fields.',
'administrator': 'Administrator',
'popular_repositories': 'Popular Repositories',
'harbor_intro_title': 'About Harbor'
}; };

View File

@ -14,7 +14,7 @@ var locale_messages = {
'index_desc_3': '访问控制: 提供基于角色的访问控制,可集成企业目前拥有的用户管理系统(如:AD/LDAP。', 'index_desc_3': '访问控制: 提供基于角色的访问控制,可集成企业目前拥有的用户管理系统(如:AD/LDAP。',
'index_desc_4': '审计: 所有访问Registry服务的操作均被记录便于日后审计。', 'index_desc_4': '审计: 所有访问Registry服务的操作均被记录便于日后审计。',
'index_desc_5': '管理界面: 具有友好易用图形管理界面。', 'index_desc_5': '管理界面: 具有友好易用图形管理界面。',
'learn_more': '更多...', 'view_all': '显示全部...',
'repositories': '镜像仓库', 'repositories': '镜像仓库',
'project_repo_name': '项目/镜像仓库名称', 'project_repo_name': '项目/镜像仓库名称',
'creation_time': '创建时间', 'creation_time': '创建时间',
@ -51,8 +51,8 @@ var locale_messages = {
'public_projects': '公开项目', 'public_projects': '公开项目',
'public': '公开', 'public': '公开',
'public_repositories': '公开镜像仓库', 'public_repositories': '公开镜像仓库',
'my_project_count': '项目', 'my_project_count': '我的项目',
'my_repo_count': '镜像仓库', 'my_repo_count': '我的镜像仓库',
'public_project_count': '公开项目', 'public_project_count': '公开项目',
'public_repo_count': '公开镜像仓库', 'public_repo_count': '公开镜像仓库',
'total_project_count': '全部项目', 'total_project_count': '全部项目',
@ -159,5 +159,13 @@ var locale_messages = {
'endpoint': '终端URL', 'endpoint': '终端URL',
'endpoint_is_required': '终端URL为必填项。', 'endpoint_is_required': '终端URL为必填项。',
'test_connection': '测试连接', 'test_connection': '测试连接',
'add_new_destination': '新建目标' 'add_new_destination': '新建目标',
'confirm_to_change_password': '确认要修改密码吗?',
'change_profile': '修改个人信息',
'confirm_to_change_profile': '确认要修改个人信息吗?',
'form_is_invalid': '表单内容无效',
'form_is_invalid_message': '表单内容无效,请填写必填字段。',
'administrator': '管理员',
'popular_repositories': '热门镜像仓库',
'harbor_intro_title': '关于 Harbor'
}; };

View File

@ -0,0 +1,24 @@
(function() {
'use strict';
angular
.module('harbor.services.user')
.factory('UpdateUserService', UpdateUserService);
UpdateUserService.$inject = ['$http'];
function UpdateUserService($http) {
return updateUser;
function updateUser(userId, user) {
return $http
.put('/api/users/' + userId, {
'username': user.username,
'email': user.email,
'realname': user.realname,
'comment': user.comment
});
}
}
})();

View File

@ -4,11 +4,12 @@
<div class="section"> <div class="section">
<h1 class="col-md-12 col-md-offset-2 main-title title-color">// 'account_setting' | tr //</h1> <h1 class="col-md-12 col-md-offset-2 main-title title-color">// 'account_setting' | tr //</h1>
<div class="col-md-12 col-md-offset-2 main-content"> <div class="col-md-12 col-md-offset-2 main-content">
<form name="form" class="form-horizontal" ng-submit="form.$valid && vm.changeProile(user)" > <modal-dialog title="//vm.modalTitle//" message="//vm.modalMessage//" action="vm.updateUser()"></modal-dialog>
<form name="form" class="css-form form-horizontal" novalidate>
<div class="form-group"> <div class="form-group">
<label for="username" class="col-sm-3 control-label">// 'username' | tr //:</label> <label for="username" class="col-sm-3 control-label">// 'username' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="text" class="form-control" id="username" ng-model="user.username" ng-value="vm.user.username" name="uUsername" ng-model-options="{ updateOn: 'blur' }" ng-disabled="true" required maxlength="20" invalid-chars> <input type="text" class="form-control" id="username" ng-model="user.username" name="uUsername" ng-disabled="vm.isOpen" required maxlength="20" invalid-chars>
<div ng-messages="form.$submitted && form.uUsername.$error"> <div ng-messages="form.$submitted && form.uUsername.$error">
<span ng-message="required">// 'username_is_required' | tr //</span> <span ng-message="required">// 'username_is_required' | tr //</span>
<span ng-message="maxlength">// 'username_is_too_long' | tr //</span> <span ng-message="maxlength">// 'username_is_too_long' | tr //</span>
@ -22,7 +23,7 @@
<div class="form-group"> <div class="form-group">
<label for="email" class="col-sm-3 control-label">// 'email' | tr //:</label> <label for="email" class="col-sm-3 control-label">// 'email' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="email" class="form-control" id="email" ng-model="user.email" ng-value="vm.user.email" ng-model-options="{ updateOn: 'blur' }" ng-disabled="true" name="uEmail" required> <input type="email" class="form-control" id="email" ng-model="user.email" name="uEmail" ng-disabled="vm.isOpen" required>
<div ng-messages="form.$submitted && form.uEmail.$error"> <div ng-messages="form.$submitted && form.uEmail.$error">
<span ng-message="required">// 'email_is_required' | tr //</span> <span ng-message="required">// 'email_is_required' | tr //</span>
<span ng-message="email">// 'email_content_illegal' | tr //</span> <span ng-message="email">// 'email_content_illegal' | tr //</span>
@ -35,7 +36,7 @@
<div class="form-group"> <div class="form-group">
<label for="fullName" class="col-sm-3 control-label">// 'full_name' | tr //:</label> <label for="fullName" class="col-sm-3 control-label">// 'full_name' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="text" class="form-control" id="fullName" ng-model="user.fullName" name="uFullName" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.user.realname" ng-disabled="true" required maxlength="20" invalid-chars> <input type="text" class="form-control" id="fullName" ng-model="user.realname" name="uFullName" ng-disabled="vm.isOpen" required maxlength="20" invalid-chars>
<div ng-messages="form.$submitted && form.uFullName.$error"> <div ng-messages="form.$submitted && form.uFullName.$error">
<span ng-message="required">// 'full_name_is_required' | tr //</span> <span ng-message="required">// 'full_name_is_required' | tr //</span>
<span ng-message="invalidChars">// 'full_name_contains_illegal_chars' | tr //</span> <span ng-message="invalidChars">// 'full_name_contains_illegal_chars' | tr //</span>
@ -49,14 +50,12 @@
<div class="form-group"> <div class="form-group">
<label for="comments" class="col-sm-3 control-label">// 'comments' | tr //:</label> <label for="comments" class="col-sm-3 control-label">// 'comments' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="text" class="form-control" id="comments" ng-model="user.comment" name="uComments" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.user.comment" ng-disabled="true" ng-model-options="{ updateOn: 'blur' }" maxlength="20"> <input type="text" class="form-control" id="comments" ng-model="user.comment" name="uComments" ng-disabled="vm.isOpen" maxlength="20">
<div ng-messages="form.$submitted && form.uComments.$error"> <div ng-messages="form.$submitted && form.uComments.$error">
<span ng-show="maxlength">// 'comment_is_too_long' | tr //</span> <span ng-show="maxlength">// 'comment_is_too_long' | tr //</span>
</div> </div>
</div> </div>
</div> </div>
</form>
<form name="form" class="form-horizontal css-form" ng-submit="form.$valid && vm.changePassword(user)" novalidate>
<div class="form-group"> <div class="form-group">
<label for="toggleChangePassword" class="col-sm-3 control-label"><a id="toggleChangePassword" href="#" ng-click="vm.toggleChangePassword()">// 'change_password' | tr //</a></label> <label for="toggleChangePassword" class="col-sm-3 control-label"><a id="toggleChangePassword" href="#" ng-click="vm.toggleChangePassword()">// 'change_password' | tr //</a></label>
</div> </div>
@ -65,8 +64,8 @@
<div class="form-group"> <div class="form-group">
<label for="oldPassword" class="col-sm-3 control-label">// 'old_password' | tr //:</label> <label for="oldPassword" class="col-sm-3 control-label">// 'old_password' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="password" class="form-control" id="oldPassword" ng-model="user.oldPassword" ng-change="vm.reset()" name="uOldPassword" ng-model-options="{ updateOn: 'blur' }" required> <input type="password" class="form-control" id="oldPassword" ng-model="user.oldPassword" ng-change="vm.reset()" name="uOldPassword" required>
<div class="error-message" ng-messages="form.uOldPassword.$error" ng-if="form.uOldPassword.$touched"> <div class="error-message" ng-messages="vm.isOpen && form.$submitted && form.uOldPassword.$touched && form.uOldPassword.$error">
<span ng-message="required">// 'old_password_is_required' | tr //</span> <span ng-message="required">// 'old_password_is_required' | tr //</span>
</div> </div>
</div> </div>
@ -77,8 +76,8 @@
<div class="form-group"> <div class="form-group">
<label for="password" class="col-sm-3 control-label">// 'new_password' | tr //:</label> <label for="password" class="col-sm-3 control-label">// 'new_password' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="password" class="form-control" id="password" ng-model="user.password" ng-change="vm.reset()" name="uPassword" ng-model-options="{ updateOn: 'blur' }" required password> <input type="password" class="form-control" id="password" ng-model="user.password" ng-change="vm.reset()" name="uPassword" required password>
<div class="error-message" ng-messages="form.uPassword.$error" ng-if="form.uPassword.$touched"> <div class="error-message" ng-messages="vm.isOpen && form.$submitted && form.uPassword.$touched && form.uPassword.$error">
<span ng-message="required">// 'password_is_required' | tr //</span> <span ng-message="required">// 'password_is_required' | tr //</span>
<span ng-message="password">// 'password_is_invalid' | tr //</span> <span ng-message="password">// 'password_is_invalid' | tr //</span>
</div> </div>
@ -92,7 +91,7 @@
<label for="confirmPassword" class="col-sm-3 control-label">// 'confirm_password' | tr //:</label> <label for="confirmPassword" class="col-sm-3 control-label">// 'confirm_password' | tr //:</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="password" class="form-control" id="confirmPassword" ng-model="user.confirmPassword" ng-change="vm.reset()" name="uConfirmPassword" ng-model-options="{ updateOn: 'blur' }" compare-to="user.password"> <input type="password" class="form-control" id="confirmPassword" ng-model="user.confirmPassword" ng-change="vm.reset()" name="uConfirmPassword" ng-model-options="{ updateOn: 'blur' }" compare-to="user.password">
<div class="error-message" ng-messages="form.uConfirmPassword.$error" ng-if="form.uConfirmPassword.$touched"> <div class="error-message" ng-messages="vm.isOpen && form.$submitted && form.uConfirmPassword.$touched && form.uConfirmPassword.$error">
<span ng-message="compareTo">// 'password_does_not_match' | tr //</span> <span ng-message="compareTo">// 'password_does_not_match' | tr //</span>
</div> </div>
</div> </div>
@ -103,8 +102,8 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-md-offset-7 col-md-10"> <div class="col-md-offset-7 col-md-10">
<input type="submit" class="btn btn-primary" ng-disabled="form.$invalid" value="// 'save' | tr //"> <input type="submit" class="btn btn-primary" ng-click="vm.confirmToUpdate(user)" data-toggle="modal" data-target="#myModal" value="// 'save' | tr //">
<input type="submit" class="btn btn-default" ng-click="vm.cancel(form)" value="// 'cancel' | tr //"> <input type="button" class="btn btn-default" ng-click="vm.cancel(form)" value="// 'cancel' | tr //">
</div> </div>
</div> </div>
<div class="error-message"> <div class="error-message">

View File

@ -39,6 +39,7 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="row"> <div class="row">
<div class="down-section"> <div class="down-section">
<modal-dialog title="// 'harbor_intro_title' | tr //" message='// vm.message //' content-type="text/html"></modal-dialog>
<h4 class="page-header underlined">// 'why_use_harbor' | tr //</h4> <h4 class="page-header underlined">// 'why_use_harbor' | tr //</h4>
<p class="page-content text-justify"> <p class="page-content text-justify">
// 'index_desc' | tr // // 'index_desc' | tr //
@ -51,15 +52,14 @@
<li class="long-line">▪︎ // 'index_desc_5' | tr //</li> <li class="long-line">▪︎ // 'index_desc_5' | tr //</li>
</ul> </ul>
<div class="page-content pull-right"> <div class="page-content pull-right">
<a href="#"><span class="glyphicon glyphicon-triangle-right"></span> // 'learn_more' | tr //</a> <a href="javascript:void(0);" data-toggle="modal" data-target="#myModal"><span class="glyphicon glyphicon-triangle-right"></span> // 'view_all' | tr //</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<div class="down-section"> <div class="down-section">
<h4 class="page-header title-color underlined">// 'repositories' | tr //</h4> <top-repository></top-repository>
<search filter-by="repository"></search>
</div> </div>
</div> </div>
</div> </div>

View File

@ -116,6 +116,7 @@
<script src="/static/resources/js/services/user/services.toggle-admin.js"></script> <script src="/static/resources/js/services/user/services.toggle-admin.js"></script>
<script src="/static/resources/js/services/user/services.delete-user.js"></script> <script src="/static/resources/js/services/user/services.delete-user.js"></script>
<script src="/static/resources/js/services/user/services.log-out.js"></script> <script src="/static/resources/js/services/user/services.log-out.js"></script>
<script src="/static/resources/js/services/user/services.update-user.js"></script>
<script src="/static/resources/js/services/repository/services.repository.module.js"></script> <script src="/static/resources/js/services/repository/services.repository.module.js"></script>
<script src="/static/resources/js/services/repository/services.list-repository.js"></script> <script src="/static/resources/js/services/repository/services.list-repository.js"></script>