vadimzgonnik 6 лет назад
Сommit
cda6a4db70

+ 3 - 0
.bowerrc

@@ -0,0 +1,3 @@
+{
+	"directory": "lib"
+}

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+lib

+ 12 - 0
.idea/angularjs_fea4_adv.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+      <excludeFolder url="file://$MODULE_DIR$/temp" />
+      <excludeFolder url="file://$MODULE_DIR$/tmp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/misc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/angularjs_fea4_adv.iml" filepath="$PROJECT_DIR$/.idea/angularjs_fea4_adv.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 314 - 0
.idea/workspace.xml

@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="f6921067-a0bc-450b-97c1-c6a05b82f2a0" name="Default" comment="">
+      <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/app/controllers/books/BooksListController.js" beforeDir="false" afterPath="$PROJECT_DIR$/app/controllers/books/BooksListController.js" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/app/controllers/partials/HeaderController.js" beforeDir="false" afterPath="$PROJECT_DIR$/app/controllers/partials/HeaderController.js" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/app/services/booksService.js" beforeDir="false" afterPath="$PROJECT_DIR$/app/services/booksService.js" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/app/views/partials/header.html" beforeDir="false" afterPath="$PROJECT_DIR$/app/views/partials/header.html" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/css/style.css" beforeDir="false" afterPath="$PROJECT_DIR$/css/style.css" afterDir="false" />
+    </list>
+    <ignored path="$PROJECT_DIR$/.tmp/" />
+    <ignored path="$PROJECT_DIR$/temp/" />
+    <ignored path="$PROJECT_DIR$/tmp/" />
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="TRACKING_ENABLED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file leaf-file-name="index.html" pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/index.html">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="255">
+              <caret line="17" column="25" selection-start-line="17" selection-start-column="25" selection-end-line="17" selection-end-column="25" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="template.html" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/modals/add-book/template.html">
+          <provider selected="true" editor-type-id="text-editor" />
+        </entry>
+      </file>
+      <file leaf-file-name="app.js" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/app.js">
+          <provider selected="true" editor-type-id="text-editor" />
+        </entry>
+      </file>
+    </leaf>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+  </component>
+  <component name="IdeDocumentHistory">
+    <option name="CHANGED_PATHS">
+      <list>
+        <option value="$PROJECT_DIR$/css/style.css" />
+        <option value="$PROJECT_DIR$/app/views/partials/header.html" />
+        <option value="$PROJECT_DIR$/app/services/booksService.js" />
+        <option value="$PROJECT_DIR$/app/controllers/partials/HeaderController.js" />
+        <option value="$PROJECT_DIR$/app/controllers/books/BooksListController.js" />
+      </list>
+    </option>
+  </component>
+  <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
+  <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
+  <component name="JsGulpfileManager">
+    <detection-done>true</detection-done>
+    <sorting>DEFINITION_ORDER</sorting>
+  </component>
+  <component name="NodePackageJsonFileManager">
+    <packageJsonPaths>
+      <path value="$PROJECT_DIR$/lib/angular-bootstrap/package.json" />
+      <path value="$PROJECT_DIR$/lib/angular-route/package.json" />
+      <path value="$PROJECT_DIR$/lib/angular/package.json" />
+      <path value="$PROJECT_DIR$/lib/bootstrap/package.json" />
+    </packageJsonPaths>
+  </component>
+  <component name="ProjectFrameBounds" extendedState="6">
+    <option name="x" value="71" />
+    <option name="y" value="-13" />
+    <option name="width" value="1295" />
+    <option name="height" value="748" />
+  </component>
+  <component name="ProjectView">
+    <navigator proportions="" version="1">
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="Scope" />
+      <pane id="ProjectPane">
+        <subPane>
+          <expand>
+            <path>
+              <item name="angularjs_fea4_adv" type="b2602c69:ProjectViewProjectNode" />
+              <item name="angularjs_fea4_adv" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="angularjs_fea4_adv" type="b2602c69:ProjectViewProjectNode" />
+              <item name="angularjs_fea4_adv" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="angularjs_fea4_adv" type="b2602c69:ProjectViewProjectNode" />
+              <item name="angularjs_fea4_adv" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="modals" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="angularjs_fea4_adv" type="b2602c69:ProjectViewProjectNode" />
+              <item name="angularjs_fea4_adv" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="modals" type="462c0819:PsiDirectoryNode" />
+              <item name="add-book" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="angularjs_fea4_adv" type="b2602c69:ProjectViewProjectNode" />
+              <item name="angularjs_fea4_adv" type="462c0819:PsiDirectoryNode" />
+              <item name="css" type="462c0819:PsiDirectoryNode" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
+    <property name="nodejs_npm_path_reset_for_default_project" value="true" />
+  </component>
+  <component name="RunDashboard">
+    <option name="ruleStates">
+      <list>
+        <RuleState>
+          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
+        </RuleState>
+        <RuleState>
+          <option name="name" value="StatusDashboardGroupingRule" />
+        </RuleState>
+      </list>
+    </option>
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="f6921067-a0bc-450b-97c1-c6a05b82f2a0" name="Default" comment="" />
+      <created>1526574216307</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1526574216307</updated>
+      <workItem from="1526574217822" duration="7441000" />
+      <workItem from="1526627732522" duration="81000" />
+      <workItem from="1527024306767" duration="141000" />
+      <workItem from="1527027385291" duration="1325000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TimeTrackingManager">
+    <option name="totallyTimeSpent" value="8988000" />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="64" y="-11" width="1303" height="780" extended-state="6" />
+    <layout>
+      <window_info active="true" content_ui="combo" id="Project" order="1" visible="true" weight="0.24960877" />
+      <window_info anchor="bottom" id="TODO" order="10" />
+      <window_info anchor="bottom" id="Docker" order="0" show_stripe_button="false" />
+      <window_info anchor="bottom" id="Event Log" order="2" side_tool="true" />
+      <window_info anchor="bottom" id="Run" order="6" />
+      <window_info anchor="bottom" id="Version Control" order="3" />
+      <window_info id="Structure" order="2" side_tool="true" weight="0.25" />
+      <window_info anchor="bottom" id="Terminal" order="1" />
+      <window_info anchor="bottom" id="Debug" order="7" weight="0.4" />
+      <window_info id="Favorites" order="0" side_tool="true" />
+      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
+      <window_info anchor="bottom" id="Inspection" order="9" weight="0.4" />
+      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
+      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
+      <window_info anchor="bottom" id="Message" order="4" />
+      <window_info anchor="bottom" id="Cvs" order="8" weight="0.25" />
+      <window_info anchor="bottom" id="Find" order="5" />
+    </layout>
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="1" />
+  </component>
+  <component name="VcsContentAnnotationSettings">
+    <option name="myLimit" value="2678400000" />
+  </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="210">
+          <caret line="14" lean-forward="true" selection-start-line="14" selection-end-line="14" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/partials/HeaderController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="195">
+          <caret line="13" column="4" selection-start-line="13" selection-start-column="4" selection-end-line="13" selection-end-column="4" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/partials/header.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="225">
+          <caret line="15" column="33" selection-start-line="15" selection-start-column="33" selection-end-line="15" selection-end-column="41" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/services/booksService.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="285">
+          <caret line="19" column="6" lean-forward="true" selection-start-line="19" selection-start-column="6" selection-end-line="19" selection-end-column="6" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/css/style.css">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="150">
+          <caret line="10" column="20" selection-start-line="10" selection-start-column="20" selection-end-line="10" selection-end-column="20" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/books/BooksListController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="105">
+          <caret line="7" selection-start-line="7" selection-end-line="7" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/partials/HeaderController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="195">
+          <caret line="13" column="4" selection-start-line="13" selection-start-column="4" selection-end-line="13" selection-end-column="4" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/partials/header.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="225">
+          <caret line="15" column="33" selection-start-line="15" selection-start-column="33" selection-end-line="15" selection-end-column="41" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/services/booksService.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="285">
+          <caret line="19" column="6" lean-forward="true" selection-start-line="19" selection-start-column="6" selection-end-line="19" selection-end-column="6" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/css/style.css">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="150">
+          <caret line="10" column="20" selection-start-line="10" selection-start-column="20" selection-end-line="10" selection-end-column="20" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/books/BooksListController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="105">
+          <caret line="7" selection-start-line="7" selection-end-line="7" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/css/style.css">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="150">
+          <caret line="10" column="20" selection-start-line="10" selection-start-column="20" selection-end-line="10" selection-end-column="20" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/services/booksService.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="285">
+          <caret line="19" column="6" selection-start-line="19" selection-start-column="6" selection-end-line="19" selection-end-column="6" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/partials/header.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="225">
+          <caret line="15" column="33" selection-start-line="15" selection-start-column="33" selection-end-line="15" selection-end-column="41" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/partials/HeaderController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="195">
+          <caret line="13" column="4" selection-start-line="13" selection-start-column="4" selection-end-line="13" selection-end-column="4" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/controllers/books/BooksListController.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="105">
+          <caret line="7" selection-start-line="7" selection-end-line="7" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/modals/add-book/template.html">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/app.js">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="255">
+          <caret line="17" column="25" selection-start-line="17" selection-start-column="25" selection-end-line="17" selection-end-column="25" />
+        </state>
+      </provider>
+    </entry>
+  </component>
+</project>

