slavailchenko35 6 lat temu
commit
be7a0278e3
37 zmienionych plików z 10403 dodań i 0 usunięć
  1. 39 0
      app/app.config.js
  2. 6 0
      app/app.module.js
  3. 26 0
      app/app.routes.js
  4. 3 0
      app/constants/webApi.com.js
  5. 39 0
      app/controllers/addBook.controller.js
  6. 21 0
      app/controllers/authors.controller.js
  7. 52 0
      app/controllers/bookdetails.controller.js
  8. 63 0
      app/controllers/bookslist.controller.js
  9. 19 0
      app/controllers/header.controller.js
  10. 33 0
      app/controllers/login.controller.js
  11. 13 0
      app/controllers/main.controller.js
  12. BIN
      app/directives/lang-switcher/images/en.png
  13. BIN
      app/directives/lang-switcher/images/ru.png
  14. 1 0
      app/directives/lang-switcher/lang-switcher.css
  15. 41 0
      app/directives/lang-switcher/lang-switcher.directive.js
  16. 10 0
      app/directives/lang-switcher/lang-switcher.template.html
  17. BIN
      app/img/noBook.png
  18. 28 0
      app/modals/add-book.template.html
  19. 16 0
      app/modals/confirm/confirm.controller.js
  20. 10 0
      app/modals/confirm/confirm.template.html
  21. 16 0
      app/services/account.factory.js
  22. 36 0
      app/services/books.factory.js
  23. 18 0
      app/services/utils.services.js
  24. 16 0
      app/views/authors.template.html
  25. 33 0
      app/views/books-details.template.html
  26. 32 0
      app/views/books-list.template.html
  27. 5 0
      app/views/footer.template.html
  28. 22 0
      app/views/header.template.html
  29. 1 0
      app/views/home.template.html
  30. 15 0
      app/views/login.template.html
  31. 6 0
      css/style.css
  32. 27 0
      i18n/en.json
  33. 27 0
      i18n/ru.json
  34. 42 0
      index.html
  35. 9643 0
      package-lock.json
  36. 28 0
      package.json
  37. 16 0
      webpack.config.js

+ 39 - 0
app/app.config.js

@@ -0,0 +1,39 @@
+app.run(function($rootScope, $location) {
+	$rootScope.$on('$routeChangeSuccess', function() {
+		$rootScope.currentMenuItem = $location.path() || '/home';
+	});
+
+});
+app.config(['$translateProvider', function($translateProvider) {
+	
+	$translateProvider.useStaticFilesLoader({
+		prefix: 'i18n/',
+		suffix: '.json'
+	});
+	$translateProvider.preferredLanguage(localStorage.getItem('preferredLanguage') || 'en');
+}]);
+
+// check authorization
+app.config(['$httpProvider', function($httpProvider) {
+
+	$httpProvider.interceptors.push(['$q', '$location', function($q, $location) {
+		return {
+			request: function(config) {
+				config.headers = config.headers || {};
+	
+				if (localStorage.getItem('authToken')) {
+					config.headers.Authorization = 'Bearer ' + localStorage.getItem('authToken');
+				}
+
+				return config;
+			},
+			responseError: function(response) {
+				if (response.status === 401) {
+					$location.path('/');
+				}
+
+				return $q.reject(response);
+			}
+		};
+	}]);
+}]);

+ 6 - 0
app/app.module.js

@@ -0,0 +1,6 @@
+var app = angular.module('fea5', [
+	'ngRoute',
+	'ui.bootstrap',
+	'cgNotify',
+	'pascalprecht.translate'
+	]);

+ 26 - 0
app/app.routes.js

