IGNITE-8200 Web Console: Override clonedCluster in cluster-edit-form if caches
or models have changed.
This improves interop with "import from DB" feature, which might update
caches/models of cluster currently opened for editing.
The import dialog works as a separate state, so the form change detection
mechanism ensures that any changes to the original
cluster are safe and won't interfere with changes made by user in cluster
edit form.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/77316692
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/77316692
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/77316692
Branch: refs/heads/ignite-7708
Commit: 77316692f14d083138d7515affd2d3f225b709e0
Parents: 3cebf91
Author: Ilya Borisov <[email protected]>
Authored: Tue Apr 17 17:15:57 2018 +0700
Committer: Alexey Kuznetsov <[email protected]>
Committed: Tue Apr 17 17:15:57 2018 +0700
----------------------------------------------------------------------
.../components/cluster-edit-form/controller.js | 24 +++++-
.../cluster-edit-form/controller.spec.js | 81 ++++++++++++++++++++
2 files changed, 102 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/77316692/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js
----------------------------------------------------------------------
diff --git
a/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js
b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js
index 35b43e0..0207729 100644
---
a/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js
+++
b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js
@@ -17,6 +17,7 @@
import cloneDeep from 'lodash/cloneDeep';
import get from 'lodash/get';
+import isEqual from 'lodash/isEqual';
import _ from 'lodash';
export default class ClusterEditFormController {
@@ -29,9 +30,11 @@ export default class ClusterEditFormController {
constructor(IgniteLegacyUtils, IgniteEventGroups, IgniteConfirm,
IgniteVersion, $scope, Clusters, IgniteFormUtils) {
Object.assign(this, {IgniteLegacyUtils, IgniteEventGroups,
IgniteConfirm, IgniteVersion, $scope, Clusters, IgniteFormUtils});
}
+
$onDestroy() {
this.subscription.unsubscribe();
}
+
$onInit() {
this.available = this.IgniteVersion.available.bind(this.IgniteVersion);
@@ -87,10 +90,9 @@ export default class ClusterEditFormController {
this.$scope.ui = this.IgniteFormUtils.formUI();
this.$scope.ui.loadedPanels = ['checkpoint', 'serviceConfiguration',
'odbcConfiguration'];
}
+
$onChanges(changes) {
- if (
- 'cluster' in changes && get(this.clonedCluster, '_id') !==
get(this.cluster, '_id')
- ) {
+ if ('cluster' in changes && this.shouldOverwriteValue(this.cluster,
this.clonedCluster)) {
this.clonedCluster = cloneDeep(changes.cluster.currentValue);
if (this.$scope.ui && this.$scope.ui.inputForm) {
this.$scope.ui.inputForm.$setPristine();
@@ -100,14 +102,30 @@ export default class ClusterEditFormController {
if ('caches' in changes)
this.cachesMenu = (changes.caches.currentValue || []).map((c) =>
({label: c.name, value: c._id}));
}
+
+ /**
+ * The form should accept incoming cluster value if:
+ * 1. It has different _id ("new" to real id).
+ * 2. Different caches or models (imported from DB).
+ * @param {Object} a Incoming value.
+ * @param {Object} b Current value.
+ */
+ shouldOverwriteValue(a, b) {
+ return get(a, '_id') !== get(b, '_id') ||
+ !isEqual(get(a, 'caches'), get(b, 'caches')) ||
+ !isEqual(get(a, 'models'), get(b, 'models'));
+ }
+
getValuesToCompare() {
return [this.cluster, this.clonedCluster].map(this.Clusters.normalize);
}
+
save() {
if (this.$scope.ui.inputForm.$invalid)
return
this.IgniteFormUtils.triggerValidation(this.$scope.ui.inputForm, this.$scope);
this.onSave({$event: cloneDeep(this.clonedCluster)});
}
+
reset = () => this.clonedCluster = cloneDeep(this.cluster);
confirmAndReset() {
return this.IgniteConfirm.confirm('Are you sure you want to undo all
changes for current cluster?')
http://git-wip-us.apache.org/repos/asf/ignite/blob/77316692/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.spec.js
----------------------------------------------------------------------
diff --git
a/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.spec.js
b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.spec.js
new file mode 100644
index 0000000..cac888f
--- /dev/null
+++
b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.spec.js
@@ -0,0 +1,81 @@
+/*
+ * 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 'mocha';
+import {assert} from 'chai';
+import {spy} from 'sinon';
+import Controller from './controller';
+
+suite('cluster-edit-form controller', () => {
+ test('cluster binding changes', () => {
+ const $scope = {
+ ui: {
+ inputForm: {
+ $setPristine: spy(),
+ $setUntouched: spy()
+ }
+ }
+ };
+
+ const mocks = Controller.$inject.map((token) => {
+ switch (token) {
+ case '$scope': return $scope;
+ default: return null;
+ }
+ });
+
+ const changeBoundCluster = ($ctrl, cluster) => {
+ $ctrl.cluster = cluster;
+ $ctrl.$onChanges({
+ cluster: {
+ currentValue: cluster
+ }
+ });
+ };
+
+ const $ctrl = new Controller(...mocks);
+
+ const cluster1 = {_id: 1, caches: [1, 2, 3]};
+ const cluster2 = {_id: 1, caches: [1, 2, 3, 4, 5, 6], models: [1, 2,
3]};
+ const cluster3 = {_id: 1, caches: [1, 2, 3, 4, 5, 6], models: [1, 2,
3], name: 'Foo'};
+
+ changeBoundCluster($ctrl, cluster1);
+
+ assert.notEqual($ctrl.clonedCluster, cluster1, 'Cloned cluster is
really cloned');
+ assert.deepEqual($ctrl.clonedCluster, cluster1, 'Cloned cluster is
really a clone of incloming value');
+ assert.equal(1, $scope.ui.inputForm.$setPristine.callCount, 'Sets form
pristine when cluster value changes');
+ assert.equal(1, $scope.ui.inputForm.$setUntouched.callCount, 'Sets
form untouched when cluster value changes');
+
+ changeBoundCluster($ctrl, cluster2);
+
+ assert.deepEqual(
+ $ctrl.clonedCluster,
+ cluster2,
+ 'Overrides clonedCluster if incoming cluster has same id but
different caches or models'
+ );
+ assert.equal(2, $scope.ui.inputForm.$setPristine.callCount, 'Sets form
pristine when bound cluster caches/models change');
+ assert.equal(2, $scope.ui.inputForm.$setUntouched.callCount, 'Sets
form untouched when bound cluster caches/models change');
+
+ changeBoundCluster($ctrl, cluster3);
+
+ assert.deepEqual(
+ $ctrl.clonedCluster,
+ cluster2,
+ 'Does not change cloned cluster value if fields other than id,
chaches and models change'
+ );
+ });
+});