Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web client/part 05 rest of app #19

Merged
merged 26 commits into from Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
75d5564
workflow for adding new book
rpmartz Jul 5, 2016
fe33270
add semicolons to appease codacy
rpmartz Jul 9, 2016
74c0eed
remove extra debugging statements from success callbacks
rpmartz Jul 10, 2016
eb3a495
change title
rpmartz Jul 10, 2016
4d46e15
us simple list to show books
rpmartz Jul 10, 2016
9262afe
pretty much best designer ever
rpmartz Jul 10, 2016
0ed8e5f
add view book functions and views
rpmartz Jul 11, 2016
c3f9608
add edit book workflow
rpmartz Jul 11, 2016
09164a3
add angular bootstrap to bower.json
rpmartz Jul 11, 2016
7ddba08
get delete modal popping up
rpmartz Jul 13, 2016
a00bf66
add ability to delete book
rpmartz Jul 14, 2016
9ee546a
rename controller
rpmartz Jul 14, 2016
2c7e040
break out of the loop after finding book to remove
rpmartz Jul 14, 2016
0c67e01
view book page implemented
rpmartz Jul 14, 2016
28bcf6e
update edit link
rpmartz Jul 14, 2016
2c5a357
hardcode panel title
rpmartz Jul 15, 2016
e9f201b
add link to return to all books
rpmartz Jul 15, 2016
1410c9c
add header and style to books page
rpmartz Jul 15, 2016
78e1b32
add pagination to all books
rpmartz Jul 17, 2016
bb6e1c3
add bootswatch
rpmartz Jul 17, 2016
9a7a1bd
add book title to delete book confirmation modal
rpmartz Jul 17, 2016
8acb9d6
add concatenation comments to index.html
rpmartz Jul 18, 2016
9075e09
add useref plugin
rpmartz Jul 18, 2016
b14e433
fix name of vendor.js
rpmartz Jul 18, 2016
eba64d9
make default build task concatenate JS files
rpmartz Jul 20, 2016
0d81aaf
see if its the +2 causing bower to break
rpmartz Jul 20, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion bower.json
Expand Up @@ -12,7 +12,11 @@
"angular": "^1.5.5",
"angular-route": "^1.5.5",
"angular-messages": "^1.5.7",
"a0-angular-storage": "^0.0.15"
"a0-angular-storage": "^0.0.15",
"angular-bootstrap": "^1.3.3",
"angular-markdown-directive": "^0.3.1",
"angular-sanitize": "^1.5.7",
"bootswatch": "^3.3.6"
},
"devDependencies": {
"angular-mocks": "^1.5.7"
Expand Down
13 changes: 12 additions & 1 deletion gulpfile.js
Expand Up @@ -6,6 +6,7 @@ var runSequence = require('run-sequence');
var Server = require('karma').Server;
var protractor = require('gulp-protractor').protractor;
var bower = require('gulp-bower');
var useref = require('gulp-useref');

gulp.task('bower', function () {
return bower();
Expand Down Expand Up @@ -58,7 +59,17 @@ gulp.task('itest', function () {
});
});

gulp.task('build', function () {
gulp.task('concat', function () {
return gulp.src('src/main/resources/static/index.html')
.pipe(useref())
.pipe(gulp.dest('src/main/resources/static'));
});

gulp.task('build:dev', function () {
runSequence('bower', 'wiredep', 'inject');
});

gulp.task('build', function () {
runSequence('bower', 'wiredep', 'inject', 'concat');
});

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -26,6 +26,7 @@
"gulp-bower": "0.0.13",
"gulp-inject": "^4.1.0",
"gulp-protractor": "^2.3.0",
"gulp-useref": "^3.1.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-jasmine": "^1.0.2",
Expand Down
11 changes: 10 additions & 1 deletion src/main/resources/static/app/js/app.js
@@ -1,7 +1,7 @@
(function () {
'use strict';

angular.module('booktrackrApp', ['ngRoute', 'ngMessages', 'angular-storage']);
angular.module('booktrackrApp', ['ngRoute', 'ngMessages', 'angular-storage', 'ui.bootstrap', 'ngSanitize', 'btford.markdown']);

angular.module('booktrackrApp').config(['$routeProvider', '$httpProvider', function ($routeProvider, $httpProvider) {
$routeProvider
Expand All @@ -13,6 +13,15 @@
.when('/books', {
templateUrl: 'partials/books.html'
})
.when('/books/new', {
templateUrl: 'partials/new-book.html'
})
.when('/books/:bookId/edit', {
templateUrl: 'partials/edit-book.html'
})
.when('/books/:bookId/view', {
templateUrl: 'partials/view-book.html'
})
.when('/login', {
templateUrl: 'partials/login.html'
})
Expand Down
133 changes: 118 additions & 15 deletions src/main/resources/static/app/js/controllers.js
Expand Up @@ -5,34 +5,37 @@
.controller('HomeController', HomeController)
.controller('SignupController', SignupController)
.controller('LoginController', LoginController)
.controller('BooksController', BooksController);
.controller('BooksController', BooksController)
.controller('NewBookController', NewBookController)
.controller('ViewBookController', ViewBookController)
.controller('EditBookController', EditBookController)
.controller('DeleteBookController', DeleteBookController);

HomeController.$inject = ['Book', '$log'];
function HomeController(Book, $log) {
var vm = this;

Book.all().then(function (res) {
$log.info(res.data);
vm.books = res.data;

}, function (err) {
$log.info(err)
})
$log.error('all books call failed: ', err);
});
}

SignupController.$inject = ['AuthService', '$log'];
function SignupController(AuthService, $log) {
SignupController.$inject = ['AuthService', '$log', '$location'];
function SignupController(AuthService, $log, $location) {
var vm = this;

vm.newUser = {};

vm.signup = function () {
AuthService.signup(vm.newUser)
.then(function (res) {
$log.info('Signup succeeded', res);
$location.path('/books');
},
function (err) {
$log.error('Signup failed ', err);
})
});

}

Expand All @@ -52,24 +55,124 @@
$location.path('/books');
},
function (err) {
$log.debug('Auth Failed');
$log.error('Auth Failed ', err);
// todo show failed auth message
})
}


}

BooksController.$inject = ['Book', '$log'];
function BooksController(Book, $log) {
BooksController.$inject = ['Book', '$log', '$uibModal'];
function BooksController(Book, $log, $uibModal) {
var vm = this;
vm.books = [];
vm.visibleBooks = [];
vm.currentPage = 1;

vm.updatePage = function (currentPage) {
var endIndex = (5 * currentPage);
var startIndex = endIndex - 5;
vm.visibleBooks = vm.books.slice(startIndex, endIndex);
};

Book.all().then(function (res) {
$log.debug('Books response: ', res);
vm.books = res.data;
vm.totalBooks = res.data.length;
vm.updatePage(vm.currentPage);

}, function (err) {
$log.error('all books call failed', err);
});

vm.openDeleteModal = function (book) {
var modalInstance = $uibModal.open({
templateUrl: 'deleteBookModal.html',
controller: 'DeleteBookController',
resolve: {
book: book
}
});

modalInstance.result.then(function (bookToDelete) {
for (var i = 0; i <= vm.books.length - 1; i++) {
if (vm.books[i].id == bookToDelete.id) {
vm.books.splice(i, 1);
break;
}
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
}
}

DeleteBookController.$inject = ['Book', '$log', '$scope', '$uibModalInstance', 'book'];
function DeleteBookController(Book, $log, $scope, $uibModalInstance, book) {
$scope.book = book;

$scope.ok = function () {
Book.delete(book).then(function (res) {
$uibModalInstance.close($scope.book);
}, function (err) {
$log.error('Error deleting book ', err);
});

};

$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}

NewBookController.$inject = ['Book', '$location', '$log'];
function NewBookController(Book, $location, $log) {
var vm = this;
vm.book = {};

vm.save = function () {
Book.create(vm.book).then(function () {
$location.path('/books');
}, function (err) {
$log.debug('error creating new book', err);
})
}
}

EditBookController.$inject = ['Book', '$location', '$routeParams'];
function EditBookController(Book, $location, $routeParams) {
var vm = this;
vm.book = {};

var currentBookId = $routeParams.bookId;
Book.getBook($routeParams.bookId).then(
function (res) {
vm.book = res.data;
},
function (err) {
$log.error('Error getting book by ID');
}
);

vm.save = function () {
Book.update(currentBookId, vm.book).then(function (res) {
$location.path('/books');
}, function (err) {
$log.error('save book failed', err);
})
};
}

ViewBookController.$inject = ['Book', '$location', '$log', '$routeParams'];
function ViewBookController(Book, $location, $log, $routeParams) {
var vm = this;

Book.getBook($routeParams.bookId).then(
function (res) {
vm.book = res.data;
},
function (err) {
$log.error('Error fetching book');
}
);
}

})();
25 changes: 24 additions & 1 deletion src/main/resources/static/app/js/services/services.js
Expand Up @@ -6,13 +6,36 @@

function Book($http) {
var service = {
all: allBooks
all: allBooks,
create: create,
delete: deleteBook,
getBook: getBook,
update: update
};

function allBooks() {
return $http.get('/books');
}

function create(newBook) {
return $http.post('/books', newBook);
}

function deleteBook(book) {
var url = '/books/' + book.id;
return $http.delete(url);
}

function getBook(id) {
var bookId = '/books/' + id;
return $http.get(bookId);
}

function update(id, book) {
var path = '/books/' + id;
return $http.put(path, book);
}

return service;
}

Expand Down
9 changes: 7 additions & 2 deletions src/main/resources/static/index.html
Expand Up @@ -3,18 +3,23 @@
<head>
<meta charset="UTF-8">
<title>Booktrackr</title>
<!-- bower:css -->
<!-- endbower -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/superhero/bootstrap.min.css"/>

<!-- inject:css -->
<!-- endinject -->
</head>
<body ng-app="booktrackrApp">
<div class="container" ng-view></div>

<!-- build:js app/js/vendor.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->

<!-- build:js app/js/booktrackr.js -->
<!-- inject:js -->
<!-- endinject -->
<!-- endbuild -->

</body>
</html>
44 changes: 38 additions & 6 deletions src/main/resources/static/partials/books.html
@@ -1,8 +1,40 @@
<div class="row">
<div class="col-xs-6 col-xs-offset-3" ng-controller="BooksController as books">
<h2>Books</h2>
<ul ng-repeat="book in books.books">
<li>{{ book.title }}</li>
</ul>
<div class="row" ng-controller="BooksController as books">
<div class="col-xs-6 col-xs-offset-3">
<div class="page-header">
<h3>My Books</h3>
</div>
<div ng-repeat="book in books.visibleBooks">
<div class="panel panel-info">
<div class="panel-heading">
<a href="#/books/{{ book.id }}/view" style="color:#ebebeb"><span class="panel-title">{{ book.title }}</span></a>
<a class="pull-right btn btn-sm btn-danger" ng-click="books.openDeleteModal(book)">
<span class="glyphicon glyphicon-trash"></span>
</a>
<a class="pull-right btn btn-sm btn-success" href="#/books/{{ book.id }}/edit">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</div>
<div class="panel-body">
{{ book.author }}
</div>
</div>
</div>
<uib-pagination total-items="books.totalBooks" ng-model="books.currentPage" items-per-page="5"
ng-change="books.updatePage(books.currentPage)"></uib-pagination>
<a class="btn btn-primary pull-right" href="#/books/new">
<span class="glyphicon glyphicon-plus"></span> Add Book
</a>
</div>
<script type="text/ng-template" id="deleteBookModal.html">
<div class="modal-header">
<h3 class="modal-title">Confirm Deletion</h3>
</div>
<div class="modal-body">
Are you sure you want to delete {{ book.title }}?
</div>
<div class="modal-footer">
<button class="btn btn-info" type="button" ng-click="ok()">OK</button>
<button class="btn btn-danger" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
</div>
26 changes: 26 additions & 0 deletions src/main/resources/static/partials/edit-book.html
@@ -0,0 +1,26 @@
<div class="row" ng-controller="EditBookController as book">
<div class="col-xs-6 col-xs-offset-3">
<h3>Edit Book</h3>
<form novalidate name="bookForm">
<div class="form-group">
<label for="title">Title</label>
<input type="text" ng-model="book.book.title" class="form-control" placeholder="Title"
ng-required="true">
</div>
<div class="form-group">
<label for="author">Author</label>
<input type="text" ng-model="book.book.author" class="form-control" placeholder="Author"
ng-required="true">
</div>
<div class="form-group">
<label for="notes">Notes</label>
<textarea rows="20" name="notes" ng-model="book.book.notes" class="form-control"></textarea>
</div>
<div class="form-group pull-right">
<a href="#/books" class="btn btn-danger">Cancel</a>
<button class="btn btn-info" ng-click="book.save()" ng-disabled="bookForm.$invalid">Save
</button>
</div>
</form>
</div>
</div>