@@ -0,0 +1,26 @@
+app.config(function($routeProvider, $locationProvider) {
+	$locationProvider.hashPrefix('');
+
+	$routeProvider
+	.when('/', {
+		templateUrl: 'app/views/home.template.html',
+		/*controller: 'Home'*/
+	})
+	.when('/login', {
+		templateUrl: 'app/views/login.template.html',
+		controller: 'Login'
+	})
+	.when('/books', {
+		templateUrl: 'app/views/books-list.template.html',
+		controller: 'BooksList'
+	})
+	.when('/books/:id', {
+		templateUrl: 'app/views/books-details.template.html',
+		controller: 'BookDetails'
+	})
+	.when('/authors', {
+		templateUrl: 'app/views/authors.template.html',
+		controller: 'Authors'
+	})
+	.otherwise('/');
+})

+ 3 - 0
app/constants/webApi.com.js

@@ -0,0 +1,3 @@
+app.constant('webApi', {
+	DOMAIN: 'http://helloworld.filonitta.fe4.a-level.com.ua'
+});

+ 39 - 0
app/controllers/addBook.controller.js

@@ -0,0 +1,39 @@
+(function(){
+    'use strict';
+    app.controller('AddBook', addBookController);
+    function addBookController($scope, $uibModalInstance, booksRepository){
+        $scope.newBook = {
+            title: '',
+            author_id: null,
+            date: "",
+            cost: '',
+            rate: '',
+            intro: ''
+        }
+        booksRepository.getAuthors()
+        .then(function(response){
+            $scope.authors = response.data.map(function(author){
+                return {
+                    id: author.id,
+                    name: author.firstname + ' ' + author.lastname
+                }
+            })
+        });
+        $scope.cancel = function(){
+            $uibModalInstance.dismiss('cancel'); 
+            // $uibModalInstance.close(false);  
+        };
+        $scope.ok = function(){
+            $uibModalInstance.close($scope.newBook);
+        }
+
+    }
+    
+
+    addBookController.$inject = [
+        '$scope',
+        '$uibModalInstance',
+        'books.repository',
+        '$uibModalInstance'
+    ];   
+})()

+ 21 - 0
app/controllers/authors.controller.js

@@ -0,0 +1,21 @@
+(function(){
+    app.controller('Authors', ['$scope', 'books.repository', '$routeParams','utils', function ($scope, booksRepository, $routeParams, utils){
+        booksRepository.getAuthors()
+        .then(function(respons){
+            $scope.authors = respons.data
+        },function(error){
+            utils.notify({
+                message: error.statusText,
+                type: 'danger'
+            })
+        })
+        $scope.deleteAuthor = function(id){
+            $scope.authors.splice($scope.authors.indexOf(id), 1)
+        };
+        // utils.notify({
+        //     message: 'her na lob',
+        //     type: 'danger'
+        // })
+        
+    }])
+})();

+ 52 - 0
app/controllers/bookdetails.controller.js

@@ -0,0 +1,52 @@
+(function ()
+{
+    'use strict';
+
+    app.controller('BookDetails', ['$scope', 'books.repository', '$routeParams','utils', function ($scope, booksRepository, $routeParams, utils)
+            {
+                var details = {};
+                booksRepository.getBookById($routeParams.id)
+                .then(function(response) {
+                    $scope.details = response.data;
+                    $scope.details.date = new Date($scope.details.date)
+                    console.log($scope.details)
+                }, function(error) {
+                    utils.notify({
+                        message: error.statusText,
+                        type: 'danger'
+                    })
+                }
+                    )
+
+                $scope.isEditeMode = false;
+                $scope.edite = function(){
+                    $scope.isEditeMode = true;
+                    details = angular.copy($scope.details)
+                }
+                $scope.noEdite = function(){
+                    $scope.isEditeMode = false;
+                    $scope.details = angular.copy(details)
+                }
+                booksRepository.getAuthors()
+                .then(function(response){
+                    $scope.authors = response.data.map(function(author){
+                        return {
+                            id: author.id,
+                            name: author.firstname + ' ' + author.lastname
+                        }
+                    })
+                })
+                $scope.save = function(){
+                    booksRepository.updateBookById($scope.details.id, $scope.details)
+                    $scope.isEditeMode = false;
+                };
+                $scope.getAuthorsById = function(id){
+                    if(!$scope.authors || !id) return;
+                    return $scope.authors.filter(function(item){
+                        return item.id === id;
+                    })[0].name;
+                }
+            }
+        ]);
+}
+)();

