From 9ed4acd4ffeb54ff005f048950523e76b6f2adea Mon Sep 17 00:00:00 2001 From: Tyr Johanson Date: Wed, 27 Jul 2016 12:57:26 -0600 Subject: [PATCH] Schema Form Developer Panel A developer panel that allows you to edit schema forms in real-time, with multiple examples. Also, you can view that same form in a standard Horizon modal to preview what the form will look like. Based on http://schemaform.io/examples/bootstrap-example.html Also fixes some bugs in the schema-form implementation: - Arrays cleaned up and fixed - Tab arrays cleaned up - Improved modal form to use schema.title if available Co-Authored-By: Rob Cresswell Change-Id: Ia75a18d4c0c064ae618ee923cd6d602b1ef6e66e --- .../contenteditable.directive.js | 59 ++++++ .../contenteditable.directive.spec.js | 67 +++++++ .../contenteditable/contenteditable.module.js | 25 +++ .../framework/widgets/form/fields/array.html | 4 +- .../widgets/form/fields/fieldset.html | 2 +- .../widgets/form/fields/tabarray.html | 12 +- .../widgets/form/modal-form.controller.js | 2 +- .../widgets/form/modal-form.service.js | 1 + .../framework/widgets/widgets.module.js | 1 + .../developer/enabled/_9040_form_builder.py | 19 ++ .../developer/form_builder/__init__.py | 0 .../contrib/developer/form_builder/panel.py | 22 ++ .../contrib/developer/form_builder/urls.py | 20 ++ .../contrib/developer/form_builder/views.py | 19 ++ .../dashboard/developer/developer.module.js | 5 +- .../static/dashboard/developer/developer.scss | 3 +- .../addons-required-feedback.json | 60 ++++++ .../form-builder/example-forms/array.json | 31 +++ .../form-builder/example-forms/buttons.json | 21 ++ .../example-forms/confirmation-dialog.json | 16 ++ .../example-forms/example-help.html | 3 + .../radios-checkboxes-select.json | 143 +++++++++++++ .../example-forms/sections-fieldsets.json | 53 +++++ .../form-builder/example-forms/tabarray.json | 30 +++ .../form-builder/example-forms/tabs.json | 43 ++++ .../example-forms/text-inputs.json | 29 +++ .../form-builder/form-builder.controller.js | 189 ++++++++++++++++++ .../form-builder/form-builder.directive.js | 44 ++++ .../developer/form-builder/form-builder.html | 58 ++++++ .../form-builder/form-builder.module.js | 46 +++++ .../developer/form-builder/form-builder.scss | 9 + .../form-builder/form-config-modal.html | 3 + .../developer/form-builder/index.html | 1 + .../dashboard/scss/components/_code.scss | 7 + .../static/dashboard/scss/horizon.scss | 1 + 35 files changed, 1035 insertions(+), 13 deletions(-) create mode 100644 horizon/static/framework/widgets/contenteditable/contenteditable.directive.js create mode 100644 horizon/static/framework/widgets/contenteditable/contenteditable.directive.spec.js create mode 100644 horizon/static/framework/widgets/contenteditable/contenteditable.module.js create mode 100644 openstack_dashboard/contrib/developer/enabled/_9040_form_builder.py create mode 100644 openstack_dashboard/contrib/developer/form_builder/__init__.py create mode 100644 openstack_dashboard/contrib/developer/form_builder/panel.py create mode 100644 openstack_dashboard/contrib/developer/form_builder/urls.py create mode 100644 openstack_dashboard/contrib/developer/form_builder/views.py create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/addons-required-feedback.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/array.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/buttons.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/confirmation-dialog.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/example-help.html create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/radios-checkboxes-select.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/sections-fieldsets.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/tabarray.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/tabs.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/example-forms/text-inputs.json create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-builder.controller.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-builder.directive.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-builder.html create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-builder.module.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-builder.scss create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/form-config-modal.html create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/form-builder/index.html create mode 100644 openstack_dashboard/static/dashboard/scss/components/_code.scss diff --git a/horizon/static/framework/widgets/contenteditable/contenteditable.directive.js b/horizon/static/framework/widgets/contenteditable/contenteditable.directive.js new file mode 100644 index 0000000000..401a3fbcc0 --- /dev/null +++ b/horizon/static/framework/widgets/contenteditable/contenteditable.directive.js @@ -0,0 +1,59 @@ +/** + * (c) Copyright 2016 Cisco Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use self file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +(function() { + 'use strict'; + + /** + * @ngdoc directive + * @name horizon.framework.widgets.contenteditable + * @description + * Allows the use of contenteditable with ng-model. Altered from + * https://docs.angularjs.org/api/ng/type/ngModel.NgModelController + */ + + angular + .module('horizon.framework.widgets.contenteditable') + .directive('contenteditable', contenteditable); + + function contenteditable() { + var directive = { + restrict: 'A', + require: '?ngModel', // get a hold of NgModelController + link: link + }; + return directive; + + function link(scope, element, attrs, ngModel) { + if (!ngModel) { return; } // do nothing if no ng-model + + // Specify how UI should be updated + ngModel.$render = function() { + element.html(ngModel.$viewValue || ''); + }; + + // Listen for change events to enable binding + element.on('blur keyup change', function() { + scope.$evalAsync(read); + }); + read(); + + function read() { + ngModel.$setViewValue(element.html()); + } + } + } +})(); diff --git a/horizon/static/framework/widgets/contenteditable/contenteditable.directive.spec.js b/horizon/static/framework/widgets/contenteditable/contenteditable.directive.spec.js new file mode 100644 index 0000000000..275af4db41 --- /dev/null +++ b/horizon/static/framework/widgets/contenteditable/contenteditable.directive.spec.js @@ -0,0 +1,67 @@ +/** + * Copyright 2016 Cisco Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function() { + 'use strict'; + + describe('contenteditable directive', function() { + var $compile, $scope; + + beforeEach(module('horizon.framework.widgets')); + beforeEach(module('horizon.framework.widgets.contenteditable')); + beforeEach(inject(function ($injector) { + $compile = $injector.get('$compile'); + $scope = $injector.get('$rootScope').$new(); + $scope.testData = ''; + })); + + describe('using a model', function() { + var element; + beforeEach(function before() { + element = $compile('
')($scope);
+        $scope.$digest();
+      });
+
+      it('should update the model when content is edited', function () {
+        element.triggerHandler('focus');
+        element.html('foo');
+        $scope.$digest();
+        element.triggerHandler('blur');
+        expect($scope.testData).toBe('foo');
+      });
+
+      it('should update the view when model is changed', function () {
+        element.triggerHandler('focus');
+        $scope.testData = 'spam';
+        $scope.$digest();
+
+        expect(element.html()).toBe('spam');
+      });
+    });
+
+    it('should not do anything without an accompanying ng-model', function() {
+      var element = $compile('
')($scope);
+      $scope.$digest();
+
+      element.triggerHandler('focus');
+      element.html('bar');
+      $scope.$digest();
+      element.triggerHandler('blur');
+
+      expect($scope.testData).toBe('');
+    });
+  });
+})();
diff --git a/horizon/static/framework/widgets/contenteditable/contenteditable.module.js b/horizon/static/framework/widgets/contenteditable/contenteditable.module.js
new file mode 100644
index 0000000000..ea92536b84
--- /dev/null
+++ b/horizon/static/framework/widgets/contenteditable/contenteditable.module.js
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 Cisco Systems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function() {
+  'use strict';
+
+  /**
+   * @ngdoc overview
+   * @name horizon.framework.widgets.contenteditable
+   */
+  angular
+    .module('horizon.framework.widgets.contenteditable', []);
+})();
diff --git a/horizon/static/framework/widgets/form/fields/array.html b/horizon/static/framework/widgets/form/fields/array.html
index 0af7b93da3..9d0667ecf8 100644
--- a/horizon/static/framework/widgets/form/fields/array.html
+++ b/horizon/static/framework/widgets/form/fields/array.html
@@ -2,8 +2,8 @@
      sf-field-model="sf-new-array"
      sf-new-array>
   
