[CORD-1338] Inline navigation for related models

Change-Id: I58ff4a4675d1ce1140fe162f1f8360f2dc9a6527
diff --git a/src/app/views/crud/crud.relations.service.ts b/src/app/views/crud/crud.relations.service.ts
new file mode 100644
index 0000000..292c6f5
--- /dev/null
+++ b/src/app/views/crud/crud.relations.service.ts
@@ -0,0 +1,109 @@
+import {IXosModelRelation} from './crud';
+import {IXosModelStoreService} from '../../datasources/stores/model.store';
+import {IXosModelDiscovererService} from '../../datasources/helpers/model-discoverer.service';
+import * as _ from 'lodash';
+import {IXosFormCfg} from '../../core/form/form';
+import {IXosTableCfg} from '../../core/table/table';
+import {IXosConfigHelpersService} from '../../core/services/helpers/config.helpers';
+
+interface IXosCrudRelationBaseTabData {
+  model: any;
+  class?: 'full' | 'empty';
+}
+
+export interface IXosCrudRelationFormTabData extends IXosCrudRelationBaseTabData {
+  formConfig: IXosFormCfg;
+}
+
+export interface IXosCrudRelationTableTabData extends IXosCrudRelationBaseTabData {
+  tableConfig: IXosTableCfg;
+}
+
+export interface IXosCrudRelationService {
+  getModel(r: IXosModelRelation, id: string | number): Promise<IXosCrudRelationFormTabData>;
+  getModels(r: IXosModelRelation, source_id: string | number): Promise<IXosCrudRelationTableTabData>;
+  existsRelatedItem(r: IXosModelRelation, item: any): boolean;
+  getHumanReadableOnField(r: IXosModelRelation, baseModel: string): string;
+}
+
+export class XosCrudRelationService implements IXosCrudRelationService {
+
+  static $inject = [
+    '$log',
+    '$q',
+    'XosModelStore',
+    'XosModelDiscoverer',
+    'ConfigHelpers'
+  ];
+
+  constructor (
+    private $log: ng.ILogService,
+    private $q: ng.IQService,
+    private XosModelStore: IXosModelStoreService,
+    private XosModelDiscovererService: IXosModelDiscovererService,
+    private ConfigHelpers: IXosConfigHelpersService
+  ) {}
+
+  public getModel (r: IXosModelRelation, id: string | number): Promise<IXosCrudRelationFormTabData> {
+    const d = this.$q.defer();
+    this.XosModelStore.get(r.model, id)
+      .subscribe(
+        item => {
+          this.$log.debug(`[XosCrud] Loaded manytoone relation with ${r.model} on ${r.on_field}`, item);
+
+          const data: IXosCrudRelationFormTabData = {
+            model: item,
+            formConfig: this.XosModelDiscovererService.get(r.model).formCfg,
+            class: angular ? 'full' : 'empty'
+          };
+
+          d.resolve(data);
+        },
+        err => d.reject
+      );
+    return d.promise;
+  };
+
+  public getModels(r: IXosModelRelation, source_id: string | number): Promise<IXosCrudRelationTableTabData> {
+    const d = this.$q.defer();
+
+    this.XosModelStore.query(r.model)
+      .subscribe(
+        items => {
+          this.$log.debug(`[XosCrud] Loaded onetomany relation with ${r.model} on ${r.on_field}`, items);
+          // building the filter parameters
+          const match = {};
+          match[`${r.on_field.toLowerCase()}_id`] = source_id;
+          const filtered = _.filter(items, match);
+          // removing search bar from table
+          const tableCfg = this.XosModelDiscovererService.get(r.model).tableCfg;
+          tableCfg.filter = null;
+
+          const data: IXosCrudRelationTableTabData = {
+            model: filtered,
+            tableConfig: tableCfg,
+            class: filtered.length > 0 ? 'full' : 'empty'
+          };
+
+          d.resolve(data);
+        },
+        err => d.reject
+      );
+
+    return d.promise;
+  }
+
+  public existsRelatedItem(r: IXosModelRelation, item: any): boolean {
+    return item && angular.isDefined(item[`${r.on_field.toLowerCase()}_id`]);
+  }
+
+  public getHumanReadableOnField(r: IXosModelRelation, baseModel: string): string {
+    if (r.on_field.toLowerCase() === baseModel.toLowerCase()) {
+      return '';
+    }
+    if (r.model.toLowerCase() === r.on_field.toLowerCase()) {
+      return '';
+    }
+    return `[${this.ConfigHelpers.toLabel(r.on_field, false)}]`;
+  }
+}