+ 63 - 0
app/controllers/bookslist.controller.js

@@ -0,0 +1,63 @@
+(function ()
+{
+    'use strict';
+
+    app.controller('BooksList', ['$scope', 'books.repository', '$uibModal', function ($scope, booksRepository, $uibModal)
+            {
+                $scope.sortField = 'title';
+
+                $scope.addBook = function(){
+                    var modalInstance =  $uibModal.open({
+                        templateUrl : 'app/modals/add-book.template.html',
+                        controller: 'AddBook',
+                        size: 'lg'
+                    })
+                    modalInstance.result
+                    .then(function(data){
+                        booksRepository.addBook(data);
+                        $scope.books.push(data)
+                    }, function(){})
+                }
+
+                $scope.sortBy = function (field)
+                {
+                    if ($scope.sortField == field)
+                    {
+                        $scope.sortField = '-' + field;
+                    }
+                    else
+                    {
+                        $scope.sortField = field;
+                    }
+                };
+
+                $scope.deleteBook = function (book){
+                    var modalInstance = $uibModal.open({
+                        templateUrl: 'app/modals/confirm/confirm.template.html',
+                        controller: 'Confirm',
+                        size: 'sm'
+                    });
+                    modalInstance.result
+                    .then(function(result){
+                        if(!result) return;
+                        booksRepository.deleteBook(book.id)
+                        .then(function(response){
+                            $scope.books.splice($scope.books.indexOf(book), 1)
+                        })
+                    })
+                };
+
+                booksRepository.getBooks()
+                .then(function (response)
+                {
+                    $scope.books = response.data;
+                }, function (error)
+                {
+                    alert(error);
+                }
+                );
+            }
+        ]);
+
+}
+)();

+ 19 - 0
app/controllers/header.controller.js

@@ -0,0 +1,19 @@
+(function ()
+{
+    'use strict';
+
+    app.controller('Header', [ '$scope','$translate',function ($scope, $translate){
+        $scope.isLogged = function() {
+        	return localStorage.getItem('authToken') ? true : false;
+        };
+        $scope.langSwitch = function(){
+            var lang = localStorage.getItem('preferredLanguage');
+            var curentleng = lang === 'en'? 'ru' : 'en';
+            $translate.use(curentleng);
+            localStorage.setItem('preferredLanguage', curentleng);
+        }
+    }
+    ]);
+
+}
+)();

+ 33 - 0
app/controllers/login.controller.js

@@ -0,0 +1,33 @@
+(function ()
+{
+    'use strict';
+
+    app.controller('Login', ['$scope', 'account.repository', '$location','utils',function ($scope, accountRepository, $location, utils)
+            {
+                $scope.user =
+                {
+                    login: 'admin@gmail.com',
+                    password: 'qQ1!1111'
+                };
+
+                $scope.login = function ()
+                {
+                    accountRepository.login($scope.user)
+                    .then(function (response)  {
+                        console.log(response)
+                        $location.path('/');
+                        localStorage.setItem('authToken', response.data.authToken);
+                        utils.notify({
+                            message: 'hello, dude ' + response.data.login,
+                            type: 'succes'
+                        })
+                    }, function (error)
+                    {
+                        
+                    }
+                    )
+                };
+            }
+        ]);
+}
+)();

+ 13 - 0
app/controllers/main.controller.js

@@ -0,0 +1,13 @@
+(function ()
+{
+    'use strict';
+
+    app.controller('Main', function ($scope)
+    {
+        
+
+    }
+    );
+
+}
+)();

BIN
app/directives/lang-switcher/images/en.png


BIN
app/directives/lang-switcher/images/ru.png


Plik diff jest za duży
+ 1 - 0
app/directives/lang-switcher/lang-switcher.css


+ 41 - 0
app/directives/lang-switcher/lang-switcher.directive.js

