mirror of
https://github.com/bitwarden/desktop.git
synced 2024-10-15 06:47:57 +02:00
login form styling. server validation errors displayed as sweet alerts
This commit is contained in:
parent
2fefdf8f6c
commit
47b500d7c0
@ -2,7 +2,10 @@
|
||||
.module('bit.accounts')
|
||||
|
||||
.controller('accountsLoginController', function ($scope, $state, loginService, userService) {
|
||||
$scope.login = function (model) {
|
||||
popupUtils.initListSectionItemListeners();
|
||||
|
||||
$scope.loginPromise = null;
|
||||
$scope.login = function (model, form) {
|
||||
$scope.loginPromise = loginService.logIn(model.email, model.masterPassword);
|
||||
|
||||
$scope.loginPromise.then(function () {
|
||||
|
@ -1,22 +1,33 @@
|
||||
<ion-view view-title="bitwarden">
|
||||
<ion-content>
|
||||
<form name="theForm" ng-submit="theForm.$valid && login(model, theForm)" bit-form="loginPromise">
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<a ng-click="close()" href="">Cancel</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" class="btn btn-link" ng-show="!theForm.$loading">Log In</button>
|
||||
<i class="fa fa-spinner fa-lg" ng-show="theForm.$loading" ng-class="{'fa-spin' : theForm.$loading}"></i>
|
||||
</div>
|
||||
<div class="title">bitwarden</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="list">
|
||||
<label class="item item-input">
|
||||
<i class="icon ion-android-mail placeholder-icon"></i>
|
||||
<input type="text" placeholder="Email address" ng-model="model.email">
|
||||
</label>
|
||||
<label class="item item-input">
|
||||
<i class="icon ion-locked placeholder-icon"></i>
|
||||
<input type="password" placeholder="Master password" ng-model="model.masterPassword">
|
||||
</label>
|
||||
<div class="list-section">
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item list-section-item-icon-input">
|
||||
<i class="fa fa-envelope fa-lg fa-fw"></i>
|
||||
<label for="email" class="sr-only">Email Address</label>
|
||||
<input id="email" type="email" name="Email" placeholder="Email Address" ng-model="model.email">
|
||||
</div>
|
||||
<div class="list-section-item list-section-item-icon-input">
|
||||
<i class="fa fa-lock fa-lg fa-fw"></i>
|
||||
<label for="master-password" class="sr-only">Master Password</label>
|
||||
<input id="master-password" type="password" name="MasterPassword" placeholder="Master Password" ng-model="model.masterPassword">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="padding">
|
||||
<button class="button button-block button-positive" ng-click="login(model)">
|
||||
Log In
|
||||
</button>
|
||||
<p class="text-center">
|
||||
<a href="#/hint">Get master password hint</a>
|
||||
</p>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
<p class="text-center">
|
||||
<a href="#/hint">Get master password hint</a>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="right">
|
||||
<a href="" ng-click="addSite()"><i class="fa fa-plus fa-lg"></i></a>
|
||||
</div>
|
||||
<div class="title">Current Tab Sites</div>
|
||||
<div class="title">Current Tab</div>
|
||||
</div>
|
||||
<div class="content content-tabs">
|
||||
<div ng-if="sites.length">
|
||||
|
@ -1,30 +0,0 @@
|
||||
angular
|
||||
.module('bit.directives')
|
||||
|
||||
.directive('bitField', function () {
|
||||
var linkFn = function (scope, element, attrs, ngModel) {
|
||||
ngModel.$registerError = registerError;
|
||||
ngModel.$validators.validate = validator;
|
||||
|
||||
function validator() {
|
||||
ngModel.$setValidity('bit', true);
|
||||
return true;
|
||||
}
|
||||
|
||||
function registerError() {
|
||||
ngModel.$setValidity('bit', false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
require: 'ngModel',
|
||||
restrict: 'A',
|
||||
compile: function (elem, attrs) {
|
||||
if (!attrs.name || attrs.name === '') {
|
||||
throw 'bit-field element does not have a valid name attribute';
|
||||
}
|
||||
|
||||
return linkFn;
|
||||
}
|
||||
};
|
||||
});
|
@ -18,9 +18,6 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// reset errors
|
||||
form.$errors = null;
|
||||
|
||||
// start loading
|
||||
form.$loading = true;
|
||||
|
||||
@ -28,8 +25,7 @@
|
||||
form.$loading = false;
|
||||
}, function failure(reason) {
|
||||
form.$loading = false;
|
||||
validationService.addErrors(form, reason);
|
||||
scope.$broadcast('show-errors-check-validity');
|
||||
validationService.showError(reason);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
angular
|
||||
.module('bit.services', ['angular-jwt']);
|
||||
.module('bit.services', ['angular-jwt', 'oitozero.ngSweetAlert']);
|
||||
|
@ -1,61 +1,47 @@
|
||||
angular
|
||||
.module('bit.services')
|
||||
|
||||
.factory('validationService', function () {
|
||||
.factory('validationService', function (SweetAlert) {
|
||||
var _service = {};
|
||||
|
||||
_service.addErrors = function (form, reason) {
|
||||
var data = reason.data;
|
||||
_service.showError = function (data) {
|
||||
var defaultErrorMessage = 'An unexpected error has occured.';
|
||||
form.$errors = [];
|
||||
var errors = [];
|
||||
|
||||
if (!data || !angular.isObject(data)) {
|
||||
form.$errors.push(defaultErrorMessage);
|
||||
return;
|
||||
errors.push(defaultErrorMessage);
|
||||
}
|
||||
|
||||
if (!data.validationErrors) {
|
||||
else if (!data.validationErrors) {
|
||||
if (data.message) {
|
||||
form.$errors.push(data.message);
|
||||
errors.push(data.message);
|
||||
}
|
||||
else {
|
||||
form.$errors.push(defaultErrorMessage);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (var key in data.validationErrors) {
|
||||
if (!data.validationErrors.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.validationErrors[key].length; i++) {
|
||||
_service.addError(form, key, data.validationErrors[key][i]);
|
||||
errors.push(defaultErrorMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
else {
|
||||
for (var key in data.validationErrors) {
|
||||
if (!data.validationErrors.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_service.addError = function (form, key, errorMessage, clearExistingErrors) {
|
||||
if (clearExistingErrors || !form.$errors) {
|
||||
form.$errors = [];
|
||||
}
|
||||
|
||||
var pushError = true;
|
||||
for (var i = 0; i < form.$errors.length; i++) {
|
||||
if (form.$errors[i] === errorMessage) {
|
||||
pushError = false;
|
||||
break;
|
||||
for (var i = 0; i < data.validationErrors[key].length; i++) {
|
||||
errors.push(data.validationErrors[key][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pushError) {
|
||||
form.$errors.push(errorMessage);
|
||||
if (errors.length) {
|
||||
SweetAlert.swal({
|
||||
title: 'Error',
|
||||
text: errors[0],
|
||||
type: 'error',
|
||||
showCancelButton: false,
|
||||
confirmButtonText: 'Ok'
|
||||
});
|
||||
}
|
||||
|
||||
if (key && key !== '' && form[key] && form[key].$registerError) {
|
||||
form[key].$registerError();
|
||||
}
|
||||
return errors;
|
||||
};
|
||||
|
||||
return _service;
|
||||
|
@ -18,19 +18,19 @@
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<label for="name" class="item-label">Name</label>
|
||||
<input id="name" type="text" name="Name" ng-model="site.name" bit-field>
|
||||
<input id="name" type="text" name="Name" ng-model="site.name">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="uri" class="item-label">URI</label>
|
||||
<input id="uri" type="text" name="Uri" ng-model="site.uri" bit-field>
|
||||
<input id="uri" type="text" name="Uri" ng-model="site.uri">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="username" class="item-label">Username</label>
|
||||
<input id="username" type="text" name="Username" ng-model="site.username" bit-field>
|
||||
<input id="username" type="text" name="Username" ng-model="site.username">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="password" class="item-label">Password</label>
|
||||
<input id="password" type="password" name="Password" ng-model="site.password" bit-field>
|
||||
<input id="password" type="password" name="Password" ng-model="site.password">
|
||||
</div>
|
||||
<a class="list-section-item" href="" ng-click="generatePassword()">
|
||||
Generate Password
|
||||
@ -42,13 +42,13 @@
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<label for="folder" class="item-label">Folder</label>
|
||||
<select id="folder" name="FolderId" ng-model="site.folderId" bit-field>
|
||||
<select id="folder" name="FolderId" ng-model="site.folderId">
|
||||
<option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}">{{folder.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="list-section-item list-section-item-checkbox">
|
||||
<label for="favorite">Favorite</label>
|
||||
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite" bit-field>
|
||||
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes" bit-field></textarea>
|
||||
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -18,19 +18,19 @@
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<label for="name" class="item-label">Name</label>
|
||||
<input id="name" type="text" name="Name" ng-model="site.name" bit-field>
|
||||
<input id="name" type="text" name="Name" ng-model="site.name">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="uri" class="item-label">URI</label>
|
||||
<input id="uri" type="text" name="Uri" ng-model="site.uri" bit-field>
|
||||
<input id="uri" type="text" name="Uri" ng-model="site.uri">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="username" class="item-label">Username</label>
|
||||
<input id="username" type="text" name="Username" ng-model="site.username" bit-field>
|
||||
<input id="username" type="text" name="Username" ng-model="site.username">
|
||||
</div>
|
||||
<div class="list-section-item">
|
||||
<label for="password" class="item-label">Password</label>
|
||||
<input id="password" type="password" name="Password" ng-model="site.password" bit-field>
|
||||
<input id="password" type="password" name="Password" ng-model="site.password">
|
||||
</div>
|
||||
<a class="list-section-item" href="" ng-click="generatePassword()">
|
||||
Generate Password
|
||||
@ -42,13 +42,13 @@
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<label for="folder" class="item-label">Folder</label>
|
||||
<select id="folder" name="FolderId" ng-model="site.folderId" bit-field>
|
||||
<select id="folder" name="FolderId" ng-model="site.folderId">
|
||||
<option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}">{{folder.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="list-section-item list-section-item-checkbox">
|
||||
<label for="favorite">Favorite</label>
|
||||
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite" bit-field>
|
||||
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
<div class="list-section-items">
|
||||
<div class="list-section-item">
|
||||
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes" bit-field></textarea>
|
||||
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -38,7 +38,6 @@
|
||||
|
||||
<script src="app/directives/directivesModule.js"></script>
|
||||
<script src="app/directives/formDirective.js"></script>
|
||||
<script src="app/directives/fieldDirective.js"></script>
|
||||
|
||||
<script src="app/services/servicesModule.js"></script>
|
||||
<script src="app/services/backgroundService.js"></script>
|
||||
|
@ -348,6 +348,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.list-section-item-icon-input {
|
||||
padding: 15px 15px;
|
||||
|
||||
.fa {
|
||||
float: left;
|
||||
color: @list-icon-color;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
input {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.list-no-selection {
|
||||
|
Loading…
Reference in New Issue
Block a user