blob: 1df2662269c21acb0231953fdae77529e331febf [file] [log] [blame]
Matteo Scandolod58d5042016-12-16 16:59:21 -08001import * as _ from 'lodash';
2import * as pluralize from 'pluralize';
Matteo Scandolocb466ed2017-01-04 17:16:24 -08003import {IXosTableColumn, IXosTableCfg} from '../../table/table';
4import {IModeldef} from '../../../datasources/rest/modeldefs.rest';
Matteo Scandolo80c3a652017-01-06 10:48:31 -08005import {IXosFormConfig, IXosFormInput} from '../../form/form';
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -08006import {IXosAuthService} from '../../../datasources/rest/auth.rest';
Matteo Scandolod58d5042016-12-16 16:59:21 -08007
8export interface IXosModelDefsField {
9 name: string;
10 type: string;
Matteo Scandolocb466ed2017-01-04 17:16:24 -080011 validators?: any;
Matteo Scandolod58d5042016-12-16 16:59:21 -080012}
13
14export interface IXosConfigHelpersService {
Matteo Scandoloee655a12016-12-19 15:38:43 -080015 excluded_fields: string[];
Matteo Scandolocb466ed2017-01-04 17:16:24 -080016 modelFieldsToColumnsCfg(fields: IXosModelDefsField[], baseUrl: string): IXosTableColumn[]; // TODO use a proper interface
Matteo Scandolo80c3a652017-01-06 10:48:31 -080017 modelToTableCfg(model: IModeldef, baseUrl: string): IXosTableCfg;
18 modelFieldToInputCfg(fields: IXosModelDefsField[]): IXosFormInput[];
19 modelToFormCfg(model: IModeldef): IXosFormConfig;
Matteo Scandolod58d5042016-12-16 16:59:21 -080020 pluralize(string: string, quantity?: number, count?: boolean): string;
21 toLabel(string: string, pluralize?: boolean): string;
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -080022 toLabels(string: string[], pluralize?: boolean): string[];
Matteo Scandolo1c5905f2017-01-04 17:41:15 -080023 urlFromCoreModel(name: string): string;
Matteo Scandolod58d5042016-12-16 16:59:21 -080024}
25
26export class ConfigHelpers {
27
Matteo Scandoloee655a12016-12-19 15:38:43 -080028 excluded_fields = [
29 'created',
30 'updated',
31 'enacted',
32 'policed',
33 'backend_register',
34 'deleted',
35 'write_protect',
36 'lazy_blocked',
37 'no_sync',
38 'no_policy',
39 'omf_friendly',
40 'enabled',
Matteo Scandolod62ea792016-12-22 14:02:28 -080041 'validators',
Matteo Scandolo80c3a652017-01-06 10:48:31 -080042 'password',
43 'backend_need_delete',
44 'backend_need_reap'
Matteo Scandoloee655a12016-12-19 15:38:43 -080045 ];
46
Matteo Scandolocb466ed2017-01-04 17:16:24 -080047 constructor(
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -080048 private toastr: ng.toastr.IToastrService,
49 private AuthService: IXosAuthService
Matteo Scandolocb466ed2017-01-04 17:16:24 -080050 ) {
Matteo Scandolod58d5042016-12-16 16:59:21 -080051 pluralize.addIrregularRule('xos', 'xosses');
52 pluralize.addPluralRule(/slice$/i, 'slices');
Matteo Scandolo80c3a652017-01-06 10:48:31 -080053 pluralize.addSingularRule(/slice$/i, 'slice');
Matteo Scandolod58d5042016-12-16 16:59:21 -080054 }
55
Matteo Scandolo1c5905f2017-01-04 17:41:15 -080056 public pluralize(string: string, quantity?: number, count?: boolean): string {
Matteo Scandolod58d5042016-12-16 16:59:21 -080057 return pluralize(string, quantity, count);
58 }
59
Matteo Scandolo1c5905f2017-01-04 17:41:15 -080060 public toLabels(strings: string[], pluralize?: boolean): string[] {
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -080061 if (angular.isArray(strings)) {
62 return _.map(strings, s => {
Matteo Scandolod58d5042016-12-16 16:59:21 -080063 return this.toLabel(s, pluralize);
64 });
65 }
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -080066 }
67
Matteo Scandolo1c5905f2017-01-04 17:41:15 -080068 public toLabel(string: string, pluralize?: boolean): string {
Matteo Scandolod58d5042016-12-16 16:59:21 -080069
70 if (pluralize) {
71 string = this.pluralize(string);
72 }
73
74 string = this.fromCamelCase(string);
75 string = this.fromSnakeCase(string);
76 string = this.fromKebabCase(string);
77
78 return this.capitalizeFirst(string);
79 }
80
Matteo Scandolo1c5905f2017-01-04 17:41:15 -080081 public modelToTableCfg(model: IModeldef, baseUrl: string): IXosTableCfg {
Matteo Scandolocb466ed2017-01-04 17:16:24 -080082 const cfg = {
83 columns: this.modelFieldsToColumnsCfg(model.fields, baseUrl),
84 filter: 'fulltext',
85 order: {field: 'id', reverse: false},
86 actions: [
87 {
88 label: 'delete',
89 icon: 'remove',
90 color: 'red',
91 cb: (item) => {
92 let obj = angular.copy(item);
93
94 item.$delete()
95 .then((res) => {
96 if (res.status === 404) {
97 // TODO understand why it does not go directly in catch
98 throw new Error();
99 }
100 this.toastr.info(`${model.name} ${obj.name} succesfully deleted`);
101 })
102 .catch(() => {
103 this.toastr.error(`Error while deleting ${obj.name}`);
104 });
105 }
106 }
107 ]
108 };
109 return cfg;
110 }
111
Matteo Scandolo1c5905f2017-01-04 17:41:15 -0800112 public modelFieldsToColumnsCfg(fields: IXosModelDefsField[], baseUrl: string): IXosTableColumn[] {
Matteo Scandoloee655a12016-12-19 15:38:43 -0800113
Matteo Scandolo231de262017-01-04 16:33:14 -0800114 const columns = _.map(fields, (f) => {
Matteo Scandoloee655a12016-12-19 15:38:43 -0800115 if (this.excluded_fields.indexOf(f.name) > -1) {
Matteo Scandolod58d5042016-12-16 16:59:21 -0800116 return;
117 }
118 const col: IXosTableColumn = {
119 label: this.toLabel(f.name),
120 prop: f.name
121 };
122
Matteo Scandoloa8a6fbb2016-12-21 16:59:08 -0800123 if (f.name === 'id' || f.name === 'name') {
Matteo Scandolo99ac9d92017-01-03 13:58:19 -0800124 // NOTE can we find a better method to generalize the route?
Matteo Scandoloee655a12016-12-19 15:38:43 -0800125 col.link = item => `#/core${baseUrl.replace(':id?', item.id)}`;
126 }
127
Matteo Scandolod58d5042016-12-16 16:59:21 -0800128 if (f.name === 'backend_status') {
129 col.type = 'icon';
130 col.formatter = (item) => {
131 if (item.backend_status.indexOf('1') > -1) {
132 return 'check';
133 }
134 if (item.backend_status.indexOf('2') > -1) {
135 return 'exclamation-circle';
136 }
137 if (item.backend_status.indexOf('0') > -1) {
138 return 'clock-o';
139 }
140 };
141 }
Matteo Scandoloa8a6fbb2016-12-21 16:59:08 -0800142
Matteo Scandolod58d5042016-12-16 16:59:21 -0800143 return col;
144 })
145 .filter(v => angular.isDefined(v));
146
Matteo Scandolo231de262017-01-04 16:33:14 -0800147 return columns;
Matteo Scandolod58d5042016-12-16 16:59:21 -0800148 };
149
Matteo Scandolo1c5905f2017-01-04 17:41:15 -0800150 public urlFromCoreModel(name: string): string {
151 return `/core/${this.pluralize(name.toLowerCase())}`;
152 }
153
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800154 public modelFieldToInputCfg(fields: IXosModelDefsField[]): IXosFormInput[] {
155
156 return _.map(fields, f => {
157 return {
158 name: f.name,
159 label: this.toLabel(f.name),
160 type: f.type,
161 validators: f.validators
162 };
163 })
164 .filter(f => this.excluded_fields.indexOf(f.name) === -1);
165 }
166
167 public modelToFormCfg(model: IModeldef): IXosFormConfig {
168 return {
169 formName: `${model.name}Form`,
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800170 exclude: ['backend_status', 'creator'],
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800171 actions: [{
172 label: 'Save',
173 class: 'success',
174 icon: 'ok',
175 cb: (item, form) => {
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800176 const model = angular.copy(item);
177
178 // TODO remove ManyToMany relations and save them separately (how??)
179 delete item.networks;
180
181 // adding userId as creator
182 item.creator = this.AuthService.getUser().id;
183
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800184 item.$save()
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800185 .then((res) => {
186 if (res.status === 403 || res.status === 405 || res.status === 500) {
187 // TODO understand why 405 does not go directly in catch (it may be realted to ng-rest-gw)
188 throw new Error();
189 }
190 this.toastr.success(`${model.name} succesfully saved`);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800191 })
192 .catch(err => {
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800193 // TODO keep the edited model
194 this.toastr.error(`Error while saving ${model.name}`);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800195 });
196 }
197 }],
198 inputs: this.modelFieldToInputCfg(model.fields)
199 };
200 }
201
Matteo Scandolod58d5042016-12-16 16:59:21 -0800202 private fromCamelCase(string: string): string {
203 return string.split(/(?=[A-Z])/).map(w => w.toLowerCase()).join(' ');
204 }
205
206 private fromSnakeCase(string: string): string {
207 return string.split('_').join(' ').trim();
208 }
209
210 private fromKebabCase(string: string): string {
211 return string.split('-').join(' ').trim();
212 }
213
214 private capitalizeFirst(string: string): string {
215 return string.slice(0, 1).toUpperCase() + string.slice(1);
216 }
217}