@@ -0,0 +1,41 @@
+(function() {
+'use strict';
+app.directive('langSwitcher', langSwitcherController);
+function getCurrentlanguage(key) {
+	return this.languages.filter((function(item) { return item.key === key }))[0];
+}
+function langSwitcherController() {
+	return {
+		restrict: 'E',
+		templateUrl: './app/directives/lang-switcher/lang-switcher.template.html',
+		scope: {},
+		link: function(scope, element, attr) {},
+		controller: ['$scope', '$translate', '$rootScope', function($scope, $translate, $rootScope) {
+			$scope.languages = [
+				{ key: 'en', value: 'En' },
+				{ key: 'ru', value: 'Ru' },
+				{ key: 'ua', value: 'Ua' }
+			];
+			$scope.showMenu = false;
+			$scope.toggleMenu = function() {
+				$scope.showMenu = !$scope.showMenu;
+			}
+			var key = localStorage.getItem('preferredLanguage') || 'en';
+			$scope.currentLang = getCurrentlanguage.call($scope, key);
+			$scope.changeLanguage = function(key) {
+				$scope.currentLang = getCurrentlanguage.call($scope, key);
+				$translate.use(key);
+				localStorage.setItem('preferredLanguage', key);
+				$rootScope.$broadcast('changeLang', key);
+				$scope.showMenu = !$scope.showMenu;
+			};
+			$scope.$on('changeLang', function(event, value) {
+				if ($scope.currentLang.key !== value) {
+					$scope.currentLang = getCurrentlanguage.call($scope, value);
+				}
+			});
+		}],
+	}
+}
+langSwitcherController.$inject = [];
+})();

+ 10 - 0
app/directives/lang-switcher/lang-switcher.template.html

@@ -0,0 +1,10 @@
+<div class="lang-switcher">
+	<button ng-click="toggleMenu()">
+		<img ng-src="./app/directives/lang-switcher/images/{{currentLang.key}}.png" alt="{{currentLang.value}}" title="{{currentLang.value}}">
+	</button>
+	<ul class="switcher-menu" ng-class="{'shown': showMenu}">
+		<li ng-repeat="lang in languages" ng-click="changeLanguage(lang.key)">
+			<img ng-src="./app/directives/lang-switcher/images/{{lang.key}}.png" alt="{{lang.value}}" title="{{lang.value}}"> 
+		</li>
+	</ul>
+</div>

BIN
app/img/noBook.png


+ 28 - 0
app/modals/add-book.template.html

@@ -0,0 +1,28 @@
+<div class="modal-header">
+	<h3 class="modal-title">{{'Add new book' | translate}} </h3>
+</div>
+<div class="modal-body">
+	<form>
+		<div class="form-group">
+			<input type="text" placeholder="Title" class="form-control" ng-model="newBook.title">
+		</div>
+		<div class="form-group">
+			<select class="form-control" ng-model="newBook.author_id" ng-options="author.id as author.name for author in authors">
+				<option value="" disabled>-- Select author --</option>
+			</select>
+		</div>
+		<div class="form-group">
+			<input type="number" placeholder="Cost" class="form-control" ng-model="newBook.cost">
+		</div>
+		<div class="form-group">
+			<input type="number" placeholder="Rate" class="form-control" min="0" max="10" ng-model="newBook.rate">
+		</div>
+		<div class="form-group">
+			<textarea rows="10" placeholder="Intro" class="form-control" ng-model="newBook.intro"></textarea>
+		</div>
+	</form>
+</div>
+<div class="modal-footer">
+	<button class="btn btn-danger" ng-click="cancel()">Cancel</button>
+	<button class="btn btn-success" ng-click="ok()">Ok</button>
+</div>

+ 16 - 0
app/modals/confirm/confirm.controller.js