+ 33 - 0
app/app.js

@@ -0,0 +1,33 @@
+var app = angular.module('fe4adv', [
+	'ngRoute',
+	'xeditable',
+	'ui.bootstrap'
+]);
+
+app.config([
+	'$routeProvider',
+	'$locationProvider',
+function($routeProvider, $locationProvider) {
+	$locationProvider.hashPrefix('');
+
+	$routeProvider
+		.when('/books', {
+			templateUrl: 'app/views/books/books-list.template.html',
+			controller: 'BooksListController'
+		})
+		.when('/books/:id', {
+			templateUrl: 'app/views/books/book-details.template.html',
+			controller: 'BookDetailsController'
+		})
+		.when('/authors', {
+			templateUrl: 'app/views/authors/authors-list.template.html',
+			controller: 'AuthorsListController'
+		})
+		.otherwise({
+			redirectTo: '/'
+		});
+}]);
+
+app.run(['editableOptions', function(editableOptions) {
+  editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
+}]);

+ 3 - 0
app/constants/api.js

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

+ 15 - 0
app/controllers/authors/AuthorsListController.js

@@ -0,0 +1,15 @@
+app.controller('AuthorsListController',
+[
+'$scope',
+'books.repository',
+function($scope, booksRepository) {
+	booksRepository.getAuthors().then(function(response) {
+		$scope.authors = response.data;
+	});
+
+	$scope.updateAuthor = function(data, id) {
+		booksRepository.updateAuthorById(id, data).then(function(response) {
+			console.log('response', response);
+		});
+	};
+}]);

