blob: fc422f3359f848d508ec477593ad423015e6e370 [file] [log] [blame]
Matteo Scandolo9f87f302016-12-13 18:11:10 -08001import {IXosTableCfg} from '../../core/table/table';
Matteo Scandolo47860fe2017-02-02 12:05:55 -08002import {IXosModelStoreService} from '../../datasources/stores/model.store';
Matteo Scandolod58d5042016-12-16 16:59:21 -08003import {IXosConfigHelpersService} from '../../core/services/helpers/config.helpers';
Matteo Scandoloee655a12016-12-19 15:38:43 -08004import * as _ from 'lodash';
Matteo Scandolo80c3a652017-01-06 10:48:31 -08005import {IXosResourceService} from '../../datasources/rest/model.rest';
Matteo Scandolo04964232017-01-07 12:53:46 -08006import {IStoreHelpersService} from '../../datasources/helpers/store.helpers';
Matteo Scandolo1aee1982017-02-17 08:33:23 -08007import {IXosModelDiscovererService} from '../../datasources/helpers/model-discoverer.service';
Matteo Scandolo5d962a32017-08-01 18:16:14 -07008import './crud.scss';
9import {IXosCrudRelationService} from './crud.relations.service';
Matteo Scandolo1aee1982017-02-17 08:33:23 -080010
11export interface IXosModelRelation {
12 model: string;
13 type: string;
Matteo Scandolo5d962a32017-08-01 18:16:14 -070014 on_field: string;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080015}
16
17class CrudController {
Matteo Scandolo1aee1982017-02-17 08:33:23 -080018 static $inject = [
19 '$scope',
Matteo Scandolo5d962a32017-08-01 18:16:14 -070020 '$log',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080021 '$state',
22 '$stateParams',
23 'XosModelStore',
24 'ConfigHelpers',
25 'ModelRest',
26 'StoreHelpers',
Matteo Scandolo5d962a32017-08-01 18:16:14 -070027 'XosModelDiscoverer',
28 'XosCrudRelation'
Matteo Scandolo1aee1982017-02-17 08:33:23 -080029 ];
Matteo Scandolo9f87f302016-12-13 18:11:10 -080030
Matteo Scandolo5d962a32017-08-01 18:16:14 -070031 // bindings
32
Matteo Scandolo1aee1982017-02-17 08:33:23 -080033 public data: {model: string};
Matteo Scandolo9f87f302016-12-13 18:11:10 -080034 public tableCfg: IXosTableCfg;
Matteo Scandoloee655a12016-12-19 15:38:43 -080035 public formCfg: any;
Matteo Scandoloee655a12016-12-19 15:38:43 -080036 public baseUrl: string;
37 public list: boolean;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080038 public title: string;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080039 public tableData: any[];
Matteo Scandoloee655a12016-12-19 15:38:43 -080040 public model: any;
Matteo Scandolo5d962a32017-08-01 18:16:14 -070041 public related: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]} = {
42 manytoone: [],
43 onetomany: []
44 };
45 public relatedModels: {manytoone: any, onetomany: any} = {
46 manytoone: {},
47 onetomany: {}
48 };
Matteo Scandolo9f87f302016-12-13 18:11:10 -080049
50 constructor(
Matteo Scandolof2c3ed62016-12-15 14:32:50 -080051 private $scope: angular.IScope,
Matteo Scandolo5d962a32017-08-01 18:16:14 -070052 private $log: angular.ILogService,
Matteo Scandoloee655a12016-12-19 15:38:43 -080053 private $state: angular.ui.IStateService,
54 private $stateParams: ng.ui.IStateParamsService,
Matteo Scandolo47860fe2017-02-02 12:05:55 -080055 private store: IXosModelStoreService,
Matteo Scandolo80c3a652017-01-06 10:48:31 -080056 private ConfigHelpers: IXosConfigHelpersService,
Matteo Scandolo04964232017-01-07 12:53:46 -080057 private ModelRest: IXosResourceService,
Matteo Scandolo1aee1982017-02-17 08:33:23 -080058 private StoreHelpers: IStoreHelpersService,
Matteo Scandolo5d962a32017-08-01 18:16:14 -070059 private XosModelDiscovererService: IXosModelDiscovererService,
60 private XosCrudRelation: IXosCrudRelationService
Matteo Scandolo9f87f302016-12-13 18:11:10 -080061 ) {
Matteo Scandolo5d962a32017-08-01 18:16:14 -070062
Matteo Scandolo9f87f302016-12-13 18:11:10 -080063 this.data = this.$state.current.data;
Matteo Scandolo1aee1982017-02-17 08:33:23 -080064 this.model = this.XosModelDiscovererService.get(this.data.model);
Matteo Scandolod58d5042016-12-16 16:59:21 -080065 this.title = this.ConfigHelpers.pluralize(this.data.model);
Matteo Scandolo9f87f302016-12-13 18:11:10 -080066
Matteo Scandoloee655a12016-12-19 15:38:43 -080067 this.list = true;
Matteo Scandolo1aee1982017-02-17 08:33:23 -080068
69 // TODO get the proper URL from model discoverer
70 this.baseUrl = '#/' + this.model.clientUrl.replace(':id?', '');
71
Matteo Scandolo5d962a32017-08-01 18:16:14 -070072 this.$log.debug('[XosCrud]', $state.current.data);
Matteo Scandoloee655a12016-12-19 15:38:43 -080073
Matteo Scandolo1aee1982017-02-17 08:33:23 -080074 this.tableCfg = this.model.tableCfg;
75 this.formCfg = this.model.formCfg;
Matteo Scandoloee655a12016-12-19 15:38:43 -080076
Matteo Scandolof2c3ed62016-12-15 14:32:50 -080077 this.store.query(this.data.model)
Matteo Scandolo035c5932016-12-14 09:55:15 -080078 .subscribe(
79 (event) => {
80 // NOTE Observable mess with $digest cycles, we need to schedule the expression later
81 $scope.$evalAsync(() => {
Matteo Scandolod58d5042016-12-16 16:59:21 -080082 this.title = this.ConfigHelpers.pluralize(this.data.model, event.length);
Matteo Scandolo035c5932016-12-14 09:55:15 -080083 this.tableData = event;
Matteo Scandoloee655a12016-12-19 15:38:43 -080084
Matteo Scandolo80c3a652017-01-06 10:48:31 -080085 // if it is a detail page for an existing model
86 if ($stateParams['id'] && $stateParams['id'] !== 'add') {
Matteo Scandolo5d962a32017-08-01 18:16:14 -070087 this.related.onetomany = _.filter($state.current.data.relations, {type: 'onetomany'});
88 this.related.manytoone = _.filter($state.current.data.relations, {type: 'manytoone'});
Matteo Scandoloee655a12016-12-19 15:38:43 -080089 this.model = _.find(this.tableData, {id: parseInt($stateParams['id'], 10)});
Matteo Scandolo5d962a32017-08-01 18:16:14 -070090 this.getRelatedModels(this.related, this.model);
Matteo Scandoloee655a12016-12-19 15:38:43 -080091 }
Matteo Scandolo035c5932016-12-14 09:55:15 -080092 });
93 }
94 );
Matteo Scandoloee655a12016-12-19 15:38:43 -080095
96 // if it is a detail page
97 if ($stateParams['id']) {
98 this.list = false;
Matteo Scandolo80c3a652017-01-06 10:48:31 -080099
100 // if it is the create page
101 if ($stateParams['id'] === 'add') {
102 // generate a resource for an empty model
Matteo Scandolo47c53fc2017-03-23 14:11:32 -0700103 const endpoint = this.XosModelDiscovererService.getApiUrlFromModel(this.XosModelDiscovererService.get(this.data.model));
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800104 const resource = this.ModelRest.getResource(endpoint);
105 this.model = new resource({});
106 }
Matteo Scandoloee655a12016-12-19 15:38:43 -0800107 }
Matteo Scandolo9f87f302016-12-13 18:11:10 -0800108 }
Matteo Scandolo00d97892016-12-23 17:53:12 -0800109
Matteo Scandolo5d962a32017-08-01 18:16:14 -0700110
111 public getRelatedItemId(relation: IXosModelRelation, item: any): boolean {
112 return this.XosCrudRelation.existsRelatedItem(relation, item);
113 }
114
115 public getHumanReadableOnField(r: IXosModelRelation) {
116 return this.XosCrudRelation.getHumanReadableOnField(r, this.data.model);
117 }
118
119 public getRelatedModels(relations: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]}, item: any) {
120 this.$log.info(`[XosCrud] Managing relation for ${this.data.model}:`, relations);
121
122 // loading many to one relations (you'll get a model)
123 _.forEach(relations.manytoone, (r: IXosModelRelation) => {
124 if (!item || !item[`${r.on_field.toLowerCase()}_id`]) {
125 return;
126 }
127
128 this.$log.debug(`[XosCrud] Loading manytoone relation with ${r.model} on ${r.on_field}`);
129
130 if (!angular.isDefined(this.relatedModels.manytoone[r.model])) {
131 this.relatedModels.manytoone[r.model] = {};
132 }
133
134 this.XosCrudRelation.getModel(r, item[`${r.on_field.toLowerCase()}_id`])
135 .then(res => {
136 this.relatedModels.manytoone[r.model][r.on_field] = res;
137 })
138 .catch(err => {
139 this.$log.error(`[XosCrud] Error loading manytoone relation with ${r.model} on ${r.on_field}`, err);
140 });
141 });
142
143 // loading onetomany relations (you'll get a list of models)
144 _.forEach(relations.onetomany, (r: IXosModelRelation) => {
145 if (!item) {
146 return;
147 }
148
149 this.$log.debug(`[XosCrud] Loading onetomany relation with ${r.model} on ${r.on_field}`);
150
151 if (!angular.isDefined(this.relatedModels.onetomany[r.model])) {
152 this.relatedModels.onetomany[r.model] = {};
153 }
154
155 this.XosCrudRelation.getModels(r, item.id)
156 .then(res => {
157 this.relatedModels.onetomany[r.model][r.on_field] = res;
158 })
159 .catch(err => {
160 this.$log.error(`[XosCrud] Error loading onetomany relation with ${r.model} on ${r.on_field}`, err);
161 });
162 });
Matteo Scandolo00d97892016-12-23 17:53:12 -0800163 }
Matteo Scandolo9f87f302016-12-13 18:11:10 -0800164}
165
166export const xosCrud: angular.IComponentOptions = {
167 template: require('./crud.html'),
168 controllerAs: 'vm',
169 controller: CrudController
170};