@@ -0,0 +1,16 @@
+app.controller('Confirm', confirmController);
+
+function confirmController($scope, $uibModalInstance) {
+	$scope.cancel = function() {
+		$uibModalInstance.close(false);
+	};
+
+	$scope.ok = function() {
+		$uibModalInstance.close(true);
+	}
+}
+
+confirmController.$inject = [
+	'$scope',
+	'$uibModalInstance',
+];

+ 10 - 0
app/modals/confirm/confirm.template.html

@@ -0,0 +1,10 @@
+<div class="modal-header">
+	<h3 class="modal-title">Confirm</h3>
+</div>
+<div class="modal-body">
+	Are you sure?
+</div>
+<div class="modal-footer">
+	<button class="btn btn-danger" ng-click="cancel()">Cancel</button>
+	<button class="btn btn-success" ng-click="ok()">Ok</button>
+</div>

+ 16 - 0
app/services/account.factory.js

@@ -0,0 +1,16 @@
+(function() {
+
+'use strict';
+
+app.factory('account.repository', ['webApi', '$http', function(webApi, $http) {
+	return {
+		login: _login,
+	};
+
+	function _login(data) {
+		return $http.post(webApi.DOMAIN + '/api/v2/login', data);
+	}
+
+}]);
+
+})();

+ 36 - 0
app/services/books.factory.js

@@ -0,0 +1,36 @@
+(function() {
+
+'use strict';
+
+app.factory('books.repository', ['webApi', '$http', function(webApi, $http) {
+	return {
+		getBooks: _getBooks,
+		getBookById: _getBookById,
+		getAuthors: _getAuthors,
+		updateBookById: _updateBookById,
+		addBook: _addBook,
+		deleteBook: _deleteBook
+	};
+
+	function _getBooks() {
+		return $http.get(webApi.DOMAIN + '/api/v2/books');
+	};
+
+	function _getBookById(id) {
+		return $http.get(webApi.DOMAIN + '/api/v2/books/' + id);
+	};
+	function _getAuthors() {
+		return $http.get(webApi.DOMAIN + '/api/v2/authors');
+	};
+	function _updateBookById(id, book) {
+		return $http.put(webApi.DOMAIN + '/api/v2/books/' + id, book);
+	};
+	function _addBook(data){
+		return $http.post(webApi.DOMAIN + '/api/v2/books', data);
+	}
+	function _deleteBook(id){
+		return $http.delete(webApi.DOMAIN + '/api/v2/books/' + id);
+	}
+}]);
+
+})();

+ 18 - 0
app/services/utils.services.js

@@ -0,0 +1,18 @@
+(function(){
+    'use strict';
+    app.service('utils', ['notify', function(notify){
+        this.notify = function(data){
+            notify.closeAll();
+            var defaults = {
+                message: '',
+                type: 'alert',
+                duration: 3000
+            }
+            data = angular.extend(defaults, data);
+            notify({
+                message: data.message,
+                classes: 'alert alert-' + data.type
+            })
+        }
+    }]);
+})();

+ 16 - 0
app/views/authors.template.html

@@ -0,0 +1,16 @@
+<h2 class="page-header">{{'Authors' | translate }}</h2>
+<table class="table table-hover">
+    <thead>
+        <th>{{'Firstname' | translate}}</th>
+        <th>{{'Lastname' | translate}}</th>
+    </thead>
+    <tbody ng-repeat="author in authors">
+        <th>{{author.firstname}}</th>
+        <th>{{author.lastname}}</th>
+        <th class="float-right">
+            <button  class="btn-danger btn-xs pull-right" ng-click="deteteAuthor(author)"><i class="glyphicon glyphicon-trash"></i></button>
+            <button  class="btn-warning btn-xs pull-right"><i class="glyphicon glyphicon-pencil"></i></button>
+            
+        </th>
+    </tbody>
+</table>

+ 33 - 0
app/views/books-details.template.html

