fuel-ui/static/component_mixins.js

165 lines
4.8 KiB
JavaScript

/*
* Copyright 2014 Mirantis, 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.
**/
import $ from 'jquery';
import _ from 'underscore';
import Backbone from 'backbone';
import i18n from 'i18n';
import React from 'react';
import ReactDOM from 'react-dom';
import dispatcher from 'dispatcher';
import {DiscardSettingsChangesDialog} from 'views/dialogs';
export {default as backboneMixin} from 'react_backbone_mixin';
export function dispatcherMixin(events, callback) {
return {
componentDidMount() {
dispatcher.on(events, _.isString(callback) ? this[callback] : callback, this);
},
componentWillUnmount() {
dispatcher.off(null, null, this);
}
};
}
export var unsavedChangesMixin = {
onBeforeunloadEvent() {
return this.hasChanges() &&
(_.result(this, 'getStayMessage') || i18n('dialog.dismiss_settings.default_message'));
},
componentWillMount() {
this.eventName = _.uniqueId('unsavedchanges');
$(window).on('beforeunload.' + this.eventName, this.onBeforeunloadEvent);
$('body').on('click.' + this.eventName, 'a[href^="#"]:not(.no-leave-check)', this.onLeave);
},
componentWillUnmount() {
$(window).off('beforeunload.' + this.eventName);
$('body').off('click.' + this.eventName);
},
onLeave(e) {
var href = $(e.currentTarget).attr('href');
if (Backbone.history.getHash() !== href.substr(1) && _.result(this, 'hasChanges')) {
e.preventDefault();
DiscardSettingsChangesDialog
.show({
isDiscardingPossible: _.result(this, 'isDiscardingPossible'),
isSavingPossible: _.result(this, 'isSavingPossible'),
applyChanges: this.applyChanges,
revertChanges: this.revertChanges
}).then(() => {
app.navigate(href);
});
}
}
};
export function pollingMixin(updateInterval, delayedStart) {
updateInterval = updateInterval * 1000;
return {
scheduleDataFetch() {
var shouldDataBeFetched = !_.isFunction(this.shouldDataBeFetched) ||
this.shouldDataBeFetched();
if (this.isMounted() && !this.activeTimeout && shouldDataBeFetched) {
this.activeTimeout = _.delay(this.startPolling, updateInterval);
}
},
startPolling(force) {
var shouldDataBeFetched = force || !_.isFunction(this.shouldDataBeFetched) ||
this.shouldDataBeFetched();
if (shouldDataBeFetched) {
this.stopPolling();
return this.fetchData().then(this.scheduleDataFetch, this.scheduleDataFetch);
}
return Promise.resolve();
},
stopPolling() {
if (this.activeTimeout) clearTimeout(this.activeTimeout);
delete this.activeTimeout;
},
componentDidMount() {
if (delayedStart) {
this.scheduleDataFetch();
} else {
this.startPolling();
}
},
componentWillUnmount() {
this.stopPolling();
}
};
}
export var outerClickMixin = {
propTypes: {
toggle: React.PropTypes.func
},
getInitialState() {
return {
clickEventName: 'click.' + _.uniqueId('outer-click')
};
},
handleBodyClick(e) {
if (!$(e.target).closest(ReactDOM.findDOMNode(this)).length) {
_.defer(_.partial(this.props.toggle, false));
}
},
componentDidMount() {
if (this.props.toggle) {
$('html').on(this.state.clickEventName, this.handleBodyClick);
Backbone.history.on('route', _.partial(this.props.toggle, false), this);
}
},
componentWillUnmount() {
if (this.props.toggle) {
$('html').off(this.state.clickEventName);
Backbone.history.off('route', null, this);
}
}
};
export function renamingMixin(refname) {
return {
getInitialState() {
return {
isRenaming: false,
renamingMixinEventName: 'click.' + _.uniqueId('rename')
};
},
componentWillUnmount() {
$('html').off(this.state.renamingMixinEventName);
},
startRenaming(e) {
e.preventDefault();
$('html').on(this.state.renamingMixinEventName, (e) => {
if (e && !$(e.target).closest(ReactDOM.findDOMNode(this.refs[refname])).length) {
this.endRenaming();
} else {
e.preventDefault();
}
});
this.setState({isRenaming: true});
},
endRenaming() {
$('html').off(this.state.renamingMixinEventName);
this.setState({
isRenaming: false,
actionInProgress: false
});
}
};
}