blob: 24b16bb9e1c439c29bf7e496b5377133ff6e6901 [file] [log] [blame]
/*
* 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 {forkJoin, merge} from 'rxjs';
import {map, tap, pluck, take, filter, distinctUntilChanged, switchMap, publishReplay, refCount} from 'rxjs/operators';
import cloneDeep from 'lodash/cloneDeep';
import get from 'lodash/get';
import naturalCompare from 'natural-compare-lite';
import {
changeItem,
removeClusterItems,
basicSave,
basicSaveAndDownload
} from '../../store/actionCreators';
import {Confirm} from 'app/services/Confirm.service';
import ConfigureState from '../../services/ConfigureState';
import ConfigSelectors from '../../store/selectors';
import Caches from '../../services/Caches';
import Clusters from '../../services/Clusters';
import IgniteVersion from 'app/services/Version.service';
import {default as ConfigChangesGuard} from '../../services/ConfigChangesGuard';
import {UIRouter} from '@uirouter/angularjs';
import FormUtils from 'app/services/FormUtils.service';
export default class PageConfigureBasicController {
form: ng.IFormController;
static $inject = [
'Confirm', '$uiRouter', 'ConfigureState', 'ConfigSelectors', 'Clusters', 'Caches', 'IgniteVersion', '$element', 'ConfigChangesGuard', 'IgniteFormUtils', '$scope'
];
constructor(
private Confirm: Confirm,
private $uiRouter: UIRouter,
private ConfigureState: ConfigureState,
private ConfigSelectors: ConfigSelectors,
private Clusters: Clusters,
private Caches: Caches,
private IgniteVersion: IgniteVersion,
private $element: JQLite,
private ConfigChangesGuard: ReturnType<typeof ConfigChangesGuard>,
private IgniteFormUtils: ReturnType<typeof FormUtils>,
private $scope: ng.IScope
) {}
$onDestroy() {
this.subscription.unsubscribe();
if (this.onBeforeTransition) this.onBeforeTransition();
this.$element = null;
}
$postLink() {
this.$element.addClass('panel--ignite');
}
_uiCanExit($transition$) {
const options = $transition$.options();
if (options.custom.justIDUpdate || options.redirectedFrom)
return true;
$transition$.onSuccess({}, () => this.reset());
return forkJoin(
this.ConfigureState.state$.pipe(pluck('edit', 'changes'), take(1)),
this.clusterID$.pipe(
switchMap((id) => this.ConfigureState.state$.pipe(this.ConfigSelectors.selectClusterShortCaches(id))),
take(1)
),
this.shortCaches$.pipe(take(1))
)
.toPromise()
.then(([changes, originalShortCaches, currentCaches]) => {
return this.ConfigChangesGuard.guard(
{
cluster: this.Clusters.normalize(this.originalCluster),
caches: originalShortCaches.map(this.Caches.normalize)
},
{
cluster: {...this.Clusters.normalize(this.clonedCluster), caches: changes.caches.ids},
caches: currentCaches.map(this.Caches.normalize)
}
);
});
}
$onInit() {
this.onBeforeTransition = this.$uiRouter.transitionService.onBefore({}, (t) => this._uiCanExit(t));
this.memorySizeInputVisible$ = this.IgniteVersion.currentSbj.pipe(
map((version) => this.IgniteVersion.since(version.ignite, '2.0.0'))
);
const clusterID$ = this.$uiRouter.globals.params$.pipe(
take(1),
pluck('clusterID'),
filter((v) => v),
take(1)
);
this.clusterID$ = clusterID$;
this.isNew$ = this.$uiRouter.globals.params$.pipe(pluck('clusterID'), map((id) => id === 'new'));
this.shortCaches$ = this.ConfigureState.state$.pipe(this.ConfigSelectors.selectCurrentShortCaches);
this.shortClusters$ = this.ConfigureState.state$.pipe(this.ConfigSelectors.selectShortClustersValue());
this.originalCluster$ = clusterID$.pipe(
distinctUntilChanged(),
switchMap((id) => {
return this.ConfigureState.state$.pipe(this.ConfigSelectors.selectClusterToEdit(id));
}),
distinctUntilChanged(),
publishReplay(1),
refCount()
);
this.subscription = merge(
this.shortCaches$.pipe(
map((caches) => caches.sort((a, b) => naturalCompare(a.name, b.name))),
tap((v) => this.shortCaches = v)
),
this.shortClusters$.pipe(tap((v) => this.shortClusters = v)),
this.originalCluster$.pipe(tap((v) => {
this.originalCluster = v;
// clonedCluster should be set only when particular cluster edit starts.
//
// Stored cluster changes should not propagate to clonedCluster because it's assumed
// that last saved copy has same shape to what's already loaded. If stored cluster would overwrite
// clonedCluster every time, then data rollback on server errors would undo all changes
// made by user and we don't want that. Advanced configuration forms do the same too.
if (get(v, '_id') !== get(this.clonedCluster, '_id')) this.clonedCluster = cloneDeep(v);
this.defaultMemoryPolicy = this.Clusters.getDefaultClusterMemoryPolicy(this.clonedCluster);
}))
).subscribe();
this.formActionsMenu = [
{
text: 'Save and Download',
click: () => this.save(true),
icon: 'download'
},
{
text: 'Save',
click: () => this.save(),
icon: 'checkmark'
}
];
this.cachesColDefs = [
{name: 'Name:', cellClass: 'pc-form-grid-col-10'},
{name: 'Mode:', cellClass: 'pc-form-grid-col-10'},
{name: 'Atomicity:', cellClass: 'pc-form-grid-col-20', tip: `
Atomicity:
<ul>
<li>ATOMIC - in this mode distributed transactions and distributed locking are not supported</li>
<li>TRANSACTIONAL - in this mode specified fully ACID-compliant transactional cache behavior</li>
<li>TRANSACTIONAL_SNAPSHOT - in this mode specified fully ACID-compliant transactional cache behavior for both key-value API and SQL transactions</li>
</ul>
`},
{name: 'Backups:', cellClass: 'pc-form-grid-col-10', tip: `
Number of nodes used to back up single partition for partitioned cache
`}
];
}
addCache() {
this.ConfigureState.dispatchAction({type: 'ADD_CACHE_TO_EDIT'});
}
removeCache(cache) {
this.ConfigureState.dispatchAction(
removeClusterItems(this.$uiRouter.globals.params.clusterID, 'caches', [cache._id], false, false)
);
}
changeCache(cache) {
return this.ConfigureState.dispatchAction(changeItem('caches', cache));
}
save(download = false) {
if (this.form.$invalid)
return this.IgniteFormUtils.triggerValidation(this.form, this.$scope);
this.ConfigureState.dispatchAction((download ? basicSaveAndDownload : basicSave)(cloneDeep(this.clonedCluster)));
}
reset() {
this.clonedCluster = cloneDeep(this.originalCluster);
this.ConfigureState.dispatchAction({type: 'RESET_EDIT_CHANGES'});
}
confirmAndReset() {
return this.Confirm.confirm('Are you sure you want to undo all changes for current cluster?')
.then(() => this.reset())
.catch(() => {});
}
}