webgme
Version:
Web-based Generic Modeling Environment
343 lines (304 loc) • 14.2 kB
JavaScript
/*globals define, WebGMEGlobal, $*/
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
* @author pmeijer / https://github.com/pmeijer
*/
define([
'js/logger',
'js/Controls/DropDownMenu',
'js/Controls/PopoverBox',
'js/Dialogs/Merge/MergeDialog',
'js/Utils/ComponentSettings',
'js/Constants'
], function (Logger, DropDownMenu, PopoverBox, MergeDialog, ComponentSettings, CONSTANTS) {
'use strict';
var BranchStatusWidget,
ITEM_VALUE_FORK = 'fork',
ITEM_VALUE_FOLLOW = 'follow',
ITEM_VALUE_MERGE = 'merge',
ITEM_VALUE_SELECT_BRANCH = 'select',
ITEM_VALUE_DOWNLOAD_ERROR = 'downloadError',
ITEM_VALUE_DOWNLOAD_COMMIT_QUEUE = 'downloadCommitQueue';
function _getDefaultConfig() {
return {
autoFollowBranchWhenOutOfSync: false
};
}
function _getComponentId() {
return 'GenericUIBranchStatus';
}
function _getConfig() {
return ComponentSettings.resolveWithWebGMEGlobal(_getDefaultConfig(), _getComponentId());
}
BranchStatusWidget = function (containerEl, client) {
this._logger = Logger.create('gme:Widgets:BranchStatusWidget', WebGMEGlobal.gmeConfig.client.log);
this._config = _getConfig();
this._client = client;
this._el = containerEl;
this._eventData = null;
this._initializeUI();
this._logger.debug('Created');
};
BranchStatusWidget.prototype._initializeUI = function () {
var self = this;
this._el.empty();
//BranchStatus DropDownMenu
this._ddBranchStatus = new DropDownMenu({
dropUp: true,
pullRight: true,
size: 'micro',
sort: true
});
this._ddBranchStatus.setTitle('BRANCHSTATUS');
this._el.append(this._ddBranchStatus.getEl());
this._popoverBox = new PopoverBox(this._ddBranchStatus.getEl());
this._ddBranchStatus.onDropDownMenuOpen = function () {
self._popoverBox.hide();
};
this._ddBranchStatus.onItemClicked = function (value) {
var branchName = self._client.getActiveBranchName(),
projectName = self._client.getActiveProjectId();
if (value === ITEM_VALUE_FORK) {
self._client.forkCurrentBranch(null, null, function (err, forkName) {
if (err) {
self._logger.error('could not fork the branch', branchName);
self._client.selectBranch(branchName, null, function (err) {
if (err) {
self._logger.error('could not re-select the branch', branchName);
throw err;
}
});
} else {
self._client.selectBranch(forkName, null, function (err) {
if (err) {
self._logger.error('Could not select new branch', forkName);
throw err;
}
});
}
});
} else if (value === ITEM_VALUE_FOLLOW) {
self._client.selectBranch(branchName, null, function (err) {
if (err) {
self._logger.error('could not re-select the branch', branchName);
throw new Error(err);
}
});
} else if (value === ITEM_VALUE_MERGE) {
self._client.forkCurrentBranch(null, null, function (err, forkName, forkHash) {
if (err) {
self._logger.error('could not fork the branch', branchName);
self._client.selectBranch(branchName, null, function (err) {
if (err) {
self._logger.error('could not re-select the branch', branchName);
throw new Error(err);
}
});
} else {
self._client.autoMerge(projectName, forkName, branchName, function (err, result) {
var mergeDialog = new MergeDialog(self.gmeClient);
if (err) {
self._logger.error('Merging resulted in error', err);
self._logger.info('Trying to select fork', forkName);
self._client.selectBranch(forkName, null, function (err) {
if (err) {
self._logger.error('Could not select new branch', forkName);
throw new Error(err);
}
});
return;
}
if (result && result.conflict && result.conflict.items.length > 0) {
//TODO create some user-friendly way to show this type of result
// TODO: we may need to open the mergeDialog here: mergeDialog.show('merge ended in conflicts', result);
self._logger.error('merge had conflicts', result.conflict);
self._client.selectBranch(forkName, null, function (err) {
if (err) {
self._logger.error('Could not select the new branch', forkName);
throw new Error(err);
}
});
} else {
self._logger.debug('Merge was successful');
self._client.selectBranch(branchName, null, function (err) {
if (err) {
self._logger.error('could not select the branch after merge', branchName);
throw new Error(err);
}
mergeDialog.show(null, result);
});
self._client.deleteBranch(projectName, forkName, forkHash, function (err) {
if (err) {
self._logger.error('Could delete temporary branch after merge', forkName);
}
});
}
});
}
});
} else if (value === ITEM_VALUE_SELECT_BRANCH) {
self._client.selectBranch(branchName, null, function (err) {
if (err) {
self._logger.error(err);
} else {
self._logger.debug('branch selected: ', branchName);
}
});
} else if (value === ITEM_VALUE_DOWNLOAD_ERROR) {
self._client.downloadError();
} else if (value === ITEM_VALUE_DOWNLOAD_COMMIT_QUEUE) {
self._client.downloadCommitQueue();
}
};
this._client.addEventListener(CONSTANTS.CLIENT.BRANCH_STATUS_CHANGED, function (__client, eventData) {
self._refreshBranchStatus(eventData);
}
);
this._refreshBranchStatus({status: this._client.getBranchStatus()});
window.addEventListener('beforeunload', function (event) {
var commitQueue = self._client.getCommitQueue(),
message;
if (commitQueue.length > 0) {
message = 'There are ' + commitQueue.length + ' commit(s) in your commitQueue. You will loose this ' +
'data unless you take an action in the branch status (footer) widget.';
event.returnValue = message; // Gecko, Trident, Chrome 34+
return message; // Gecko, WebKit, Chrome <34
}
});
};
BranchStatusWidget.prototype._refreshBranchStatus = function (eventData) {
var status = eventData.status;
this._eventData = eventData;
switch (status) {
case CONSTANTS.CLIENT.BRANCH_STATUS.SYNC:
this._branchInSync();
break;
case CONSTANTS.CLIENT.BRANCH_STATUS.AHEAD_NOT_SYNC:
this._branchAheadNotSync(eventData);
break;
case CONSTANTS.CLIENT.BRANCH_STATUS.AHEAD_SYNC:
this._branchAhead(eventData);
break;
case CONSTANTS.CLIENT.BRANCH_STATUS.MERGING:
this._branchMerging(eventData);
break;
case CONSTANTS.CLIENT.BRANCH_STATUS.PULLING:
this._branchPulling(eventData);
break;
case CONSTANTS.CLIENT.BRANCH_STATUS.ERROR:
this._branchError(eventData);
break;
default:
this._noBranch();
break;
}
};
BranchStatusWidget.prototype._branchInSync = function () {
this._ddBranchStatus.clear();
this._ddBranchStatus.setTitle('IN SYNC');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.GREEN);
if (this._outOfSync === true) {
this._popoverBox.show('Back in sync...', this._popoverBox.alertLevels.SUCCESS, true);
delete this._outOfSync;
}
};
BranchStatusWidget.prototype._branchAheadNotSync = function (eventData) {
this._ddBranchStatus.clear();
this._outOfSync = true;
if (this._client.isConnected()) {
if (this._config.autoFollowBranchWhenOutOfSync && this._client.getCommitQueue().length === 1) {
$.notify({
icon: 'fa fa-share-alt fa-rotate-90',
message: 'Ooops! Looks like someone is chaning the model concurretly .. ' +
'Your last change was dropped, check branch history for details.'
}, {
delay: 10000,
hideDuration: 0,
type: 'warning',
offset: {
x: 20,
y: 37
}
});
this._ddBranchStatus.onItemClicked(ITEM_VALUE_FOLLOW);
return;
}
this._ddBranchStatus.addItem({
text: 'Create a branch with local changes.',
value: ITEM_VALUE_FORK
});
this._ddBranchStatus.addItem({
text: 'Drop local changes and follow branch.',
value: ITEM_VALUE_FOLLOW
});
this._ddBranchStatus.addItem({
text: 'Attempt to merge in local changes.',
value: ITEM_VALUE_MERGE
});
}
this._ddBranchStatus.addItem({
text: 'Download local changes.',
value: ITEM_VALUE_DOWNLOAD_COMMIT_QUEUE
});
this._ddBranchStatus.setTitle('AHEAD[' + eventData.commitQueue.length + ']');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.ORANGE);
$.notify({
icon: 'fa fa-share-alt fa-rotate-90',
message: 'You are not not in sync with the current branch. Your action is required! Pick a solution ' +
'from the widget down in the footer.'
}, {
delay: 10000,
hideDuration: 0,
type: 'warning',
offset: {
x: 20,
y: 37
}
});
this._popoverBox.show('You are out of sync - an action is required!',
this._popoverBox.alertLevels.WARNING, true);
};
BranchStatusWidget.prototype._branchAhead = function (eventData) {
this._ddBranchStatus.clear();
this._ddBranchStatus.addItem({
text: 'Download local changes.',
value: ITEM_VALUE_DOWNLOAD_COMMIT_QUEUE
});
this._ddBranchStatus.setTitle('AHEAD[' + eventData.commitQueue.length + ']');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.LIGHT_BLUE);
};
BranchStatusWidget.prototype._branchMerging = function (eventData) {
this._ddBranchStatus.clear();
this._ddBranchStatus.setTitle('MERGING[' + eventData.commitQueue.length + ']');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.BLUE);
};
BranchStatusWidget.prototype._branchPulling = function (eventData) {
this._ddBranchStatus.clear();
this._ddBranchStatus.setTitle('PULLING[' + eventData.updateQueue.length + ']');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.GRAY);
};
BranchStatusWidget.prototype._branchError = function (eventData) {
this._ddBranchStatus.clear();
this._ddBranchStatus.setTitle('ERROR');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.RED);
this._popoverBox.show('Critical error - detached from branch.',
this._popoverBox.alertLevels.ERROR, true);
this._ddBranchStatus.addItem({
text: 'Reselect branch',
value: ITEM_VALUE_SELECT_BRANCH
});
this._ddBranchStatus.addItem({
text: 'Download error data',
value: ITEM_VALUE_DOWNLOAD_ERROR
});
};
BranchStatusWidget.prototype._noBranch = function () {
this._ddBranchStatus.clear();
this._ddBranchStatus.setTitle('NO BRANCH');
this._ddBranchStatus.setColor(DropDownMenu.prototype.COLORS.GRAY);
this._outOfSync = false;
//this._popoverBox.show('No branch selected', this._popoverBox.alertLevels.WARNING, false);
};
return BranchStatusWidget;
});