+ 14 - 0
app/controllers/books/BookDetailsController.js

@@ -0,0 +1,14 @@
+app.controller('BookDetailsController', [
+	'$scope',
+	'$routeParams',
+	'books.repository',
+function($scope, $routeParams, booksRepository) {
+	var bookId = $routeParams.id;
+
+	booksRepository.getBookById(bookId).then(function(response) {
+		$scope.book = response.data;
+		console.log($scope.book);
+
+		console.log(Object.keys($scope.book));
+	}, function(error) {});
+}]);

+ 51 - 0
app/controllers/books/BooksListController.js

@@ -0,0 +1,51 @@
+app.controller('BooksListController', [
+'$scope',
+'books.repository',
+'$uibModal',
+function($scope, booksRepository, $uibModal) {
+var searchRequest = sessionStorage.getItem('searchString');
+
+if(!searchRequest) {
+    booksRepository.getBooks().then(function (response) {
+        $scope.books = response.data;
+    }, function (error) {
+    });
+} else {
+    booksRepository.searchBy(searchRequest).then(function (response) {
+        $scope.books = response.data;
+    });
+
+    sessionStorage.removeItem('searchRequest');
+}
+
+	$scope.sortField = 'title';
+
+	$scope.sort = function(field) {
+		$scope.sortField = $scope.sortField !== field ? field : '-' + field;
+	};
+
+	$scope.showModalAddBook = function() {
+		var modalInstance = $uibModal.open({
+			backdrop: 'static',
+			size: 'lg',
+			templateUrl: './app/modals/add-book/template.html',
+			controller: 'AddBookController'
+		});
+
+		modalInstance.result.then(function(result) {
+			$scope.books.push(result);
+		}, function() {
+			console.log('modal is closed');
+		});
+	};
+	$scope.$on('SearchBookEvent', function (event, value) {
+		console.log(value, '<<<<<');
+
+		booksRepository.searchBy(value).then(function (response) {
+			$scope.books = response.data;
+
+			console.log(response.data, '<<<<<')
+
+        })
+    })
+}]);

