login form styling. server validation errors displayed as sweet alerts

This commit is contained in:
Kyle Spearrin 2016-09-20 16:17:31 -04:00
parent 2fefdf8f6c
commit 47b500d7c0
11 changed files with 91 additions and 111 deletions

View File

@ -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 () {

View File

@ -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>

View File

@ -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">

View File

@ -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;
}
};
});

View File

@ -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);
});
}
});

View File

@ -1,2 +1,2 @@
angular
.module('bit.services', ['angular-jwt']);
.module('bit.services', ['angular-jwt', 'oitozero.ngSweetAlert']);

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 {