@@ -0,0 +1,33 @@
+<h1 class='page-header'>{{'Book details' | translate }}</h1>
+<div class="book-details" ng-if='!isEditeMode'>
+    <button class="btn-primary"  ng-click="edite()"><i class="glyphicon glyphicon-pencil"></i></button>
+    <h3>{{details.title}}</h3>
+    <h3>Author: {{getAuthorsById(details.author_id)}}</h3>
+    <span>({{details.date}})</span>
+    <span><i class="glyphicon glyphicon-heart">{{details.rate}}</i>${{details.cost}}</span>
+    <img ng-src='{{details.image || "./app/img/noBook.png"}}' class="imgDetail">
+    <p>{{details.intro}}</p>
+</div>
+<div class="edite-detail" ng-if='isEditeMode'>
+        <button class="btn-success"  ng-click="save()"><i class="glyphicon glyphicon-pencil"></i></button>
+        <button class="btn-danger"  ng-click="noEdite()"><i class="glyphicon glyphicon-remove"></i></button>
+        <div class="form-group">
+            <label for="title"></label>
+            <input type="text" class="form-control" ng-model='details.title' id="title">
+        </div>
+        <div class="form-group">
+            <label for="date"></label>
+            <input type="date" ng-model='details.date' class="form-control" id="date">
+        </div>
+        <div class="form-group">
+            <label for="text"></label>
+            <textarea type="text" ng-model="details.intro"  class="form-control" id='text' rows="10" ></textarea>
+        </div>
+        <div class="form-group">
+                <label for="text"></label>
+                <select ng-model="details.author_id" ng-options="author.id as author.name for author in authors">
+
+                </select>
+        </div>
+        
+</div>

+ 32 - 0
app/views/books-list.template.html

@@ -0,0 +1,32 @@
+<div class="page-header">
+  <h1>{{'Books list' | translate}} </h1>
+</div>
+<button class="btn btn-primary pull-right" style="margin-bottom: 20px" ng-click="addBook()"><i class="glyphicon glyphicon-plus"></i>{{'Add new book' | translate}}</button>
+<input type="text" placeholder="Filter" class="form-control" ng-model="searchString" /><br />
+<table class="table table-hover">
+  <thead>
+    <tr>
+      <th ng-click="sortBy('title')"><i class="glyphicon" ng-class="{'glyphicon-chevron-up' : sortField === 'title', 'glyphicon-chevron-down' : sortField === '-title'}"></i> {{'Title' | translate}}</th>
+      <th ng-click="sortBy('author')"><i class="glyphicon" ng-class="{'glyphicon-chevron-up' : sortField === 'author', 'glyphicon-chevron-down' : sortField === '-author'}"></i>{{'Author ' | translate}}</th>
+      <th ng-click="sortBy('date')"><i class="glyphicon" ng-class="{'glyphicon-chevron-up' : sortField === 'date', 'glyphicon-chevron-down' : sortField === '-date'}"></i>{{'Date' | translate}}</th>
+      <th ng-click="sortBy('cost')"><i class="glyphicon" ng-class="{'glyphicon-chevron-up' : sortField === 'cost', 'glyphicon-chevron-down' : sortField === '-cost'}"></i>{{'Cost' | translate}}</th>
+      <th ng-click="sortBy('rate')"><i class="glyphicon" ng-class="{'glyphicon-chevron-up' : sortField === 'rate', 'glyphicon-chevron-down' : sortField === '-rate'}"></i>{{'Rate' | translate}}</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr ng-repeat="book in books | orderBy:sortField | filter: searchString track by $index">
+      <td>{{book.title}}</td>
+      <td>{{book.author | uppercase}}</td>
+      <td>{{book.date | date: 'longDate'}}</td>
+      <td>{{book.cost | currency}}</td>
+      <td>{{book.rate | number : 1 }}</td>
+      <td>
+        <a href="#/books/{{book.id}}" class="btn btn-info btn-xs"><i class="glyphicon glyphicon-eye-open"></i></a>
+        <button class="btn-danger btn-xs" ng-click="deleteBook(book)"><i class="glyphicon glyphicon-trash"></i></button>
+      </td>
+    </tr>
+  </tbody>
+</table>
+<div class="text-center" ng-if="!books.length">
+  No Data
+</div>

