Merge "add toggle function to XosSidePanel"
diff --git a/src/app/core/field/field.html b/src/app/core/field/field.html
index 9baa1d5..5dad952 100644
--- a/src/app/core/field/field.html
+++ b/src/app/core/field/field.html
@@ -12,7 +12,7 @@
         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'"
+<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"
diff --git a/src/app/core/field/field.ts b/src/app/core/field/field.ts
index 5c5b48a..f05a8e4 100644
--- a/src/app/core/field/field.ts
+++ b/src/app/core/field/field.ts
@@ -38,6 +38,16 @@
       throw new Error('[xosField] Please provide an ng-model');
     }
 
+    // NOTE set default value (if any)
+    if (this.field.default && !angular.isDefined(this.ngModel)) {
+      if (this.field.type === 'number') {
+        this.ngModel = parseInt(this.field.default, 10);
+      }
+      else {
+        this.ngModel = this.field.default;
+      }
+    }
+
 
     if (this.field.type === 'array') {
       this.$scope.$watch(() => this.ngModel.length, () => {
diff --git a/src/app/core/form/form.ts b/src/app/core/form/form.ts
index 1c01e31..273e9b1 100644
--- a/src/app/core/form/form.ts
+++ b/src/app/core/form/form.ts
@@ -41,6 +41,7 @@
   hint?: string;
   validators: IXosFormInputValidator;
   options?: IXosFormInputOptions[];
+  default?: any | null;
 }
 
 export interface IXosFormCfg {
diff --git a/src/app/core/services/helpers/config.helpers.spec.ts b/src/app/core/services/helpers/config.helpers.spec.ts
index d060001..5b2ae07 100644
--- a/src/app/core/services/helpers/config.helpers.spec.ts
+++ b/src/app/core/services/helpers/config.helpers.spec.ts
@@ -198,25 +198,22 @@
   describe('the modelFieldToInputConfig', () => {
     it('should return an array of inputs', () => {
       const inputs: IXosFormInput[] = service.modelFieldToInputCfg(model.fields);
-      expect(inputs[0].name).toBe('id');
-      expect(inputs[0].type).toBe('number');
-      expect(inputs[0].label).toBe('Id');
 
-      expect(inputs[1].name).toBe('name');
+      expect(inputs[0].name).toBe('name');
+      expect(inputs[0].type).toBe('string');
+      expect(inputs[0].label).toBe('Name');
+      expect(inputs[0].validators.required).toBe(true);
+
+      expect(inputs[1].name).toBe('something');
       expect(inputs[1].type).toBe('string');
-      expect(inputs[1].label).toBe('Name');
-      expect(inputs[1].validators.required).toBe(true);
+      expect(inputs[1].label).toBe('Something');
+      expect(inputs[1].validators.maxlength).toBe(30);
 
-      expect(inputs[2].name).toBe('something');
-      expect(inputs[2].type).toBe('string');
-      expect(inputs[2].label).toBe('Something');
-      expect(inputs[2].validators.maxlength).toBe(30);
-
-      expect(inputs[3].name).toBe('else');
-      expect(inputs[3].type).toBe('number');
-      expect(inputs[3].label).toBe('Else');
-      expect(inputs[3].validators.min).toBe(20);
-      expect(inputs[3].validators.max).toBe(40);
+      expect(inputs[2].name).toBe('else');
+      expect(inputs[2].type).toBe('number');
+      expect(inputs[2].label).toBe('Else');
+      expect(inputs[2].validators.min).toBe(20);
+      expect(inputs[2].validators.max).toBe(40);
     });
   });
 
@@ -229,7 +226,8 @@
       expect(config.actions[0].class).toBe('success');
       expect(config.actions[0].icon).toBe('ok');
       expect(config.actions[0].cb).toBeDefined();
-      expect(config.inputs.length).toBe(4);
+      // NOTE 'id' and 'updated' are hidden fields
+      expect(config.inputs.length).toBe(3);
     });
   });
 
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index b49b27c..ed3f0c0 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -2,7 +2,7 @@
 import * as pluralize from 'pluralize';
 import {IXosTableColumn, IXosTableCfg} from '../../table/table';
 import {IXosModeldef} from '../../../datasources/rest/modeldefs.rest';
-import {IXosFormCfg, IXosFormInput, IXosFormInputValidator} from '../../form/form';
+import {IXosFormCfg, IXosFormInput, IXosFormInputValidator, IXosFormInputOptions} from '../../form/form';
 import {IXosModelStoreService} from '../../../datasources/stores/model.store';
 import {IXosState} from '../runtime-states';
 
@@ -21,6 +21,8 @@
     model: string;
     type: string;
   };
+  options?: IXosFormInputOptions[];
+  default?: any | null;
 }
 
 export interface IXosConfigHelpersService {
@@ -59,9 +61,16 @@
     'validators',
     'password',
     'backend_need_delete',
-    'backend_need_reap'
+    'backend_need_reap',
+    'leaf_model_name'
   ];
 
+  public form_excluded_fields = this.excluded_fields.concat([
+    'id',
+    'policy_status',
+    'backend_status',
+  ]);
+
   constructor(
     private $state: ng.ui.IStateService,
     private toastr: ng.toastr.IToastrService,
@@ -152,7 +161,7 @@
       }
 
       // if the field identify a relation, create a link
-      if (f.relation && f.relation.type === 'many_to_one') {
+      if (f.relation && f.relation.type === 'manytoone') {
         col.type = 'custom';
         col.formatter = item => {
           this.populateRelated(item, item[f.name], f);
@@ -163,19 +172,19 @@
         };
       }
 
-      if (f.name === 'backend_status') {
+      if (f.name === 'backend_status' || f.name === 'policy_status') {
         col.type = 'icon';
         col.hover = (item) => {
           return item[f.name];
         };
         col.formatter = (item) => {
-          if (item.backend_status.indexOf('1') > -1) {
+          if (item[f.name].indexOf('1') > -1) {
             return 'check';
           }
-          if (item.backend_status.indexOf('2') > -1) {
+          if (item[f.name].indexOf('2') > -1) {
             return 'exclamation-circle';
           }
-          if (item.backend_status.indexOf('0') > -1) {
+          if (item[f.name].indexOf('0') > -1) {
             return 'clock-o';
           }
         };
@@ -217,22 +226,30 @@
         label: this.toLabel(f.name),
         type: f.type,
         validators: this.formatValidators(f.validators),
-        hint: f.hint
+        hint: f.hint,
+        default: f.default || null
       };
+
+      // NOTE populate drop-downs based on relation
       if (f.relation) {
         input.type = 'select';
         this.populateSelectField(f, input);
-        return input;
+      }
+      // NOTE if static options are defined in modeldefs
+      // the f.options field is already populated,
+      // we just need to move it to the input
+      else if (f.options && f.options.length > 0) {
+        input.options = f.options;
       }
       return input;
     })
-      .filter(f => this.excluded_fields.indexOf(f.name) === -1);
+      .filter(f => this.form_excluded_fields.indexOf(f.name) === -1);
   }
 
   public modelToFormCfg(model: IXosModeldef): IXosFormCfg {
     const formCfg: IXosFormCfg = {
       formName: `${model.name}Form`,
-      exclude: ['backend_status', 'creator', 'id'],
+      exclude: this.form_excluded_fields,
       actions: [{
         label: 'Save',
         class: 'success',