Repository: jhipster/generator-jhipster (ts)

Issue:
Duplication code
##### **Overview of the issue**
* https://github.com/jhipster/jhipster-sample-app/blob/master/src/main/webapp/app/app.route.ts seems to not be used. This code is duplicatated with https://github.com/jhipster/jhipster-sample-app/blob/master/src/main/webapp/app/layouts/navbar/navbar.route.ts.
* In an entity generated, entity.service.ts have two methods identicals : `convertItemFromServer` and `convert`. We could see that for example in https://github.com/jhipster/jhipster-sample-app/blob/master/src/main/webapp/app/entities/bank-account/bank-account.service.ts.

##### **Motivation for or Use Case**

It could be cool to not have duplicated code. Simpler to understand the code. Safer. 


##### **Related issues**

<!-- Has a similar issue been reported before? Please search both closed & open issues -->
No related issues found. I've searched with keywords « navbar.route.ts » , « app.route.ts », « convertItemFromServer ».


##### **JHipster Version(s)**
JHipster 4.14.1

##### **JHipster configuration**
Irrelevant. All configurations. See the official sample  https://github.com/jhipster/jhipster-sample-app/.

Pull request:
Refactor entity.service.ts.ejs + delete app.route.ts.ejs
### Overview
refactor [entity.service.ts.ejs](https://github.com/jhipster/generator-jhipster/blob/239acc14495d0069c64a35842065cb09ff6ea6ff/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity.service.ts.ejs) + delete [app.route.ts.ejs](https://github.com/jhipster/generator-jhipster/blob/239acc14495d0069c64a35842065cb09ff6ea6ff/generators/client/templates/angular/src/main/webapp/app/app.route.ts.ejs)

Fix #7302 

Recent others authors of entity.service.ts.ejs are @Tcharl, @jdubois and @deepu105. 

### Code generated. 
##### JHipster V5
* This patch cause  some modifications on the code generated (it's its goal). We could compare the difference thanks the repository https://github.com/jhipster/jhipster-sample-app/. I've forked this repository and enabled elasticsearch. The difference caused by this patch in the code generated by JHipster  could be seen at https://github.com/JulioJu/jhipster-sample-app/compare/754bfd437e52eb6673394929a2ec92c824cee432...JulioJu:c5a1fab55843d625305f144b71c56feef875654b
* Note: https://github.com/JulioJu/jhipster-sample-app/ and https://github.com/JulioJu/jhipster-sample-app/  have only one configuration who differs: elasticsearch is enabled (see [.yo,rc.json](https://github.com/JulioJu/jhipster-sample-app/commit/d8db5760cb346c9d3d2cb4e8dbc39c21045f7968)).
#### Test on branch 4.14.1
* On the actual head (239acc14495d0069c64a35842065cb09ff6ea6ff) of jhipster/jhipster-sample-app  with Elasticsearch enabled there is some bugs. 
* Therefore, only for test purposes, I've tested my patch of entity.service.ts.ejs on the branch 4.14.1. You could see how the code is modified for branch 4.14.1 at https://github.com/JulioJu/generator-jhipster/tree/v4.14.1_entity.service_patched. 
* You could see how the code generated by JHipster patched differs at https://github.com/JulioJu/jhipster-sample-app/tree/v14.4.1patched. 

### How remove app.route.ts on upgrade ?
* In [./generators/cleanup.js](./generators/cleanup.js). I believe my modifications are wrong.
```javascript
// Delete ${ANGULAR_DIR}/app.route.ts only if jhipster version is strictly less than 5.0.0
if (generator.isJhipsterVersionLessThan('5.0.0')) {
     generator.removeFile(`${ANGULAR_DIR}/app.route.ts`);
}
```
I've followed other examples in this file. But, I want delete `${ANGULAR_DIR}/app.route.ts`  if jhipster version is greater than 5.0.0. So maybe I would like write instead.
```javascript
// Delete ${ANGULAR_DIR}/app.route.ts only if jhipster version is equal to 5.0.0 or greater than 5.0.0.
if (generator.jhipsterVersion === '5.0.0' || !generator.isJhipsterVersionLessThan('5.0.0')) {
     generator.removeFile(`${ANGULAR_DIR}/app.route.ts`);
}
```
But I've never seen this syntax in [./generators/cleanup.js](https://github.com/jhipster/generator-jhipster/blob/239acc14495d0069c64a35842065cb09ff6ea6ff/generators/cleanup.js). 

What do you think about that ?
### Checklist
- Please make sure the below checklist is followed for Pull Requests.

- [V ] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green (I've runned `$ ./build-samples.sh build ngx-default`)
- ~~[ ] Tests are added where necessary~~ (no test necessary)
- ~~[ ] Documentation is added/updated where necessary~~ (no documentation necessary)
- [ V] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md) are followed


Patch:
diff --git a/generators/cleanup.js b/generators/cleanup.js
index 2243a7e919..e9953f0814 100644
--- a/generators/cleanup.js
+++ b/generators/cleanup.js
@@ -45,6 +45,7 @@ function cleanupOldFiles(generator) {
         generator.removeFile(`${ANGULAR_DIR}components/form/uib-pagination.config.js`);
     }
     if (generator.isJhipsterVersionLessThan('5.0.0')) {
+        generator.removeFile(`${ANGULAR_DIR}/app.route.ts`);
         generator.removeFile(`${ANGULAR_DIR}shared/auth/account.service.ts`);
         generator.removeFile(`${ANGULAR_DIR}shared/auth/auth-jwt.service.ts`);
         generator.removeFile(`${ANGULAR_DIR}shared/auth/auth-session.service.ts`);
diff --git a/generators/client/files-angular.js b/generators/client/files-angular.js
index 74319191ee..c4501fc624 100644
--- a/generators/client/files-angular.js
+++ b/generators/client/files-angular.js
@@ -129,7 +129,6 @@ const files = {
             path: ANGULAR_DIR,
             templates: [
                 'app.main.ts',
-                'app.route.ts',
                 'app.module.ts',
                 'app-routing.module.ts',
                 'app.constants.ts',
diff --git a/generators/client/templates/angular/src/main/webapp/app/app.route.ts.ejs b/generators/client/templates/angular/src/main/webapp/app/app.route.ts.ejs
deleted file mode 100644
index d5ea37eb13..0000000000
--- a/generators/client/templates/angular/src/main/webapp/app/app.route.ts.ejs
+++ /dev/null
@@ -1,27 +0,0 @@
-<%#
- Copyright 2013-2018 the original author or authors from the JHipster project.
-
- This file is part of the JHipster project, see https://www.jhipster.tech/
- for more information.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--%>
-import { Route } from '@angular/router';
-
-import { NavbarComponent } from './layouts';
-
-export const navbarRoute: Route = {
-    path: '',
-    component: NavbarComponent,
-    outlet: 'navbar'
-};
diff --git a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity.service.ts.ejs b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity.service.ts.ejs
index 4716a76768..d2c5e91792 100644
--- a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity.service.ts.ejs
+++ b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity.service.ts.ejs
@@ -27,8 +27,8 @@ import { SERVER_API_URL } from 'app/app.constants';
 import { createRequestOption } from 'app/shared';
 import { I<%= entityAngularName %> } from 'app/shared/model/<%= entityModelFileName %>.model';
 
-export type EntityResponseType = HttpResponse<I<%= entityAngularName %>>;
-export type EntityArrayResponseType = HttpResponse<I<%= entityAngularName %>[]>;
+type EntityResponseType = HttpResponse<I<%= entityAngularName %>>;
+type EntityArrayResponseType = HttpResponse<I<%= entityAngularName %>[]>;
 
 @Injectable()
 export class <%= entityAngularName %>Service {
@@ -39,91 +39,80 @@ export class <%= entityAngularName %>Service {
     <%_ } _%>
 
     constructor(private http: HttpClient) { }
-    <%_ if (entityAngularName.length <= 30) { _%>
 
     create(<%= entityInstance %>: I<%= entityAngularName %>): Observable<EntityResponseType> {
-    <%_ } else { _%>
-
-    create(<%= entityInstance %>: I<%= entityAngularName %>):
-        Observable<EntityResponseType> {
-    <%_ } _%>
-        const copy = this.convert(<%= entityInstance %>);
-        return this.http.post<I<%= entityAngularName %>>(this.resourceUrl, copy, { observe: 'response' })
-            .map((res: EntityResponseType) => this.convertResponse(res));
+        <%_ if (fieldsContainDate) { _%>
+        const copy = this.convertDateFromClient(<%= entityInstance %>);
+        <%_ } _%>
+            return this.http.post<I<%= entityAngularName %>>(this.resourceUrl,
+                    <% if (fieldsContainDate) { %> copy <% } else { %> <%= entityInstance %> <% } %>,
+                    { observe: 'response' })
+            <% if (fieldsContainDate) { %>.map((res: EntityResponseType) => this.convertDateFromServer(res))<% } %>;
     }
-    <%_ if (entityAngularName.length <= 30) { _%>
 
     update(<%= entityInstance %>: I<%= entityAngularName %>): Observable<EntityResponseType> {
-    <%_ } else { _%>
-
-    update(<%= entityInstance %>: I<%= entityAngularName %>):
-        Observable<EntityResponseType> {
-    <%_ } _%>
-        const copy = this.convert(<%= entityInstance %>);
-        return this.http.put<I<%= entityAngularName %>>(this.resourceUrl, copy, { observe: 'response' })
-            .map((res: EntityResponseType) => this.convertResponse(res));
+        <%_ if (fieldsContainDate) { _%>
+        const copy = this.convertDateFromClient(<%= entityInstance %>);
+        <%_ } _%>
+            return this.http.put<I<%= entityAngularName %>>(this.resourceUrl,
+                    <% if (fieldsContainDate) { %> copy <% } else { %> <%= entityInstance %> <% } %>,
+                    { observe: 'response' })
+            <% if (fieldsContainDate) { %>.map((res: EntityResponseType) => this.convertDateFromServer(res))<% } %>;
     }
 
     find(id: <% if (pkType === 'String') { %>string<% } else { %>number<% } %>): Observable<EntityResponseType> {
         return this.http.get<I<%= entityAngularName %>>(`${this.resourceUrl}/${id}`, { observe: 'response'})
-            .map((res: EntityResponseType) => this.convertResponse(res));
+            <% if (fieldsContainDate) { %>.map((res: EntityResponseType) => this.convertDateFromServer(res))<% } %>;
     }
 
     query(req?: any): Observable<EntityArrayResponseType> {
         const options = createRequestOption(req);
         return this.http.get<I<%= entityAngularName %>[]>(this.resourceUrl, { params: options, observe: 'response' })
-            .map((res: EntityArrayResponseType) => this.convertArrayResponse(res));
+            <% if (fieldsContainDate) { %>.map((res: EntityArrayResponseType) => this.convertDateArrayFromServer(res))<% } %>;
     }
 
     delete(id: <% if (pkType === 'String') { %>string<% } else { %>number<% } %>): Observable<HttpResponse<any>> {
         return this.http.delete<any>(`${this.resourceUrl}/${id}`, { observe: 'response'});
     }
-    <%_ if (searchEngine === 'elasticsearch') { _%>
 
+    <%_ if (searchEngine === 'elasticsearch') { _%>
     search(req?: any): Observable<EntityArrayResponseType> {
         const options = createRequestOption(req);
         return this.http.get<I<%= entityAngularName %>[]>(this.resourceSearchUrl, { params: options, observe: 'response' })
-            .map((res: EntityArrayResponseType) => this.convertArrayResponse(res));
+            <% if (fieldsContainDate) { %>.map((res: EntityArrayResponseType) => this.convertDateArrayFromServer(res))<% } %>;
     }
     <%_ } _%>
 
-    private convertResponse(res: EntityResponseType): EntityResponseType {
-        const body: I<%= entityAngularName %> = this.convertItemFromServer(res.body);
-        return res.clone({body});
-    }
-
-    private convertArrayResponse(res: EntityArrayResponseType): EntityArrayResponseType {
-        const jsonResponse: I<%= entityAngularName %>[] = res.body;
-        const body: I<%= entityAngularName %>[] = [];
-        for (let i = 0; i < jsonResponse.length; i++) {
-            body.push(this.convertItemFromServer(jsonResponse[i]));
-        }
-        return res.clone({body});
-    }
-
-    /**
-     * Convert a returned JSON object to <%= entityAngularName %>.
-     */
-    private convertItemFromServer(<%= entityInstance %>: I<%= entityAngularName %>): I<%= entityAngularName %> {
+    <%_ if (fieldsContainDate) { _%>
+    private convertDateFromClient(<%= entityInstance %>: I<%= entityAngularName %>): I<%= entityAngularName %> {
         const copy: I<%= entityAngularName %> = Object.assign({}, <%= entityInstance %>, {
         <%_ for (idx in fields) { _%>
         <%_ if ( ['Instant', 'ZonedDateTime', 'LocalDate'].includes(fields[idx].fieldType) ) { _%>
-        <%=fields[idx].fieldName%>: <%= entityInstance %>.<%= fields[idx].fieldName %> != null ? moment(<%= entityInstance %>.<%= fields[idx].fieldName %>) : <%= entityInstance %>.<%= fields[idx].fieldName %>,
-            <%_ } _%>
+        <%= fields[idx].fieldName %>: <%= entityInstance %>.<%= fields[idx].fieldName %> != null && <%= entityInstance %>.<%= fields[idx].fieldName %>.isValid() ? <%= entityInstance %>.<%= fields[idx].fieldName %>.toJSON() : null,
+        <%_ } _%>
         <%_ } _%>
         });
         return copy;
     }
 
-    /**
-     * Convert a <%= entityAngularName %> to a JSON which can be sent to the server.
-     */
-    private convert(<%= entityInstance %>: I<%= entityAngularName %>): I<%= entityAngularName %> {
-        const copy: I<%= entityAngularName %> = Object.assign({}, <%= entityInstance %>, {
-        <%_ for (idx in fields){ if ( ['Instant', 'ZonedDateTime', 'LocalDate'].includes(fields[idx].fieldType) ) { _%>
-        <%= fields[idx].fieldName %>: <%= entityInstance %>.<%= fields[idx].fieldName %> != null && <%= entityInstance %>.<%= fields[idx].fieldName %>.isValid() ? <%= entityInstance %>.<%= fields[idx].fieldName %>.toJSON() : null,
-        <%_ } } _%>
+    private convertDateFromServer(res: EntityResponseType): EntityResponseType {
+        <%_ for (idx in fields) { _%>
+        <%_ if ( ['Instant', 'ZonedDateTime', 'LocalDate'].includes(fields[idx].fieldType) ) { _%>
+            res.body.<%= fields[idx].fieldName %> = res.body.<%= fields[idx].fieldName %> != null ? moment(res.body.<%= fields[idx].fieldName %>) : null;
+        <%_ } _%>
+        <%_ } _%>
+        return res;
+    }
+
+    private convertDateArrayFromServer(res: EntityArrayResponseType): EntityArrayResponseType {
+        res.body.forEach ((<%= entityInstance %>: I<%= entityAngularName %>) => {
+            <%_ for (idx in fields) { _%>
+            <%_ if ( ['Instant', 'ZonedDateTime', 'LocalDate'].includes(fields[idx].fieldType) ) { _%>
+            <%= entityInstance %>.<%= fields[idx].fieldName %> = <%= entityInstance %>.<%= fields[idx].fieldName %> != null ? moment(<%= entityInstance %>.<%= fields[idx].fieldName %>) : null;
+            <%_ } _%>
+            <%_ } _%>
         });
-        return copy;
+        return res;
     }
+    <%_ } _%>
 }


Test patch:
diff --git a/generators/client/templates/angular/src/test/javascript/spec/app/core/user/user.service.spec.ts.ejs b/generators/client/templates/angular/src/test/javascript/spec/app/core/user/user.service.spec.ts.ejs
index e4e6506d80..e3be39329e 100644
--- a/generators/client/templates/angular/src/test/javascript/spec/app/core/user/user.service.spec.ts.ejs
+++ b/generators/client/templates/angular/src/test/javascript/spec/app/core/user/user.service.spec.ts.ejs
@@ -58,7 +58,7 @@ describe('Service Tests', () => {
             });
             it('should return User', () => {
 
-                service.find('user').subscribe((received) => {
+                service.find('user').subscribe(received => {
                     expect(received.body.login).toEqual('user');
                 });
 
@@ -69,7 +69,7 @@ describe('Service Tests', () => {
             <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') { _%>
             it('should return Authorities', () => {
 
-                service.authorities().subscribe((_authorities) => {
+                service.authorities().subscribe(_authorities => {
                     expect(_authorities).toEqual(['ROLE_USER', 'ROLE_ADMIN']);
                 });
                 const req = httpMock.expectOne({ method: 'GET' });
diff --git a/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs b/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
index 15eb4b7aef..ef3e7d149f 100644
--- a/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
+++ b/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
@@ -77,7 +77,7 @@ describe('Service Tests', () => {
 
             it('should return a <%= entityAngularName %>', () => {
 
-                service.find(<%- tsKeyId %>).subscribe((received) => {
+                service.find(<%- tsKeyId %>).subscribe(received => {
                     expect(received.body.id).toEqual(<%- tsKeyId %>);
                 });
 
diff --git a/test/utils/expected-files.js b/test/utils/expected-files.js
index 03042fbc67..332406654e 100644
--- a/test/utils/expected-files.js
+++ b/test/utils/expected-files.js
@@ -266,7 +266,6 @@ const expectedFiles = {
         `${CLIENT_MAIN_SRC_DIR}app/app.constants.ts`,
         `${CLIENT_MAIN_SRC_DIR}app/app.main.ts`,
         `${CLIENT_MAIN_SRC_DIR}app/app.module.ts`,
-        `${CLIENT_MAIN_SRC_DIR}app/app.route.ts`,
         `${CLIENT_MAIN_SRC_DIR}app/blocks/config/prod.config.ts`,
         `${CLIENT_MAIN_SRC_DIR}app/blocks/config/uib-pagination.config.ts`,
         `${CLIENT_MAIN_SRC_DIR}app/blocks/interceptor/auth-expired.interceptor.ts`,