+ 5 - 0
app/views/footer.template.html

@@ -0,0 +1,5 @@
+<footer class="navbar-default navbar-fixed-bottom p-t-5 p-b-40">
+	<div class="container">
+		<lang-switcher></lang-switcher>
+	</div>
+</footer>

+ 22 - 0
app/views/header.template.html

@@ -0,0 +1,22 @@
+<nav class="navbar navbar-default" role="navigation" ng-controller="Header">
+    <div class="container-fluid">
+        <div class="navbar-header">
+            <a class="navbar-brand" href="#">AngularJS</a>
+        </div>
+        <div id="navbar" class="navbar-collapse collapse in" aria-expanded="true" aria-hidden="false">
+            <ul class="nav navbar-nav">
+               <li ng-class="{active: currentMenuItem === '/'}"><a href="#/">{{'Home' | translate }}</a></li>
+               <li ng-class="{active: currentMenuItem === '/books'}"><a href="#/books">{{'Books' | translate }}</a></li>
+               <li ng-class="{active: currentMenuItem === '/authors'}"><a href="#/authors">{{'Authors' | translate }}</a></li>
+            </ul>
+            <ul class="nav navbar-nav navbar-right">
+               <li ng-if="!isLogged()" ng-class="{active: currentMenuItem == '/login'}">
+                 <a href="#/login">Authorization</a>
+               </li>
+               <li class="p-t-15 p-r-15 p-l-15">
+                   <lang-switcher></lang-switcher>
+               </li>
+            </ul>
+        </div>
+    </div>
+</nav>

+ 1 - 0
app/views/home.template.html

@@ -0,0 +1 @@
+<h2>Our home page</h2>

+ 15 - 0
app/views/login.template.html

@@ -0,0 +1,15 @@
+<div class="row m-t-100">
+	<div class="col-xs-4 col-xs-offset-4">
+		<h3 class="text-center m-b-30">Authorization</h3>
+		<form class="well" ng-submit="login()">
+			<div class="form-group">
+				<input type="text" placeholder="Email" class="form-control" ng-model="user.login">
+			</div>
+			<div class="form-group">
+				<input type="password" placeholder="Password" class="form-control" ng-model="user.password">
+			</div>
+
+			<button class="btn btn-primary btn-block">Login</button>
+		</form>
+	</div>
+</div>

Plik diff jest za duży
+ 6 - 0
css/style.css


+ 27 - 0
i18n/en.json

@@ -0,0 +1,27 @@
+{
+	"Authors": "Authors",
+	"Home": "Home",
+	"Books": "Books",
+	"Authors": "Authors",
+	"Search": "Search",
+	"No data": "No data",
+	"Title": "Title",
+	"Author": "Author",
+	"Date": "Date",
+	"Cost": "Cost",
+	"Rate": "Rate",
+	"Add book": "Add book",
+	"Filter": "Filter",
+	"Books list": "Books list",
+	"Firstname": "Firstname",
+	"Lastname": "Lastname",
+	"Add author": "Add author",
+	"Home": "Home",
+	"Add new book": "Add new book",
+	"Select author": "Select author",
+	"Intro": "Intro",
+	"Cancel": "Cancel",
+	"Ok": "Ok",
+	"Confirm": "Confirm",
+	"Are you sure?": "Are you sure?"
+}

+ 27 - 0
i18n/ru.json

@@ -0,0 +1,27 @@
+{
+	"Authors": "Авторы",
+	"Home": "Домашняя страница",
+	"Books": "Книги",
+	"Authors": "Авторы",
+	"Search": "Поиск",
+	"No data": "Нет данных",
+	"Title": "Название",
+	"Author": "Автор",
+	"Date": "Дата",
+	"Cost": "Цена",
+	"Rate": "Рейтинг",
+	"Add book": "Добавить книгу",
+	"Filter": "Фильтр",
+	"Books list": "Список книг",
+	"Firstname": "Имя",
+	"Lastname": "Фамилия",
+	"Add author": "Добавить автора",
+	"Home": "Главная страница",
+	"Add new book": "Добавить новую книгу",
+	"Select author": "Выбрать автора",
+	"Intro": "Описание",
+	"Cancel": "Отмена",
+	"Ok": "Ok",
+	"Confirm": "Подтверждение",
+	"Are you sure?": "Вы уверены?"
+}

