[CORD-2810] Prevent the user from inserting values in read_only fields
Change-Id: I00460544dd7d36f8482b04ea89912005a108f6b8
diff --git a/src/app/core/field/field.html b/src/app/core/field/field.html
index a91665d..5189ea5 100644
--- a/src/app/core/field/field.html
+++ b/src/app/core/field/field.html
@@ -18,99 +18,107 @@
<label ng-if="vm.field.type !== 'object' && vm.field.type !== 'array'">
{{vm.field.label}}
<span class="required" ng-if="vm.field.validators.required">*</span>
+ <span class="read-only" ng-if="vm.field.read_only">read only</span>
</label>
-<input
- xos-custom-validator custom-validator="vm.field.validators.custom || null"
- ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select' && vm.field.type !== 'array'"
- type="{{vm.field.type}}"
- name="{{vm.name}}"
- class="form-control"
- ng-model="vm.ngModel"
- ng-minlength="vm.field.validators.minlength || 0"
- ng-maxlength="vm.field.validators.maxlength || 2000"
- ng-required="vm.field.validators.required || false" />
-<select class="form-control" ng-if="vm.field.type === 'select'"
- name = "{{vm.name}}"
- ng-options="item.id as item.label for item in vm.field.options"
- ng-model="vm.ngModel"
- ng-required="vm.field.validators.required || false">
-</select>
-<span class="boolean-field" ng-if="vm.field.type === 'boolean'">
- <a
- class="btn btn-success"
- ng-show="vm.ngModel"
- ng-click="vm.ngModel = false">
- <i class="fa fa-check"></i>
- </a>
- <a
- class="btn btn-danger"
- ng-show="!vm.ngModel"
- ng-click="vm.ngModel = true">
- <i class="fa fa-remove"></i>
- </a>
- </span>
-<div
- class="panel panel-default object-field"
- ng-if="vm.field.type == 'object' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"
->
- <div class="panel-heading">{{vm.field.label}}</div>
- <div class="panel-body">
- <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">
- <xos-field
- name="k"
- field="{label: vm.formatLabel(k), type: vm.getType(v)}"
- ng-model="v">
- </xos-field>
- </div>
- <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">
- <xos-field
- name="k"
- field="{
- label: v.label || vm.formatLabel(k),
- type: v.type,
- validators: v.validators
- }"
- ng-model="vm.ngModel[k]">
- </xos-field>
- </div>
- </div>
+
+<div ng-if="vm.field.read_only">
+ <pre class="form-control" readonly>{{vm.ngModel || ""}}</pre>
</div>
-<div
- class="panel panel-default array-field"
- ng-if="vm.field.type == 'array'">
- <div class="panel-heading">{{vm.field.label}}</div>
- <div class="panel-body selected">
- <ul class="draggable" dnd-list="vm.ngModel">
- <li
- class="array-element"
- ng-repeat="item in vm.ngModel"
- dnd-draggable="item"
- dnd-moved="vm.ngModel.splice($index, 1)"
- dnd-effect-allowed="move"
- dnd-selected="models.selected = item"
- >
- <div class="well well-sm text-center">
- {{item}}
- </div>
- </li>
- <div class="clearfix"></div>
- </ul>
+
+<div ng-if="!vm.field.read_only">
+ <input
+ xos-custom-validator custom-validator="vm.field.validators.custom || null"
+ ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select' && vm.field.type !== 'array'"
+ type="{{vm.field.type}}"
+ name="{{vm.name}}"
+ class="form-control"
+ ng-model="vm.ngModel"
+ ng-minlength="vm.field.validators.minlength || 0"
+ ng-maxlength="vm.field.validators.maxlength || 2000"
+ ng-required="vm.field.validators.required || false" />
+ <select class="form-control" ng-if="vm.field.type === 'select'"
+ name = "{{vm.name}}"
+ ng-options="item.id as item.label for item in vm.field.options"
+ ng-model="vm.ngModel"
+ ng-required="vm.field.validators.required || false">
+ </select>
+ <span class="boolean-field" ng-if="vm.field.type === 'boolean'">
+ <a
+ class="btn btn-success"
+ ng-show="vm.ngModel"
+ ng-click="vm.ngModel = false">
+ <i class="fa fa-check"></i>
+ </a>
+ <a
+ class="btn btn-danger"
+ ng-show="!vm.ngModel"
+ ng-click="vm.ngModel = true">
+ <i class="fa fa-remove"></i>
+ </a>
+ </span>
+ <div
+ class="panel panel-default object-field"
+ ng-if="vm.field.type == 'object' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"
+ >
+ <div class="panel-heading">{{vm.field.label}}</div>
+ <div class="panel-body">
+ <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">
+ <xos-field
+ name="k"
+ field="{label: vm.formatLabel(k), type: vm.getType(v)}"
+ ng-model="v">
+ </xos-field>
+ </div>
+ <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">
+ <xos-field
+ name="k"
+ field="{
+ label: v.label || vm.formatLabel(k),
+ type: v.type,
+ validators: v.validators
+ }"
+ ng-model="vm.ngModel[k]">
+ </xos-field>
+ </div>
+ </div>
</div>
- <div class="panel-body unselected">
- <ul class="draggable" dnd-list="vm.field.availableOptions">
- <li
- class="array-element"
- ng-repeat="item in vm.field.availableOptions"
- dnd-draggable="item"
- dnd-moved="vm.field.availableOptions.splice($index, 1)"
- dnd-effect-allowed="move"
- dnd-selected="models.selected = item"
- >
- <div class="well well-sm text-center">
- {{item}}
- </div>
- </li>
- <div class="clearfix"></div>
- </ul>
+ <div
+ class="panel panel-default array-field"
+ ng-if="vm.field.type == 'array'">
+ <div class="panel-heading">{{vm.field.label}}</div>
+ <div class="panel-body selected">
+ <ul class="draggable" dnd-list="vm.ngModel">
+ <li
+ class="array-element"
+ ng-repeat="item in vm.ngModel"
+ dnd-draggable="item"
+ dnd-moved="vm.ngModel.splice($index, 1)"
+ dnd-effect-allowed="move"
+ dnd-selected="models.selected = item"
+ >
+ <div class="well well-sm text-center">
+ {{item}}
+ </div>
+ </li>
+ <div class="clearfix"></div>
+ </ul>
+ </div>
+ <div class="panel-body unselected">
+ <ul class="draggable" dnd-list="vm.field.availableOptions">
+ <li
+ class="array-element"
+ ng-repeat="item in vm.field.availableOptions"
+ dnd-draggable="item"
+ dnd-moved="vm.field.availableOptions.splice($index, 1)"
+ dnd-effect-allowed="move"
+ dnd-selected="models.selected = item"
+ >
+ <div class="well well-sm text-center">
+ {{item}}
+ </div>
+ </li>
+ <div class="clearfix"></div>
+ </ul>
+ </div>
</div>
</div>
\ No newline at end of file
diff --git a/src/app/core/field/field.scss b/src/app/core/field/field.scss
index 7bdb659..b86c95f 100644
--- a/src/app/core/field/field.scss
+++ b/src/app/core/field/field.scss
@@ -18,6 +18,12 @@
@import "../../style/vars";
-span.required {
+span.required,
+span.read-only {
color: $color-accent;
+}
+
+span.read-only {
+ vertical-align: super;
+ font-size: 70%;
}
\ No newline at end of file
diff --git a/src/app/core/form/form.spec.ts b/src/app/core/form/form.spec.ts
index b010907..1be9a43 100644
--- a/src/app/core/form/form.spec.ts
+++ b/src/app/core/form/form.spec.ts
@@ -102,13 +102,15 @@
name: 'id',
label: 'Id:',
type: 'number',
- validators: {}
+ validators: {},
+ read_only: false
},
{
name: 'first_name',
label: 'Name:',
type: 'text',
- validators: {}
+ validators: {},
+ read_only: false
},
{
name: 'email',
@@ -116,19 +118,22 @@
type: 'email',
validators: {
required: true
- }
+ },
+ read_only: false
},
{
name: 'birthDate',
label: 'DOB:',
type: 'date',
- validators: {}
+ validators: {},
+ read_only: false
},
{
name: 'enabled',
label: 'Status:',
type: 'boolean',
- validators: {}
+ validators: {},
+ read_only: false
},
{
name: 'role',
@@ -138,7 +143,8 @@
{id: 1, label: 'user'},
{id: 2, label: 'admin'}
],
- validators: {}
+ validators: {},
+ read_only: false
}
];
diff --git a/src/app/core/form/form.ts b/src/app/core/form/form.ts
index 8faa2bd..1c10c33 100644
--- a/src/app/core/form/form.ts
+++ b/src/app/core/form/form.ts
@@ -56,6 +56,7 @@
name: string;
label: string;
type: string; // options are: [date, boolean, number, email, string, select],
+ read_only: boolean;
hint?: string;
validators: IXosFormInputValidator;
options?: IXosFormInputOptions[];
diff --git a/src/app/core/services/helpers/config.helpers.spec.ts b/src/app/core/services/helpers/config.helpers.spec.ts
index db1c840..9e7318e 100644
--- a/src/app/core/services/helpers/config.helpers.spec.ts
+++ b/src/app/core/services/helpers/config.helpers.spec.ts
@@ -36,7 +36,8 @@
{
type: 'number',
name: 'id',
- validators: []
+ validators: [],
+ read_only: false
},
{
type: 'string',
@@ -46,7 +47,8 @@
bool_value: true,
name: 'required'
}
- ]
+ ],
+ read_only: false
},
{
type: 'string',
@@ -56,7 +58,8 @@
int_value: 30,
name: 'maxlength'
}
- ]
+ ],
+ read_only: false
},
{
type: 'number',
@@ -70,12 +73,14 @@
int_value: 40,
name: 'max'
}
- ]
+ ],
+ read_only: false
},
{
type: 'date',
name: 'updated',
- validators: []
+ validators: [],
+ read_only: false
},
],
description: '',
@@ -255,13 +260,15 @@
type: 'boolean',
name: 'active',
default: '"True"',
- validators: []
+ validators: [],
+ read_only: false
},
{
type: 'boolean',
name: 'disabled',
default: '"False"',
- validators: []
+ validators: [],
+ read_only: false
},
];
const form_fields = service.modelFieldToInputCfg(fields);
@@ -312,7 +319,8 @@
relation: {
model: 'Test',
type: 'many_to_one'
- }
+ },
+ read_only: false
};
describe('the populateRelated method', () => {
@@ -332,7 +340,8 @@
name: 'test',
label: 'Test',
type: 'select',
- validators: {}
+ validators: {},
+ read_only: false
};
it('should add the available choice to the select', () => {
@@ -358,7 +367,8 @@
{
type: 'number',
name: 'foo',
- validators: []
+ validators: [],
+ read_only: false
},
{
type: 'string',
@@ -368,7 +378,8 @@
bool_value: true,
name: 'required'
}
- ]
+ ],
+ read_only: false
}
],
description: '',
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index 4baf9c5..443b6c2 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -34,6 +34,7 @@
export interface IXosModelDefsField {
name: string;
type: string;
+ read_only: boolean;
validators?: IXosModelDefsFieldValidators[];
hint?: string;
relation?: {
@@ -271,7 +272,8 @@
type: f.type,
validators: this.formatValidators(f.validators),
hint: f.hint,
- default: this.formatDefaultValues(f.default)
+ default: this.formatDefaultValues(f.default),
+ read_only: f.read_only
};
// NOTE populate drop-downs based on relation
diff --git a/src/app/datasources/helpers/model-discoverer.service.ts b/src/app/datasources/helpers/model-discoverer.service.ts
index 0addc05..fca593c 100644
--- a/src/app/datasources/helpers/model-discoverer.service.ts
+++ b/src/app/datasources/helpers/model-discoverer.service.ts
@@ -19,11 +19,11 @@
// TODO test me hard!!!
import * as _ from 'lodash';
-import {IXosModeldefsService, IXosModeldef, IXosModelDefsField, IXosModelDefsRelation} from '../rest/modeldefs.rest';
+import {IXosModeldefsService, IXosModeldef, IXosModelDefsRelation} from '../rest/modeldefs.rest';
import {IXosTableCfg} from '../../core/table/table';
import {IXosFormCfg} from '../../core/form/form';
import {IXosNavigationService} from '../../core/services/navigation';
-import {IXosConfigHelpersService} from '../../core/services/helpers/config.helpers';
+import {IXosConfigHelpersService, IXosModelDefsField} from '../../core/services/helpers/config.helpers';
import {IXosRuntimeStatesService, IXosState} from '../../core/services/runtime-states';
import {IXosModelStoreService} from '../stores/model.store';
import {IXosAuthService} from '../rest/auth.rest';
diff --git a/src/app/datasources/helpers/model.discoverer.service.spec.ts b/src/app/datasources/helpers/model.discoverer.service.spec.ts
index 8011442..a6e6340 100644
--- a/src/app/datasources/helpers/model.discoverer.service.spec.ts
+++ b/src/app/datasources/helpers/model.discoverer.service.spec.ts
@@ -26,8 +26,8 @@
const stubModels: IXosModeldef[] = [
{
fields: [
- {name: 'id', type: 'number'},
- {name: 'foo', type: 'string'}
+ {name: 'id', type: 'number', read_only: false},
+ {name: 'foo', type: 'string', read_only: false}
],
relations: [],
name: 'Node',
@@ -37,8 +37,8 @@
},
{
fields: [
- {name: 'id', type: 'number'},
- {name: 'bar', type: 'string'}
+ {name: 'id', type: 'number', read_only: false},
+ {name: 'bar', type: 'string', read_only: false}
],
relations: [],
name: 'VSGTenant',
diff --git a/src/app/datasources/helpers/modeldefs.service.spec.ts b/src/app/datasources/helpers/modeldefs.service.spec.ts
index 9d5660d..e0f37a6 100644
--- a/src/app/datasources/helpers/modeldefs.service.spec.ts
+++ b/src/app/datasources/helpers/modeldefs.service.spec.ts
@@ -43,8 +43,8 @@
const modelDef: IXosModel = {
fields: [
- {name: 'id', type: 'number'},
- {name: 'foo', type: 'string'}
+ {name: 'id', type: 'number', read_only: false},
+ {name: 'foo', type: 'string', read_only: false}
],
relations: [],
name: 'Node',
diff --git a/src/app/datasources/rest/modeldefs.rest.ts b/src/app/datasources/rest/modeldefs.rest.ts
index 300b71b..60fc917 100644
--- a/src/app/datasources/rest/modeldefs.rest.ts
+++ b/src/app/datasources/rest/modeldefs.rest.ts
@@ -19,18 +19,6 @@
import {IXosModelDefsField} from '../../core/services/helpers/config.helpers';
import {IXosAppConfig} from '../../../index';
-// Models interfaces
-export interface IXosModelDefsField {
- name: string;
- type: string;
- validators?: any;
- hint?: string;
- relation?: {
- model: string;
- type: string;
- };
-}
-
export interface IXosModelDefsRelation {
model: string; // model name
type: string; // relation type
diff --git a/src/app/views/crud/crud.html b/src/app/views/crud/crud.html
index 596add8..c586bca 100644
--- a/src/app/views/crud/crud.html
+++ b/src/app/views/crud/crud.html
@@ -49,7 +49,7 @@
<xos-form ng-model="vm.model" config="vm.formCfg"></xos-form>
</div>
</uib-tab>
- <uib-tab ng-if="vm.debugTab" heading="Debug">
+ <uib-tab ng-if="vm.debugTab && vm.model.id" heading="Debug">
<div class="panel-body">
<xos-debug-model ng-model="vm.model"></xos-debug-model>
</div>