+ 14 - 0
app/controllers/partials/HeaderController.js

@@ -0,0 +1,14 @@
+app.controller('HeaderController', ['$scope', '$rootScope', '$location', function($scope, $rootScope, $location) {
+	$scope.searchString = " ";
+
+	$scope.search = function () {
+		console.log($scope.searchString, '<<<<<<<' );
+		sessionStorage.setItem('searchRequest', $scope.searchString);
+
+
+		$rootScope.$broadcast('SearchBookEvent', $scope.searchString);
+        $location.path ('/books');
+        $scope.searchString = '';
+    };
+
+}]);

+ 36 - 0
app/modals/add-book/AddBookController.js

@@ -0,0 +1,36 @@
+app.controller('AddBookController', [
+'$scope',
+'$uibModalInstance',
+'books.repository',
+function($scope, $uibModalInstance, booksRepository) {
+	$scope.bookModel = {
+		title: '',
+		cost: 0,
+		rate: 0,
+		image: '',
+		author_id: null
+	};
+
+	booksRepository.getAuthors().then(function(response) {
+		$scope.authors = response.data.map(function(item) {
+			return {
+				id: item.id,
+				name: item.firstname + ' ' + item.lastname
+			}
+		});
+
+		$scope.bookModel.author_id = $scope.authors[0].id;
+	});
+
+	$scope.cancel = function() {
+		$uibModalInstance.dismiss();
+		// $uibModalInstance.close(false);
+	};
+
+	$scope.ok = function() {
+		booksRepository.createBook($scope.bookModel)
+		.then(function(response) {
+			$uibModalInstance.close(response.data);
+		});
+	}
+}])

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

@@ -0,0 +1,27 @@
+<div class="modal-header">
+	<h3 class="modal-title" id="modal-title">Add book</h3>
+</div>
+<div class="modal-body" id="modal-body">
+	<div class="form-group">
+		<input type="text" class="form-control" placeholder="Title" ng-model="bookModel.title">
+	</div>
+	<div class="form-group">
+		<input type="number" class="form-control" placeholder="Cost" ng-model="bookModel.cost">
+	</div>
+	<div class="form-group">
+		<input type="number" class="form-control" placeholder="Rate" ng-model="bookModel.rate">
+	</div>
+	<div class="form-group">
+		<input type="text" class="form-control" placeholder="Image" ng-model="bookModel.image">
+	</div>
+	<div class="form-group">
+		<select class="form-control" ng-model="bookModel.author_id"
+		ng-options="author.id as author.name for author in authors"
+		ng-selected="author.id === bookModel.author_id">
+		</select>
+	</div>
+</div>
+<div class="modal-footer">
+	<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
+	<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
+</div>

+ 25 - 0
app/services/booksService.js

@@ -0,0 +1,25 @@
+app.service('books.repository', ['$http', 'webApi', function($http, webApi) {
+	this.getBooks = function() {
+		return $http.get(webApi.apiUrl + '/api/v1/books');
+	};
+
+	this.getBookById = function(id) {
+		return $http.get(webApi.apiUrl + '/api/v1/books/' + id);
+	};
+
+	this.getAuthors = function() {
+		return $http.get(webApi.apiUrl + '/api/v1/authors');
+	};
+
+	this.updateAuthorById = function(id, data) {
+		return $http.put(webApi.apiUrl + '/api/v1/authors/' + id, data);
+	};
+
+	this.createBook = function(data) {
+		return $http.post(webApi.apiUrl + '/api/v1/books', data);
+	};
+	this.searchBy = function (searchString) {
+		return $http.get(webApi.apiUrl + '/api/v1/search?string=' + searchString )
+    }
+
+}]);