+ 42 - 0
index.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en" ng-app="fea5" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+  <meta charset="UTF-8" />
+	<title>Angular JS</title>
+	<link rel="stylesheet" href="node_modules/@cgross/angular-notify/dist/angular-notify.css"></link>
+  <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css" />
+  <link rel="stylesheet" href="app/directives/lang-switcher/lang-switcher.css">
+  <link rel="stylesheet" href="css/style.css">
+</head>
+	<body ng-controller="Main">
+	  <div class="container">	  
+	    <ng-include src="'app/views/header.template.html'"></ng-include>
+	    <div ng-view></div>	
+	    <div ng-include src="'app/views/footer.template.html'"></div>
+	  </div>
+
+	  <script src="node_modules/angular/angular.js"></script> 
+		<script src="node_modules/angular-route/angular-route.min.js"></script>
+		<script src="node_modules/@cgross/angular-notify/dist/angular-notify.js"></script>
+		<script src="node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js"></script>
+		<script src="node_modules/angular-translate/dist/angular-translate.min.js"></script>
+		<script src="node_modules/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js"></script>
+	  <script src="app/app.module.js"></script> 
+	  <script src="app/constants/webApi.com.js"></script>
+	  <script src="app/app.config.js"></script> 
+		<script src="app/app.routes.js"></script> 
+		<script src="app/services/utils.services.js"></script> 
+	  <script src="app/controllers/main.controller.js"></script>
+	  <script src="app/controllers/bookslist.controller.js"></script>
+		<script src="app/controllers/header.controller.js"></script>
+		<script src="app/controllers/authors.controller.js"></script>
+	  <script src="app/services/books.factory.js"></script>
+	  <script src="app/controllers/bookdetails.controller.js"></script>
+		<script src="app/controllers/login.controller.js"></script>
+		<script src="app/controllers/addBook.controller.js"></script>
+		<script src="app/modals/confirm/confirm.controller.js"></script>
+	  <script src="app/services/account.factory.js"></script>
+	  <script src="app/directives/lang-switcher/lang-switcher.directive.js"></script>
+		
+	</body>
+</html>

Plik diff jest za duży
+ 9643 - 0
package-lock.json


+ 28 - 0
package.json

@@ -0,0 +1,28 @@
+{
+  "name": "2018-06-01",
+  "version": "1.0.0",
+  "description": "",
+  "main": "webpack.config.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "server": "webpack-dev-server --color --watch-content-base --open"
+  },
+  "author": "",
+  "license": "ISC",
+  "devDependencies": {
+    "html-webpack-plugin": "^3.2.0",
+    "webpack": "^3.12.0",
+    "webpack-cli": "^2.1.4",
+    "webpack-dev-server": "^2.11.2"
+  },
+  "dependencies": {
+    "@cgross/angular-notify": "^2.5.1",
+    "angular": "^1.6.6",
+    "angular-bootstrap": "^0.12.2",
+    "angular-route": "^1.7.1",
+    "angular-translate": "^2.18.1",
+    "angular-translate-loader-static-files": "^2.18.1",
+    "angular-ui-bootstrap": "^2.5.6",
+    "bootstrap": "^3.3.7"
+  }
+}

+ 16 - 0
webpack.config.js

@@ -0,0 +1,16 @@
+const path = require('path');
+const glob = require('glob');
+
+const config = {
+	context: path.resolve(__dirname, './'),
+	entry: {
+		app: './app/app.module.js',
+	},
+	devServer: {
+		port: 9000,
+		stats: 'errors-only'
+	}
+};
+
+module.exports = config;
+