commit f3d8e7de7e85832194152328b9ceb0aa270a879f
Author: Ondřej Váně <onry.vane@gmail.com>
Date:   Wed Mar 18 11:17:05 2020 +0100

    Re #7656: Integrace frontendu a backendu
    
    - propojení fe a be jedním post voláním
    - vytvoření service na fe, která volá be
    - na be je odeslán objekt dotazu v jsonu
    - opraveny testy na be

diff --git a/README.md b/README.md
index be5e237..590ece6 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Indexace a fulltextové vyhledávání v historických obrazových dokumentech - ANONYMOUS
 
 ## Frontend - Angular
-### Suštění lokálně
+### Spuštění lokálně
 - naistalovat a nastavit lokální prostředí [návod zde](https://angular.io/guide/setup-local).
 - přesunout se do složky ./fe/fulltextsearch
 - spustit příkaz `ng serve -o`
@@ -10,6 +10,7 @@
 
 ### Spuštění v dockeru
 - nainstalovat docker [návod zde](https://docs.docker.com/docker-for-windows/install/)
+- nastartovat docker `docker-machine start`
 - přesunout se do složky ./fe/fulltextsearch
 - spustit příkaz pro vytvoření docker image `docker build -t dockerangular .`
 - spustit příkaz pro nastartování kontejneru `docker run -p4200:80 dockerangular`
diff --git a/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/IndexController.java b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/IndexController.java
index eee292e..fae0c88 100644
--- a/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/IndexController.java
+++ b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/IndexController.java
@@ -1,14 +1,21 @@
 package cz.zcu.kiv.aswi.fulltextsearch;
 
+import cz.zcu.kiv.aswi.fulltextsearch.model.Query;
+import cz.zcu.kiv.aswi.fulltextsearch.model.QueryResponse;
+import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+@CrossOrigin(origins = "*", allowedHeaders = "*")
 @RestController
 public class IndexController {
 
     @PostMapping("/")
-    public String index() {
-        return "index";
+    public QueryResponse index(@RequestBody Query query) {
+        return new QueryResponse("Hello, here is spring\n" +
+                "Query was: " + query.getQuery() + "\n" +
+                "Query sent: " + query.getDate().toString());
     }
 
 }
diff --git a/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/Query.java b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/Query.java
new file mode 100644
index 0000000..d5037fe
--- /dev/null
+++ b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/Query.java
@@ -0,0 +1,33 @@
+package cz.zcu.kiv.aswi.fulltextsearch.model;
+
+import com.fasterxml.jackson.annotation.JsonClassDescription;
+
+import java.util.Date;
+
+@JsonClassDescription("query")
+public class Query {
+
+    private String query;
+    private Date date;
+
+    public Query(String query, Date date) {
+        this.query = query;
+        this.date = date;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+
+    public void setDate(Date date) {
+        this.date = date;
+    }
+}
diff --git a/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/QueryResponse.java b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/QueryResponse.java
new file mode 100644
index 0000000..98f80c9
--- /dev/null
+++ b/be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/QueryResponse.java
@@ -0,0 +1,18 @@
+package cz.zcu.kiv.aswi.fulltextsearch.model;
+
+public class QueryResponse {
+
+    private String response;
+
+    public QueryResponse(String response) {
+        this.response = response;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+}
diff --git a/be/fulltextsearch/src/test/java/cz/zcu/kiv/aswi/fulltextsearch/IndexControllerTest.java b/be/fulltextsearch/src/test/java/cz/zcu/kiv/aswi/fulltextsearch/IndexControllerTest.java
index ae93100..1d2ce91 100644
--- a/be/fulltextsearch/src/test/java/cz/zcu/kiv/aswi/fulltextsearch/IndexControllerTest.java
+++ b/be/fulltextsearch/src/test/java/cz/zcu/kiv/aswi/fulltextsearch/IndexControllerTest.java
@@ -1,5 +1,7 @@
 package cz.zcu.kiv.aswi.fulltextsearch;
 
+import cz.zcu.kiv.aswi.fulltextsearch.model.Query;
+import org.apache.coyote.Request;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -13,6 +15,7 @@ import org.springframework.http.ResponseEntity;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Date;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -35,14 +38,16 @@ public class IndexControllerTest {
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_JSON);
 
-        String string = "";
-        HttpEntity<String> request = new HttpEntity<>(string, headers);
+        Date date = new Date();
+        Query testQuery = new Query("Test query", date);
+        HttpEntity<Query> request = new HttpEntity<>(testQuery, headers);
+
 
         ResponseEntity<String> result = restTemplate.postForEntity(uri, request, String.class);
 
         assertEquals(200, result.getStatusCodeValue());
-        assertEquals("index", result.getBody());
+        assertEquals("{\"response\":\"Hello, here is spring\\nQuery was: Test query\\nQuery sent: "+date.toString()+"\"}", result.getBody());
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/fe/fulltextsearch/e2e/src/app.e2e-spec.ts b/fe/fulltextsearch/e2e/src/app.e2e-spec.ts
index c9db425..0941ddb 100644
--- a/fe/fulltextsearch/e2e/src/app.e2e-spec.ts
+++ b/fe/fulltextsearch/e2e/src/app.e2e-spec.ts
@@ -10,7 +10,7 @@ describe('workspace-project App', () => {
 
   it('should display welcome message', () => {
     page.navigateTo();
-    expect(page.getTitleText()).toEqual('Hello in fulltext search frontend');
+    expect(page.getTitleText()).toEqual('Hello in Fulltext search frontend');
   });
 
   afterEach(async () => {
diff --git a/fe/fulltextsearch/src/app/app.component.css b/fe/fulltextsearch/src/app/app.component.css
index e69de29..3eb6333 100644
--- a/fe/fulltextsearch/src/app/app.component.css
+++ b/fe/fulltextsearch/src/app/app.component.css
@@ -0,0 +1,7 @@
+.test {
+  width: 80%;
+  height: 80%;
+  margin: 10%;
+  border: 3px solid grey;
+  padding: 10px;
+}
diff --git a/fe/fulltextsearch/src/app/app.component.html b/fe/fulltextsearch/src/app/app.component.html
index e052117..45af78d 100644
--- a/fe/fulltextsearch/src/app/app.component.html
+++ b/fe/fulltextsearch/src/app/app.component.html
@@ -1,7 +1,19 @@
-<h1 style="text-align: center">Hello in fulltext search frontend</h1>
-<h2>Test bootstrap</h2>
-<div class="alert alert-primary" role="alert">
-  This is a primary alert—check it out!
+<div class="test">
+  <h1 style="text-align: center">Hello in {{title}} frontend</h1>
+  <form #queryForm="ngForm" (ngSubmit)="sendQuery(queryForm.value)">
+    <span><b>Object query:</b> </span>{{ queryForm.value | json }}
+    <div class="input-group mb-3">
+      <input type="text" class="form-control" placeholder="Query" aria-describedby="basic-addon2" ngModel name="query">
+      <div class="input-group-append">
+        <button class="btn btn-outline-secondary" type="submit">Search</button>
+      </div>
+    </div>
+
+    <div class="form-group">
+      <label for="exampleFormControlTextarea1">Response:</label>
+      <textarea readonly class="form-control" id="exampleFormControlTextarea1" rows="10">{{response.response}}</textarea>
+    </div>
+  </form>
 </div>
 
 <!-- Routing -->
diff --git a/fe/fulltextsearch/src/app/app.component.ts b/fe/fulltextsearch/src/app/app.component.ts
index 65c7ebb..8e61356 100644
--- a/fe/fulltextsearch/src/app/app.component.ts
+++ b/fe/fulltextsearch/src/app/app.component.ts
@@ -1,4 +1,7 @@
 import { Component } from '@angular/core';
+import { Query } from './model/Query';
+import { QueryService} from './services/query.service';
+import { QueryResponse } from './model/QueryResponse';
 
 @Component({
   selector: 'app-root',
@@ -7,4 +10,15 @@ import { Component } from '@angular/core';
 })
 export class AppComponent {
   title = 'Fulltext search';
+  response: QueryResponse = new QueryResponse();
+
+  constructor(private queryService: QueryService) { }
+
+  sendQuery(temp: Query) {
+    console.log(temp);
+    temp.date = new Date();
+    this.queryService.sendQuery(temp).subscribe( response => {
+        this.response = response;
+    });
+  }
 }
diff --git a/fe/fulltextsearch/src/app/app.module.ts b/fe/fulltextsearch/src/app/app.module.ts
index 2c3ba29..7a4326e 100644
--- a/fe/fulltextsearch/src/app/app.module.ts
+++ b/fe/fulltextsearch/src/app/app.module.ts
@@ -1,8 +1,10 @@
 import { BrowserModule } from '@angular/platform-browser';
 import { NgModule } from '@angular/core';
+import { HttpClientModule } from '@angular/common/http';
 
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
+import { FormsModule } from '@angular/forms';
 
 @NgModule({
   declarations: [
@@ -10,7 +12,9 @@ import { AppComponent } from './app.component';
   ],
   imports: [
     BrowserModule,
-    AppRoutingModule
+    AppRoutingModule,
+    FormsModule,
+    HttpClientModule
   ],
   providers: [],
   bootstrap: [AppComponent]
diff --git a/fe/fulltextsearch/src/app/model/Query.ts b/fe/fulltextsearch/src/app/model/Query.ts
new file mode 100644
index 0000000..cfde4d4
--- /dev/null
+++ b/fe/fulltextsearch/src/app/model/Query.ts
@@ -0,0 +1,9 @@
+export class Query {
+  query: string;
+  date: Date;
+
+  constructor(query: string, date: Date) {
+    this.query = query;
+    this.date = date;
+  }
+}
diff --git a/fe/fulltextsearch/src/app/model/QueryResponse.ts b/fe/fulltextsearch/src/app/model/QueryResponse.ts
new file mode 100644
index 0000000..69b22d8
--- /dev/null
+++ b/fe/fulltextsearch/src/app/model/QueryResponse.ts
@@ -0,0 +1,3 @@
+export class QueryResponse {
+  response: string;
+}
diff --git a/fe/fulltextsearch/src/app/services/query.service.spec.ts b/fe/fulltextsearch/src/app/services/query.service.spec.ts
new file mode 100644
index 0000000..a484326
--- /dev/null
+++ b/fe/fulltextsearch/src/app/services/query.service.spec.ts
@@ -0,0 +1,15 @@
+import { TestBed } from '@angular/core/testing';
+
+import { QueryService } from './query.service';
+import {HttpClientModule} from '@angular/common/http';
+
+describe('QueryService', () => {
+  beforeEach(() => TestBed.configureTestingModule({
+    imports: [HttpClientModule]
+  }));
+
+  it('should be created', () => {
+    const service: QueryService = TestBed.get(QueryService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/fe/fulltextsearch/src/app/services/query.service.ts b/fe/fulltextsearch/src/app/services/query.service.ts
new file mode 100644
index 0000000..27ad632
--- /dev/null
+++ b/fe/fulltextsearch/src/app/services/query.service.ts
@@ -0,0 +1,20 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import {Observable} from 'rxjs';
+import { QueryResponse } from '../model/QueryResponse';
+import {Query} from '../model/Query';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class QueryService {
+
+  backendUrl = 'http://localhost:8080/';
+
+
+  constructor( private httpClient: HttpClient) {}
+
+  sendQuery(query: Query): Observable<QueryResponse> {
+    return this.httpClient.post<QueryResponse>(this.backendUrl, query);
+  }
+}
