You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2016/02/08 11:13:55 UTC

[2/4] ignite git commit: IGNITE-843 changed case of dir

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/field.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/field.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/field.directive.js
new file mode 100644
index 0000000..e02bebe
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/field.directive.js
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './field.jade!';
+import './field.css!';
+
+export default ['igniteFormField', [() => {
+    const controller = [function() {
+        const ctrl = this;
+
+        ctrl.type = ctrl.type || 'external';
+    }];
+
+    return {
+        restrict: 'E',
+        scope: {},
+        bindToController: {
+            for: '@',
+            label: '@',
+            type: '@'
+        },
+        template,
+        controller,
+        controllerAs: 'field',
+        replace: true,
+        transclude: true,
+        require: '^form'
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/field.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/field.jade b/modules/control-center-web/src/main/js/app/modules/form/field/field.jade
new file mode 100644
index 0000000..6d7c04a
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/field.jade
@@ -0,0 +1,26 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+div
+    div(ng-if='field.type == "external"')
+        label.col-xs-4.col-sm-4.col-md-4(
+            for='{{::field.for}}'
+            class='{{ field.required ? "required" : "" }}'
+        ) 
+            span(ng-if='field.label') {{::field.label}}:
+        .col-xs-8.col-sm-8.col-md-8(ng-transclude='')
+    div(ng-if='field.type == "internal"')
+        label.col-xs-12.col-sm-12.col-md-12(ng-transclude)       

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/form-control-feedback.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/form-control-feedback.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/form-control-feedback.directive.js
new file mode 100644
index 0000000..ba3e7fe
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/form-control-feedback.directive.js
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['formControlFeedback', [() => {
+    const link = ($scope, $element, $attrs, [form]) => {
+        const name = $scope.name;
+        const err = $attrs.igniteError;
+        const msg = $attrs.igniteErrorMessage;
+
+        if (name && err && msg) {
+            form.$errorMessages = form.$errorMessages || {};
+            form.$errorMessages[name] = form.$errorMessages[name] || {};
+            form.$errorMessages[name][err] = msg;
+        }
+    };
+
+    return {
+        restrict: 'C',
+        link,
+        require: ['^form']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/autofocus.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/autofocus.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/input/autofocus.directive.js
new file mode 100644
index 0000000..eeccc3f
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/autofocus.directive.js
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['igniteFormFieldInputAutofocus', [() => {
+    const link = (scope, el, attrs) => {
+        if (typeof attrs.igniteFormFieldInputAutofocus === 'undefined' || !attrs.igniteFormFieldInputAutofocus)
+            return;
+
+        el.focus();
+    };
+
+    return {
+        restrict: 'A',
+        link
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.directive.js
new file mode 100644
index 0000000..d259718
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.directive.js
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './checkbox.jade!';
+
+export default ['igniteFormFieldInputCheckbox', ['IgniteFormGUID', (guid) => {
+    const link = (scope, el, attrs, [form, label]) => {
+        const {id, name} = scope;
+        const field = form[name];
+
+        scope.field = field;
+        label.for = scope.id = id || guid();
+
+        label.type = 'internal';
+
+        form.$defaults = form.$defaults || {};
+        form.$defaults[name] = _.cloneDeep(scope.value);
+
+        const setAsDefault = () => {
+            if (!form.$pristine) return;
+
+            form.$defaults = form.$defaults || {};
+            form.$defaults[name] = _.cloneDeep(scope.value);
+        };
+
+        scope.$watch(() => form.$pristine, setAsDefault);
+        scope.$watch('value', setAsDefault);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            id: '@',
+            name: '@',
+            required: '=ngRequired',
+            disabled: '=ngDisabled',
+
+            value: '=ngModel'
+        },
+        link,
+        template,
+        replace: true,
+        transclude: true,
+        require: ['^form', '?^igniteFormField']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.jade b/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.jade
new file mode 100644
index 0000000..c3cd283
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/checkbox.jade
@@ -0,0 +1,28 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+.input-tip
+    input(
+        id='{{ id }}'
+        name='{{ name }}'
+        type='checkbox'
+
+        data-ng-model='value'
+        data-ng-required='required || false'
+        data-ng-disabled='disabled || false'
+    )
+
+    span(ng-transclude='')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.directive.js
new file mode 100644
index 0000000..9627965
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.directive.js
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './datalist.jade!';
+
+export default ['igniteFormFieldInputDatalist', ['IgniteFormGUID', (guid) => {
+    const link = (scope, $element, attrs, [form]) => {
+        const {id, name} = scope;
+
+        scope.id = id || guid();
+
+        form.$defaults = form.$defaults || {};
+        form.$defaults[name] = _.cloneDeep(scope.value);
+
+        const setAsDefault = () => {
+            if (!form.$pristine) return;
+
+            form.$defaults = form.$defaults || {};
+            form.$defaults[name] = _.cloneDeep(scope.value);
+        };
+
+        scope.$watch(() => form.$pristine, setAsDefault);
+        scope.$watch('value', setAsDefault);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            id: '@',
+            name: '@',
+            placeholder: '@',
+            disabled: '=ngDisabled',
+
+            options: '=',
+            value: '=ngModel'
+        },
+        link,
+        template,
+        replace: true,
+        transclude: true,
+        require: ['^form', '?^igniteFormField']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.jade b/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.jade
new file mode 100644
index 0000000..1002d03
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/datalist.jade
@@ -0,0 +1,33 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+.input-tip
+    input.form-control(
+        id='{{ id }}'
+        name='{{ name }}'
+        placeholder='{{ placeholder }}' 
+        data-min-length='1'
+
+        bs-typeahead
+        bs-options='item for item in options' 
+        retain-selection
+        container='body'
+
+        data-ng-model='value'
+        data-ng-disabled='disabled || false'
+    )
+
+    span(ng-transclude='')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/number.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/number.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/input/number.directive.js
new file mode 100644
index 0000000..b88425f
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/number.directive.js
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './number.jade!';
+
+export default ['igniteFormFieldInputNumber', ['IgniteFormGUID', (guid) => {
+    const link = (scope, el, attrs, [form, label]) => {
+        const {id, name} = scope;
+        const field = form[name];
+
+        scope.field = field;
+        label.for = scope.id = id || guid();
+
+        form.$defaults = form.$defaults || {};
+        form.$defaults[name] = _.cloneDeep(scope.value);
+
+        const setAsDefault = () => {
+            if (!form.$pristine) return;
+
+            form.$defaults = form.$defaults || {};
+            form.$defaults[name] = _.cloneDeep(scope.value);
+        };
+
+        scope.$watch(() => form.$pristine, setAsDefault);
+        scope.$watch('value', setAsDefault);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            id: '@',
+            name: '@',
+            placeholder: '@',
+            required: '=ngRequired',
+            disabled: '=ngDisabled',
+
+            min: '@',
+            max: '@',
+            value: '=ngModel'
+        },
+        link,
+        template,
+        replace: true,
+        transclude: true,
+        require: ['^form', '?^igniteFormField']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/number.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/number.jade b/modules/control-center-web/src/main/js/app/modules/form/field/input/number.jade
new file mode 100644
index 0000000..b032c46
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/number.jade
@@ -0,0 +1,44 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+mixin feedback(error, message)
+    i.fa.fa-exclamation-triangle.form-control-feedback(
+        ng-show='field.$error.#{error}'
+        bs-tooltip='"#{message}"'
+        ignite-error='#{error}'
+        ignite-error-message='#{message}'
+    )
+
+.input-tip
+    input.form-control(
+        id='{{ id }}'
+        name='{{ name }}'
+        placeholder='{{ placeholder }}'
+        type='number'
+        min='{{ min || 0 }}'
+        max='{{ max || Number.MAX_VALUE }}'
+
+        data-ng-model='value'
+        data-ng-required='required || false'
+        data-ng-disabled='disabled || false'
+        data-ng-model-options='{debounce: 150}'
+    )
+
+    +feedback('min', 'Value is less than allowable minimum')
+    +feedback('max', 'Value is more than allowable maximum')
+    +feedback('number', 'Invalid value. Only numbers allowed')
+
+    span(ng-transclude='')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.css
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.css b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.css
new file mode 100644
index 0000000..9efdb2c
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.css
@@ -0,0 +1,24 @@
+label .input-tip {
+	position: initial;
+}
+
+.input-tip .fa-floppy-o {
+	position: absolute;
+    top: 0;
+    right: 0;
+    z-index: 2;
+
+    width: 34px;
+    height: 34px;
+
+    text-align: center;
+
+    display: inline-block;
+    line-height: 28px;
+    pointer-events: initial;
+}
+
+.input-tip .form-control-feedback {
+    height: auto;
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.directive.js
new file mode 100644
index 0000000..1cb8e92
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.directive.js
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './text.jade!';
+import './text.css!';
+
+export default ['igniteFormFieldInputText', ['IgniteFormGUID', (guid) => {
+    const link = (scope, el, attrs, [ngModel, form, label]) => {
+        const {id, name} = scope;
+
+        label.for = scope.id = id || guid();
+
+        scope.label = label;
+        scope.ngModel = ngModel;
+        scope.$watch('required', (required) => {
+            label.required = required || false;
+        });
+
+        form.$defaults = form.$defaults || {};
+        form.$defaults[name] = _.cloneDeep(scope.value);
+
+        const setAsDefault = () => {
+            if (!form.$pristine) return;
+
+            form.$defaults = form.$defaults || {};
+            form.$defaults[name] = _.cloneDeep(scope.value);
+        };
+
+        scope.$watch(() => form.$pristine, setAsDefault);
+        scope.$watch('value', setAsDefault);
+
+        scope.ngChange = function() {
+            ngModel.$setViewValue(scope.value);
+
+            if (JSON.stringify(scope.value) !== JSON.stringify(form.$defaults[name]))
+                ngModel.$setDirty();
+            else
+                ngModel.$setPristine();
+
+            if (ngModel.$valid)
+                el.find('input').addClass('ng-valid').removeClass('ng-invalid');
+            else
+                el.find('input').removeClass('ng-valid').addClass('ng-invalid');
+        };
+
+        ngModel.$render = function() {
+            scope.value = ngModel.$modelValue;
+        };
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            id: '@',
+            name: '@',
+            placeholder: '@',
+            required: '=ngRequired',
+            disabled: '=ngDisabled',
+
+            ngBlur: '&',
+
+            autofocus: '=igniteFormFieldInputAutofocus'
+        },
+        link,
+        template,
+        replace: true,
+        transclude: true,
+        require: ['ngModel', '^form', '?^igniteFormField']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/input/text.jade b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.jade
new file mode 100644
index 0000000..28298ab
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/input/text.jade
@@ -0,0 +1,38 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+.input-tip
+    input.form-control(
+        id='{{ id }}'
+        placeholder='{{ placeholder }}' 
+        type='text' 
+
+        data-ng-model='value'
+        data-ng-blur='ngBlur()'
+        data-ng-change='ngChange()'
+        data-ng-required='required || false'
+        data-ng-disabled='disabled || false'
+        data-ng-model-options='{debounce: 150}'
+
+        data-ignite-form-field-input-autofocus='autofocus || false'
+    )
+
+    i.fa.fa-exclamation-triangle.form-control-feedback(
+        ng-if='!ngModel.$pristine && ngModel.$error.required'
+        bs-tooltip='"{{ label.name }} could not be empty!"'
+    )
+
+    span(ng-transclude='')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/label.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/label.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/label.directive.js
new file mode 100644
index 0000000..d22df2c
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/label.directive.js
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['igniteFormFieldLabel', [() => {
+    return {
+        restrict: 'E',
+        compile() {
+            return {
+                post($scope, $element, $attrs, [form, field], $transclude) {
+                    $transclude($scope, function(clone) {
+                        const text = clone.text();
+
+                        if (/(.*):$/.test(text))
+                            field.name = /(.*):$/.exec(text)[1];
+
+                        const $label = $element.parent().parent().find('label');
+
+                        $label.append(clone);
+                    });
+                }
+            };
+        },
+        replace: true,
+        transclude: true,
+        require: ['^form', '?^igniteFormField']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/tooltip.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/tooltip.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/tooltip.directive.js
new file mode 100644
index 0000000..78aa8fd
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/tooltip.directive.js
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+const template = `<i class='tipField fa fa-question-circle'></i>`;
+
+export default ['igniteFormFieldTooltip', ['$tooltip', ($tooltip) => {
+    const link = ($scope, $element, $attrs, $ctrls, $transclude) => {
+        const content = Array.prototype.slice.apply($transclude($scope))
+            .reduce((html, el) => html += el.outerHTML, '');
+
+        $tooltip($element, { title: content });
+
+        // TODO cleanup css styles.
+        if ($element.hasClass('tipLabel'))
+            $element.removeClass('tipField');
+
+        if ($element.parent('label').length)
+            $element.addClass('tipLabel').removeClass('tipField');
+    };
+
+    return {
+        restrict: 'E',
+        scope: {},
+        template,
+        link,
+        replace: true,
+        transclude: true,
+        require: '^form'
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/field/up.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/field/up.directive.js b/modules/control-center-web/src/main/js/app/modules/form/field/up.directive.js
new file mode 100644
index 0000000..d591eac
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/field/up.directive.js
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+
+
+const template = `<i class='tipField fa fa-arrow-up ng-scope' ng-click='up()'></i>`;
+
+export default ['igniteFormFieldUp', ['$tooltip', ($tooltip) => {
+    const link = (scope, $element) => {
+        $tooltip($element, { title: 'Move item up' });
+
+        scope.up = () => {
+            const idx = scope.models.indexOf(scope.model);
+
+            scope.models.splice(idx, 1);
+            scope.models.splice(idx - 1, 0, scope.model);
+        };
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            model: '=ngModel',
+            models: '=models'
+        },
+        template,
+        link,
+        replace: true,
+        transclude: true,
+        require: '^form'
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/form.module.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/form.module.js b/modules/control-center-web/src/main/js/app/modules/form/form.module.js
new file mode 100644
index 0000000..aac831d
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/form.module.js
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import angular from 'angular';
+
+// Panel.
+import igniteFormPanel from './panel/panel.directive';
+import igniteFormPanelChevron from './panel/chevron.directive';
+import igniteFormRevert from './panel/revert.directive';
+
+// Field.
+import igniteFormField from './field/field.directive';
+import igniteFormFieldLabel from './field/label.directive';
+import igniteFormFieldTooltip from './field/tooltip.directive';
+import igniteFormFieldDropdown from './field/dropdown.directive';
+import igniteFormFieldInputNumber from './field/input/number.directive';
+import igniteFormFieldInputText from './field/input/text.directive';
+import igniteFormFieldInputCheckbox from './field/input/checkbox.directive';
+import igniteFormFieldInputDatalist from './field/input/datalist.directive';
+
+// Group.
+import igniteFormGroup from './group/group.directive';
+import igniteFormGroupAdd from './group/add.directive';
+import igniteFormGroupTooltip from './group/tooltip.directive';
+
+// Validators.
+import javaKeywords from './validator/java-keywords.directive';
+import javaPackageSpecified from './validator/java-package-specified.directive';
+import javaBuiltInClass from './validator/java-built-in-class.directive';
+import javaIdentifier from './validator/java-identifier.directive';
+import javaPackageName from './validator/java-package-name.directive';
+import unique from './validator/unique.directive';
+
+// Helpers.
+import igniteFormFieldInputAutofocus from './field/input/autofocus.directive';
+import igniteFormFieldUp from './field/up.directive';
+import igniteFormFieldDown from './field/down.directive';
+import igniteFormControlFeedback from './field/form-control-feedback.directive';
+
+angular
+.module('ignite-console.Form', [
+
+])
+// Panel.
+.directive(...igniteFormPanel)
+.directive(...igniteFormPanelChevron)
+.directive(...igniteFormRevert)
+// Field.
+.directive(...igniteFormField)
+.directive(...igniteFormFieldLabel)
+.directive(...igniteFormFieldTooltip)
+.directive(...igniteFormFieldDropdown)
+.directive(...igniteFormFieldInputNumber)
+.directive(...igniteFormFieldInputText)
+.directive(...igniteFormFieldInputCheckbox)
+.directive(...igniteFormFieldInputDatalist)
+// Group.
+.directive(...igniteFormGroup)
+.directive(...igniteFormGroupAdd)
+.directive(...igniteFormGroupTooltip)
+// Validators.
+.directive(...javaKeywords)
+.directive(...javaPackageSpecified)
+.directive(...javaBuiltInClass)
+.directive(...javaIdentifier)
+.directive(...javaPackageName)
+.directive(...unique)
+// Helpers.
+.directive(...igniteFormFieldInputAutofocus)
+.directive(...igniteFormFieldUp)
+.directive(...igniteFormFieldDown)
+.directive(...igniteFormControlFeedback)
+// Generator of globally unique identifier.
+.factory('IgniteFormGUID', [() => {
+    let guid = 0;
+
+    return () => `form-field-${guid++}`;
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/add.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/add.directive.js b/modules/control-center-web/src/main/js/app/modules/form/group/add.directive.js
new file mode 100644
index 0000000..6d79026
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/add.directive.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+const template = `<i class='group-legend-btn fa fa-plus'></i>`;
+
+export default ['igniteFormGroupAdd', ['$tooltip', ($tooltip) => {
+    const link = ($scope, $element, $attrs, $ctrls, $transclude) => {
+        const content = Array.prototype.slice
+        .apply($transclude($scope))
+        .reduce((html, el) => html += el.outerHTML, '');
+
+        $tooltip($element, { title: content });
+
+        $element.closest('.group').find('.group-legend').append($element);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {},
+        template,
+        link,
+        replace: true,
+        transclude: true,
+        require: ['^form', '^igniteFormGroup']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/group.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/group.directive.js b/modules/control-center-web/src/main/js/app/modules/form/group/group.directive.js
new file mode 100644
index 0000000..db03503
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/group.directive.js
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './group.jade!';
+
+export default ['igniteFormGroup', [() => {
+    const controller = [function() { }];
+
+    const link = (scope, el, attrs, [ngModelCtrl, ownFormCtrl, parentFormCtrl]) => {
+        const name = attrs.ngForm;
+        ngModelCtrl.$name = name;
+
+        parentFormCtrl.$addControl(ngModelCtrl);
+        parentFormCtrl.$removeControl(ownFormCtrl);
+
+        scope.value = scope.value || [];
+        parentFormCtrl.$defaults = parentFormCtrl.$defaults || {};
+        parentFormCtrl.$defaults[name] = _.cloneDeep(scope.value);
+
+        const setAsDefault = () => {
+            if (!parentFormCtrl.$pristine)
+                return;
+
+            scope.value = scope.value || [];
+            parentFormCtrl.$defaults = parentFormCtrl.$defaults || {};
+            parentFormCtrl.$defaults[name] = _.cloneDeep(scope.value);
+        };
+
+        const setAsDirty = () => {
+            if (JSON.stringify(scope.value) !== JSON.stringify(parentFormCtrl.$defaults[name]))
+                ngModelCtrl.$setDirty();
+            else
+                ngModelCtrl.$setPristine();
+        };
+
+        scope.$watch(() => parentFormCtrl.$pristine, setAsDefault);
+
+        scope.$watch('value', setAsDefault);
+        scope.$watch('value', setAsDirty, true);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            value: '=ngModel'
+        },
+        bindToController: {
+            label: '@'
+        },
+        link,
+        template,
+        controller,
+        controllerAs: 'group',
+        replace: true,
+        transclude: true,
+        require: ['ngModel', '?form', '^^form']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/group.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/group.jade b/modules/control-center-web/src/main/js/app/modules/form/group/group.jade
new file mode 100644
index 0000000..ba3a8f2
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/group.jade
@@ -0,0 +1,21 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+.group-section
+    .group
+        .group-legend
+            label {{::group.label}}
+        div(ng-transclude='')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/table.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/table.directive.js b/modules/control-center-web/src/main/js/app/modules/form/group/table.directive.js
new file mode 100644
index 0000000..520f8c2
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/table.directive.js
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import template from './table.jade!';
+
+export default ['igniteFormGroupTable', [() => {
+    return {
+        restrict: 'E',
+        scope: {},
+        template,
+        replace: true,
+        transclude: true,
+        require: ['^form', '^igniteFormGroup']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/table.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/table.jade b/modules/control-center-web/src/main/js/app/modules/form/group/table.jade
new file mode 100644
index 0000000..6f9486d
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/table.jade
@@ -0,0 +1,17 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+div
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/group/tooltip.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/group/tooltip.directive.js b/modules/control-center-web/src/main/js/app/modules/form/group/tooltip.directive.js
new file mode 100644
index 0000000..5af8fb1
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/group/tooltip.directive.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+const template = `<i class='group-legend-btn fa fa-question-circle'></i>`;
+
+export default ['igniteFormGroupTooltip', ['$tooltip', ($tooltip) => {
+    const link = ($scope, $element, $attrs, $ctrls, $transclude) => {
+        const content = Array.prototype.slice
+        .apply($transclude($scope))
+        .reduce((html, el) => html += el.outerHTML, '');
+
+        $tooltip($element, { title: content });
+
+        $element.closest('.group').find('.group-legend').append($element);
+    };
+
+    return {
+        restrict: 'E',
+        scope: {},
+        template,
+        link,
+        replace: true,
+        transclude: true,
+        require: ['^form', '^igniteFormGroup']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/panel/chevron.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/panel/chevron.directive.js b/modules/control-center-web/src/main/js/app/modules/form/panel/chevron.directive.js
new file mode 100644
index 0000000..9f7e1d0
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/panel/chevron.directive.js
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+const template = `<i class='fa' ng-class='isOpen ? "fa-chevron-circle-down" : "fa-chevron-circle-right"'></i>`;
+
+export default ['igniteFormPanelChevron', [() => {
+    const controller = [() => {}];
+
+    const link = ($scope, $element, $attrs, [bsCollapseCtrl]) => {
+        const $target = $element.parent().parent().find('.panel-collapse');
+
+        bsCollapseCtrl.$viewChangeListeners.push(function() {
+            const index = bsCollapseCtrl.$targets.reduce((acc, el, i) => {
+                if (el[0] === $target[0])
+                    acc.push(i);
+
+                return acc;
+            }, [])[0];
+
+            $scope.isOpen = false;
+
+            const active = bsCollapseCtrl.$activeIndexes();
+
+            if ((active instanceof Array) && active.indexOf(index) !== -1 || active === index)
+                $scope.isOpen = true;
+        });
+    };
+
+    return {
+        restrict: 'E',
+        scope: {},
+        link,
+        template,
+        controller,
+        replace: true,
+        transclude: true,
+        require: ['^bsCollapse']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/panel/panel.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/panel/panel.directive.js b/modules/control-center-web/src/main/js/app/modules/form/panel/panel.directive.js
new file mode 100644
index 0000000..b8e7c25
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/panel/panel.directive.js
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['form', [() => {
+    const link = (scope, $element, $attrs, [form]) => {
+        const $form = $element.parent().closest('form');
+
+        scope.$watch(() => {
+            return $form.hasClass('ng-pristine');
+        }, (value) => {
+            if (!value)
+                return;
+
+            form.$setPristine();
+        });
+    };
+
+    return {
+        restrict: 'E',
+        link,
+        require: ['^form']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/panel/revert.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/panel/revert.directive.js b/modules/control-center-web/src/main/js/app/modules/form/panel/revert.directive.js
new file mode 100644
index 0000000..874b466
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/panel/revert.directive.js
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+const template = `<i ng-show='form.$dirty' class='fa fa-undo pull-right' ng-click='revert($event)'></i>`;
+
+export default ['igniteFormRevert', ['$tooltip', ($tooltip) => {
+    const link = (scope, $element, $attrs, [form]) => {
+        $tooltip($element, { title: 'Undo unsaved changes' });
+
+        scope.form = form;
+
+        scope.revert = (e) => {
+            e.stopPropagation();
+
+            for (const name in form.$defaults) {
+                if ({}.hasOwnProperty.call(form.$defaults, name) && form[name]) {
+                    form[name].$setViewValue(form.$defaults[name]);
+                    form[name].$setPristine();
+                    form[name].$render();
+                }
+            }
+
+            form.$setPristine();
+        };
+    };
+
+    return {
+        restrict: 'E',
+        scope: {
+            model: '=ngModel',
+            models: '=models'
+        },
+        template,
+        link,
+        replace: true,
+        require: ['^form']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/java-built-in-class.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/java-built-in-class.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/java-built-in-class.directive.js
new file mode 100644
index 0000000..caa268d
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/java-built-in-class.directive.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['javaBuiltInClass', ['JavaTypes', (JavaTypes) => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.javaBuiltInClass === 'undefined' || !attrs.javaBuiltInClass)
+            return;
+
+        ngModel.$validators.javaBuiltInClass = JavaTypes.nonBuiltInClass;
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/java-identifier.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/java-identifier.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/java-identifier.directive.js
new file mode 100644
index 0000000..81a48a3
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/java-identifier.directive.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['javaIdentifier', ['JavaTypes', (JavaTypes) => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.javaIdentifier === 'undefined' || !attrs.javaIdentifier)
+            return;
+
+        ngModel.$validators.javaIdentifier = JavaTypes.validIdentifier;
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/java-keywords.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/java-keywords.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/java-keywords.directive.js
new file mode 100644
index 0000000..8faae6d
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/java-keywords.directive.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['javaKeywords', ['JavaTypes', (JavaTypes) => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.javaKeywords === 'undefined' || !attrs.javaKeywords)
+            return;
+
+        ngModel.$validators.javaKeywords = (value) => {
+            if (value) {
+                for (const item of value.split('.')) {
+                    if (JavaTypes.isKeywords(item))
+                        return false;
+                }
+            }
+
+            return true;
+        };
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-name.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-name.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-name.directive.js
new file mode 100644
index 0000000..173e118
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-name.directive.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['javaPackageName', ['JavaTypes', (JavaTypes) => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.javaPackageName === 'undefined' || !attrs.javaPackageName)
+            return;
+
+        ngModel.$validators.javaPackageName = JavaTypes.validPackage;
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-specified.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-specified.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-specified.directive.js
new file mode 100644
index 0000000..9ba43f3
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/java-package-specified.directive.js
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['javaPackageSpecified', [() => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.javaPackageSpecified === 'undefined' || !attrs.javaPackageSpecified)
+            return;
+
+        ngModel.$validators.javaPackageSpecified = (value) => {
+            return !value || !(value.split('.').length < 2);
+        };
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/a84f6b6a/modules/control-center-web/src/main/js/app/modules/form/validator/unique.directive.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app/modules/form/validator/unique.directive.js b/modules/control-center-web/src/main/js/app/modules/form/validator/unique.directive.js
new file mode 100644
index 0000000..905a595
--- /dev/null
+++ b/modules/control-center-web/src/main/js/app/modules/form/validator/unique.directive.js
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+export default ['igniteUnique', ['$parse', ($parse) => {
+    const link = (scope, el, attrs, [ngModel]) => {
+        if (typeof attrs.igniteUnique === 'undefined' || !attrs.igniteUnique)
+            return;
+
+        ngModel.$validators.igniteUnique = (value) => {
+            const arr = $parse(attrs.igniteUnique)(scope);
+
+            // Return true in case if array not exist, array empty.
+            if (!arr || !arr.length)
+                return true;
+
+            const name = attrs.name;
+            const idx = arr.indexOf(value);
+
+            // In case of new element check all items.
+            if (name === 'new')
+                return idx < 0;
+
+            // Check for $index in case of editing in-place.
+            return (_.isNumber(scope.$index) && (idx < 0 || scope.$index === idx));
+        };
+    };
+
+    return {
+        restrict: 'A',
+        link,
+        require: ['ngModel']
+    };
+}]];