blob: e281d16398dc1566c4e0bc2d99ded0abb2a041a4 [file] [log] [blame]
Matteo Scandolofb46ae62017-08-08 09:10:50 -07001
2/*
3 * Copyright 2017-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
Matteo Scandolo9f87f302016-12-13 18:11:10 -080019import {IXosTableCfg} from '../../core/table/table';
Matteo Scandolo47860fe2017-02-02 12:05:55 -080020import {IXosModelStoreService} from '../../datasources/stores/model.store';
Matteo Scandolod58d5042016-12-16 16:59:21 -080021import {IXosConfigHelpersService} from '../../core/services/helpers/config.helpers';
Matteo Scandoloee655a12016-12-19 15:38:43 -080022import * as _ from 'lodash';
Matteo Scandolo80c3a652017-01-06 10:48:31 -080023import {IXosResourceService} from '../../datasources/rest/model.rest';
Matteo Scandolo04964232017-01-07 12:53:46 -080024import {IStoreHelpersService} from '../../datasources/helpers/store.helpers';
Matteo Scandolo1aee1982017-02-17 08:33:23 -080025import {IXosModelDiscovererService} from '../../datasources/helpers/model-discoverer.service';
Matteo Scandolo5d962a32017-08-01 18:16:14 -070026import './crud.scss';
27import {IXosCrudRelationService} from './crud.relations.service';
Matteo Scandolo1aee1982017-02-17 08:33:23 -080028
29export interface IXosModelRelation {
30 model: string;
31 type: string;
Matteo Scandolo5d962a32017-08-01 18:16:14 -070032 on_field: string;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080033}
34
35class CrudController {
Matteo Scandolo1aee1982017-02-17 08:33:23 -080036 static $inject = [
37 '$scope',
Matteo Scandolo5d962a32017-08-01 18:16:14 -070038 '$log',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080039 '$state',
40 '$stateParams',
41 'XosModelStore',
42 'ConfigHelpers',
43 'ModelRest',
44 'StoreHelpers',
Matteo Scandolo5d962a32017-08-01 18:16:14 -070045 'XosModelDiscoverer',
46 'XosCrudRelation'
Matteo Scandolo1aee1982017-02-17 08:33:23 -080047 ];
Matteo Scandolo9f87f302016-12-13 18:11:10 -080048
Matteo Scandolo5d962a32017-08-01 18:16:14 -070049 // bindings
50
Matteo Scandolo1aee1982017-02-17 08:33:23 -080051 public data: {model: string};
Matteo Scandolo9f87f302016-12-13 18:11:10 -080052 public tableCfg: IXosTableCfg;
Matteo Scandoloee655a12016-12-19 15:38:43 -080053 public formCfg: any;
Matteo Scandoloee655a12016-12-19 15:38:43 -080054 public baseUrl: string;
55 public list: boolean;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080056 public title: string;
Matteo Scandolo9f87f302016-12-13 18:11:10 -080057 public tableData: any[];
Matteo Scandoloee655a12016-12-19 15:38:43 -080058 public model: any;
Matteo Scandolo5d962a32017-08-01 18:16:14 -070059 public related: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]} = {
60 manytoone: [],
61 onetomany: []
62 };
63 public relatedModels: {manytoone: any, onetomany: any} = {
64 manytoone: {},
65 onetomany: {}
66 };
Matteo Scandolo9f87f302016-12-13 18:11:10 -080067
68 constructor(
Matteo Scandolof2c3ed62016-12-15 14:32:50 -080069 private $scope: angular.IScope,
Matteo Scandolo5d962a32017-08-01 18:16:14 -070070 private $log: angular.ILogService,
Matteo Scandoloee655a12016-12-19 15:38:43 -080071 private $state: angular.ui.IStateService,
72 private $stateParams: ng.ui.IStateParamsService,
Matteo Scandolo47860fe2017-02-02 12:05:55 -080073 private store: IXosModelStoreService,
Matteo Scandolo80c3a652017-01-06 10:48:31 -080074 private ConfigHelpers: IXosConfigHelpersService,
Matteo Scandolo04964232017-01-07 12:53:46 -080075 private ModelRest: IXosResourceService,
Matteo Scandolo1aee1982017-02-17 08:33:23 -080076 private StoreHelpers: IStoreHelpersService,
Matteo Scandolo5d962a32017-08-01 18:16:14 -070077 private XosModelDiscovererService: IXosModelDiscovererService,
78 private XosCrudRelation: IXosCrudRelationService
Matteo Scandolo9f87f302016-12-13 18:11:10 -080079 ) {
Matteo Scandolo5d962a32017-08-01 18:16:14 -070080
Matteo Scandolo9f87f302016-12-13 18:11:10 -080081 this.data = this.$state.current.data;
Matteo Scandolo1aee1982017-02-17 08:33:23 -080082 this.model = this.XosModelDiscovererService.get(this.data.model);
Matteo Scandolod58d5042016-12-16 16:59:21 -080083 this.title = this.ConfigHelpers.pluralize(this.data.model);
Matteo Scandolo9f87f302016-12-13 18:11:10 -080084
Matteo Scandoloee655a12016-12-19 15:38:43 -080085 this.list = true;
Matteo Scandolo1aee1982017-02-17 08:33:23 -080086
87 // TODO get the proper URL from model discoverer
88 this.baseUrl = '#/' + this.model.clientUrl.replace(':id?', '');
89
Matteo Scandolo5d962a32017-08-01 18:16:14 -070090 this.$log.debug('[XosCrud]', $state.current.data);
Matteo Scandoloee655a12016-12-19 15:38:43 -080091
Matteo Scandolo1aee1982017-02-17 08:33:23 -080092 this.tableCfg = this.model.tableCfg;
93 this.formCfg = this.model.formCfg;
Matteo Scandoloee655a12016-12-19 15:38:43 -080094
Matteo Scandolof2c3ed62016-12-15 14:32:50 -080095 this.store.query(this.data.model)
Matteo Scandolo035c5932016-12-14 09:55:15 -080096 .subscribe(
97 (event) => {
98 // NOTE Observable mess with $digest cycles, we need to schedule the expression later
99 $scope.$evalAsync(() => {
Matteo Scandolod58d5042016-12-16 16:59:21 -0800100 this.title = this.ConfigHelpers.pluralize(this.data.model, event.length);
Matteo Scandolo035c5932016-12-14 09:55:15 -0800101 this.tableData = event;
Matteo Scandoloee655a12016-12-19 15:38:43 -0800102
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800103 // if it is a detail page for an existing model
104 if ($stateParams['id'] && $stateParams['id'] !== 'add') {
Matteo Scandolo5d962a32017-08-01 18:16:14 -0700105 this.related.onetomany = _.filter($state.current.data.relations, {type: 'onetomany'});
106 this.related.manytoone = _.filter($state.current.data.relations, {type: 'manytoone'});
Matteo Scandoloee655a12016-12-19 15:38:43 -0800107 this.model = _.find(this.tableData, {id: parseInt($stateParams['id'], 10)});
Matteo Scandolo5d962a32017-08-01 18:16:14 -0700108 this.getRelatedModels(this.related, this.model);
Matteo Scandoloee655a12016-12-19 15:38:43 -0800109 }
Matteo Scandolo035c5932016-12-14 09:55:15 -0800110 });
111 }
112 );
Matteo Scandoloee655a12016-12-19 15:38:43 -0800113
114 // if it is a detail page
115 if ($stateParams['id']) {
116 this.list = false;
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800117
118 // if it is the create page
119 if ($stateParams['id'] === 'add') {
120 // generate a resource for an empty model
Matteo Scandolo47c53fc2017-03-23 14:11:32 -0700121 const endpoint = this.XosModelDiscovererService.getApiUrlFromModel(this.XosModelDiscovererService.get(this.data.model));
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800122 const resource = this.ModelRest.getResource(endpoint);
123 this.model = new resource({});
124 }
Matteo Scandoloee655a12016-12-19 15:38:43 -0800125 }
Matteo Scandolo9f87f302016-12-13 18:11:10 -0800126 }
Matteo Scandolo00d97892016-12-23 17:53:12 -0800127
Matteo Scandolo5d962a32017-08-01 18:16:14 -0700128
129 public getRelatedItemId(relation: IXosModelRelation, item: any): boolean {
130 return this.XosCrudRelation.existsRelatedItem(relation, item);
131 }
132
133 public getHumanReadableOnField(r: IXosModelRelation) {
134 return this.XosCrudRelation.getHumanReadableOnField(r, this.data.model);
135 }
136
137 public getRelatedModels(relations: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]}, item: any) {
138 this.$log.info(`[XosCrud] Managing relation for ${this.data.model}:`, relations);
139
140 // loading many to one relations (you'll get a model)
141 _.forEach(relations.manytoone, (r: IXosModelRelation) => {
142 if (!item || !item[`${r.on_field.toLowerCase()}_id`]) {
143 return;
144 }
145
146 this.$log.debug(`[XosCrud] Loading manytoone relation with ${r.model} on ${r.on_field}`);
147
148 if (!angular.isDefined(this.relatedModels.manytoone[r.model])) {
149 this.relatedModels.manytoone[r.model] = {};
150 }
151
152 this.XosCrudRelation.getModel(r, item[`${r.on_field.toLowerCase()}_id`])
153 .then(res => {
154 this.relatedModels.manytoone[r.model][r.on_field] = res;
155 })
156 .catch(err => {
157 this.$log.error(`[XosCrud] Error loading manytoone relation with ${r.model} on ${r.on_field}`, err);
158 });
159 });
160
161 // loading onetomany relations (you'll get a list of models)
162 _.forEach(relations.onetomany, (r: IXosModelRelation) => {
163 if (!item) {
164 return;
165 }
166
167 this.$log.debug(`[XosCrud] Loading onetomany relation with ${r.model} on ${r.on_field}`);
168
169 if (!angular.isDefined(this.relatedModels.onetomany[r.model])) {
170 this.relatedModels.onetomany[r.model] = {};
171 }
172
173 this.XosCrudRelation.getModels(r, item.id)
174 .then(res => {
175 this.relatedModels.onetomany[r.model][r.on_field] = res;
176 })
177 .catch(err => {
178 this.$log.error(`[XosCrud] Error loading onetomany relation with ${r.model} on ${r.on_field}`, err);
179 });
180 });
Matteo Scandolo00d97892016-12-23 17:53:12 -0800181 }
Matteo Scandolo9f87f302016-12-13 18:11:10 -0800182}
183
184export const xosCrud: angular.IComponentOptions = {
185 template: require('./crud.html'),
186 controllerAs: 'vm',
187 controller: CrudController
188};