+ 35 - 0
app/views/authors/authors-list.template.html

@@ -0,0 +1,35 @@
+<div class="page-header">Authors</div>
+
+	<table class="table table-striped table-hover">
+		<thead>
+			<th>Firstname</th>
+			<th>Lastname</th>
+			<th class="text-right">Actions</th>
+		</thead>
+		<tbody>
+			<tr ng-repeat="author in authors">
+				<td>
+					<a href="" editable-text="author.firstname" e-form="editableForm" e-name="firstname">{{author.firstname || 'empty'}}</a>
+				</td>
+				<td><a href="" editable-text="author.lastname" e-form="editableForm" e-name="lastname">{{author.lastname || 'empty'}}</a></td>
+				<td class="text-right">
+
+					<form editable-form name="editableForm" shown="inserted == author" onaftersave="updateAuthor($data, author.id)">
+						<div class="buttons">
+							<button type="button" class="btn btn-default btn-xs" ng-click="editableForm.$show()" ng-show="!editableForm.$visible"><i class="glyphicon glyphicon-pencil"></i></button>
+							
+							<span ng-show="editableForm.$visible">
+								<button type="submit" class="btn btn-primary btn-xs" ng-disabled="editableForm.$waiting">
+									<i class="glyphicon glyphicon-ok"></i>
+								</button>
+								<button type="button" class="btn btn-danger btn-xs" ng-disabled="editableForm.$waiting" ng-click="editableForm.$cancel()">
+									<i class="glyphicon glyphicon-remove"></i>
+								</button>
+							</span>
+						</div>	
+					</form>
+				
+				</td>
+			</tr>
+		</tbody>
+	</table>

+ 8 - 0
app/views/books/book-details.template.html

@@ -0,0 +1,8 @@
+<div>
+	<div class="page-header"><h1>{{book.title}}</h1></div>
+
+	<p class="clearfix">
+		<img src="{{book.image || 'img/noimage.png'}}" alt="" class="img-thumbnail rounded pull-left book-preview">
+		{{book.intro}}
+	</p>
+</div>

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

@@ -0,0 +1,49 @@
+<div>
+	<div class="page-header"><h1>Books</h1></div>
+
+	<div class="row">
+		<div class="col-xs-4">
+			<div class="form-group">
+				<input type="text" class="form-control" placeholder="Filter by..." ng-model="filterBy">
+			</div>
+		</div>
+		<div class="col-xs-8 text-right">
+			<button class="btn btn-primary" ng-click="showModalAddBook()"><i class="glyphicon glyphicon-plus"></i> Add book</button>
+		</div>
+	</div>
+
+	<table class="table table-striped table-hover">
+		<thead>
+			<tr>
+				<th ng-click="sort('title')">
+					Title <i class="glyphicon" ng-class="{'glyphicon-chevron-up': sortField === '-title', 'glyphicon-chevron-down': sortField === 'title'}"></i>
+				</th>
+				<th ng-click="sort('author')">
+					Author  <i class="glyphicon" ng-class="{'glyphicon-chevron-up': sortField === '-author', 'glyphicon-chevron-down': sortField === 'author'}"></i>
+				</th>
+				<th ng-click="sort('date')">
+					Date  <i class="glyphicon" ng-class="{'glyphicon-chevron-up': sortField === '-date', 'glyphicon-chevron-down': sortField === 'date'}"></i>
+				</th>
+				<th ng-click="sort('cost')">
+					Cost  <i class="glyphicon" ng-class="{'glyphicon-chevron-up': sortField === '-cost', 'glyphicon-chevron-down': sortField === 'cost'}"></i>
+				</th>
+				<th ng-click="sort('rate')">
+					Rate  <i class="glyphicon" ng-class="{'glyphicon-chevron-up': sortField === '-rate', 'glyphicon-chevron-down': sortField === 'rate'}"></i>
+				</th>
+				<th>
+					Actions
+				</th>
+			</tr>
+		</thead>
+		<tr ng-repeat="book in books | orderBy: sortField | filter : filterBy">
+			<td>{{book.title}}</td>
+			<td>{{book.author}}</td>
+			<td>{{book.date | date : 'longDate'}}</td>
+			<td>{{book.cost | currency}}</td>
+			<td>{{book.rate | number : 2}}</td>
+			<td class="text-right">
+				<a href="#/books/{{book.id}}" class="btn btn-info btn-xs"><i class="glyphicon glyphicon-eye-open"></i></a>
+			</td>
+		</tr>
+	</table>
+</div>