-  
    -
  1. +
  2. diff --git a/horizon/static/framework/widgets/form/fields/fieldset.html b/horizon/static/framework/widgets/form/fields/fieldset.html index 5c46d8118f..471bc5ba78 100644 --- a/horizon/static/framework/widgets/form/fields/fieldset.html +++ b/horizon/static/framework/widgets/form/fields/fieldset.html @@ -1,4 +1,4 @@
    - {$:: form.title $} + {$:: form.title $}
    diff --git a/horizon/static/framework/widgets/form/fields/tabarray.html b/horizon/static/framework/widgets/form/fields/tabarray.html index 08f20f1bd6..fd65473301 100644 --- a/horizon/static/framework/widgets/form/fields/tabarray.html +++ b/horizon/static/framework/widgets/form/fields/tabarray.html @@ -2,10 +2,10 @@ ng-model="modelArray" schema-validate="form" sf-field-model="sf-new-array" sf-new-array - class="clearfix hz-tabarray schema-form-tabarray-{$form.tabType || 'left'$} {$form.htmlClass$}"> + class="clearfix hz-tabarray schema-form-tabarray-{$form.tabType || 'left'$} {::$form.htmlClass$}">
    -
    -
    +
    + class="btn {$:: form.style.remove || 'btn-danger' $} pull-right"> {$::form.remove || 'Remove'$} @@ -50,7 +50,7 @@
    -