+ 1 - 0
app/views/partials/footer.html

@@ -0,0 +1 @@
+<div>footer</div>

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

@@ -0,0 +1,22 @@
+<header ng-controller="HeaderController">
+    <nav class="navbar navbar-default" role="navigation">
+        <ul class="nav navbar-nav">
+            <li role="menuitem">
+                <a href="#/">Home</a>
+            </li>
+            <li role="menuitem">
+                <a href="#/books">Books</a>
+            </li>
+            <li role="menuitem">
+                <a href="#/authors">Authors</a>
+            </li>
+        </ul>
+        <ul class="nav navbar-nav navbar-right">
+            <li>
+                <form ng-submit="search()">
+                    <input type="search" class="form-control" placeholder="Search by book title" ng-model="searchString">
+                </form>
+            </li>
+        </ul>
+    </nav>
+</header>


+ 27 - 0
bower.json

@@ -0,0 +1,27 @@
+{
+  "name": "gallery",
+  "authors": [
+    "Natalie <filonitta@gmail.com>"
+  ],
+  "description": "jQuery gallery plugin",
+  "main": "index.html",
+  "license": "MIT",
+  "homepage": "",
+  "private": true,
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "jquery": "^3.1.1",
+    "bootstrap": "^3.3.7",
+    "angular": "1.6.6",
+    "angular-route": "^1.6.7",
+    "angular-notify": "^2.5.1",
+    "angular-bootstrap": "^2.5.0",
+    "angular-xeditable": "^0.8.1"
+  }
+}

+ 12 - 0
css/style.css

@@ -0,0 +1,12 @@
+[ng\:cloak], [ng-cloak], .ng-cloak {
+	display: none !important;
+}
+
+.book-preview {
+	max-width: 300px;
+	margin-right: 10px;
+}
+.navbar-right{
+	margin-right: 10px;
+	margin-top: 6	px;
+}

BIN
img/noimage.png


+ 36 - 0
index.html

@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="UTF-8">
+	<title>AngularJS</title>
+	
+	<link href="lib/angular-xeditable/dist/css/xeditable.css" rel="stylesheet">
+
+	<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css">
+	<link rel="stylesheet" href="css/style.css">
+</head>
+<body ng-app="fe4adv">
+	<div class="container" ng-cloak>
+		<ng-include src="'app/views/partials/header.html'"></ng-include>
+
+		<ng-view></ng-view>
+
+		<div ng-include="'app/views/partials/footer.html'"></div>
+	</div>
+	
+	<script src="lib/angular/angular.js"></script>
+	<script src="lib/angular-route/angular-route.min.js"></script>
+	<script src="lib/angular-xeditable/dist/js/xeditable.js"></script>
+	<script src="lib/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+
+	<script src="app/app.js"></script>
+	<script src="app/constants/api.js"></script>
+	<script src="app/services/booksService.js"></script>
+	<script src="app/controllers/books/BooksListController.js"></script>
+	<script src="app/controllers/books/BookDetailsController.js"></script>
+	<script src="app/controllers/authors/AuthorsListController.js"></script>
+	<script src="app/controllers/partials/HeaderController.js"></script>
+	<script src="app/modals/add-book/AddBookController.js"></script>
+
+</body>
+</html>