Merge pull request #531 from mabashian/4796-workflow-resize-v2

Zoom workflow graph to fit screen on initial load
This commit is contained in:
Michael Abashian 2017-10-23 10:47:14 -04:00 committed by GitHub
commit 2f689fffbe
11 changed files with 85 additions and 34 deletions

View File

@ -163,7 +163,7 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n) {
},
add_survey: {
ngClick: 'addSurvey()',
ngShow: '$state.is(\'templates.addWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate.workflowMaker\')',
ngShow: '!survey_exists && ($state.is(\'templates.addWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate.workflowMaker\'))',
awFeature: 'surveys',
awToolTip: '{{surveyTooltip}}',
dataPlacement: 'top',
@ -173,7 +173,7 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n) {
edit_survey: {
ngClick: 'editSurvey()',
awFeature: 'surveys',
ngShow: '$state.is(\'templates.addWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate.workflowMaker\')',
ngShow: 'survey_exists && ($state.is(\'templates.addWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate\') || $state.is(\'templates.editWorkflowJobTemplate.workflowMaker\'))',
label: i18n._('Edit Survey'),
class: 'Form-primaryButton',
awToolTip: '{{surveyTooltip}}',

View File

@ -21,7 +21,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
restrict: 'E',
link: function(scope, element) {
let margin = {top: 20, right: 20, bottom: 20, left: 20},
let marginLeft = 20,
i = 0,
nodeW = 180,
nodeH = 60,
@ -36,7 +36,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
line,
zoomObj,
baseSvg,
svgGroup;
svgGroup,
graphLoaded;
scope.dimensionsSet = false;
@ -75,7 +76,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
);
svgGroup = baseSvg.append("g")
.attr("transform", "translate(" + margin.left + "," + (windowHeight/2 - rootH/2 - startNodeOffsetY) + ")");
.attr("id", "aw-workflow-chart-g")
.attr("transform", "translate(" + marginLeft + "," + (windowHeight/2 - rootH/2 - startNodeOffsetY) + ")");
}
function calcAvailableScreenSpace() {
@ -158,7 +160,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
let scale = d3.event.scale,
translation = d3.event.translate;
translation = [translation[0] + (margin.left*scale), translation[1] + ((windowHeight/2 - rootH/2 - startNodeOffsetY)*scale)];
translation = [translation[0] + (marginLeft*scale), translation[1] + ((windowHeight/2 - rootH/2 - startNodeOffsetY)*scale)];
svgGroup.attr("transform", "translate(" + translation + ")scale(" + scale + ")");
@ -177,7 +179,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
translateX = unscaledOffsetX*scale - ((scale*windowWidth)-windowWidth)/2,
translateY = unscaledOffsetY*scale - ((scale*windowHeight)-windowHeight)/2;
svgGroup.attr("transform", "translate(" + [translateX + (margin.left*scale), translateY + ((windowHeight/2 - rootH/2 - startNodeOffsetY)*scale)] + ")scale(" + scale + ")");
svgGroup.attr("transform", "translate(" + [translateX + (marginLeft*scale), translateY + ((windowHeight/2 - rootH/2 - startNodeOffsetY)*scale)] + ")scale(" + scale + ")");
zoomObj.scale(scale);
zoomObj.translate([translateX, translateY]);
}
@ -200,12 +202,36 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
}
function resetZoomAndPan() {
svgGroup.attr("transform", "translate(" + margin.left + "," + (windowHeight/2 - rootH/2 - startNodeOffsetY) + ")scale(" + 1 + ")");
svgGroup.attr("transform", "translate(" + marginLeft + "," + (windowHeight/2 - rootH/2 - startNodeOffsetY) + ")scale(" + 1 + ")");
// Update the zoomObj
zoomObj.scale(1);
zoomObj.translate([0,0]);
}
function zoomToFitChart() {
let graphDimensions = d3.select('#aw-workflow-chart-g')[0][0].getBoundingClientRect(),
startNodeDimensions = d3.select('.WorkflowChart-rootNode')[0][0].getBoundingClientRect(),
availableScreenSpace = calcAvailableScreenSpace(),
currentZoomValue = zoomObj.scale(),
unscaledH = graphDimensions.height/currentZoomValue,
unscaledW = graphDimensions.width/currentZoomValue,
scaleNeededForMaxHeight = (availableScreenSpace.height)/unscaledH,
scaleNeededForMaxWidth = (availableScreenSpace.width - marginLeft)/unscaledW,
lowerScale = Math.min(scaleNeededForMaxHeight, scaleNeededForMaxWidth),
scaleToFit = lowerScale < 0.5 ? 0.5 : (lowerScale > 2 ? 2 : Math.floor(lowerScale * 10)/10),
startNodeOffsetFromGraphCenter = Math.round((((rootH/2) + (startNodeDimensions.top/currentZoomValue)) - ((graphDimensions.top/currentZoomValue) + (unscaledH/2)))*scaleToFit);
manualZoom(scaleToFit*100);
scope.workflowZoomed({
zoom: scaleToFit
});
svgGroup.attr("transform", "translate(" + marginLeft + "," + (windowHeight/2 - (nodeH*scaleToFit/2) + startNodeOffsetFromGraphCenter) + ")scale(" + scaleToFit + ")");
zoomObj.translate([marginLeft - scaleToFit*marginLeft, windowHeight/2 - (nodeH*scaleToFit/2) + startNodeOffsetFromGraphCenter - ((windowHeight/2 - rootH/2 - startNodeOffsetY)*scaleToFit)]);
}
function update() {
let userCanAddEdit = (scope.workflowJobTemplateObj && scope.workflowJobTemplateObj.summary_fields && scope.workflowJobTemplateObj.summary_fields.user_capabilities && scope.workflowJobTemplateObj.summary_fields.user_capabilities.edit) || scope.canAddWorkflowJobTemplate;
if(scope.dimensionsSet) {
@ -243,7 +269,6 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
thisNode.append("rect")
.attr("width", rootW)
.attr("height", rootH)
//.attr("y", (windowHeight-margin.top-margin.bottom)/2 - rootH)
.attr("y", 10)
.attr("rx", 5)
.attr("ry", 5)
@ -252,7 +277,6 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.call(add_node);
thisNode.append("text")
.attr("x", 13)
//.attr("y", (windowHeight-margin.top-margin.bottom)/2 - rootH + rootH/2)
.attr("y", 30)
.attr("dy", ".35em")
.attr("class", "WorkflowChart-startText")
@ -544,6 +568,12 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
node.exit().remove();
if(nodes && nodes.length > 1 && !graphLoaded) {
zoomToFitChart();
}
graphLoaded = true;
let link = svgGroup.selectAll("g.link")
.data(links, function(d) {
return d.source.id + "-" + d.target.id;
@ -927,6 +957,10 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
manualZoom(params.zoom);
});
scope.$on('zoomToFitChart', function() {
zoomToFitChart();
});
let clearWatchTreeData = scope.$watch('treeData', function(newVal) {
if(newVal) {
update();

View File

@ -7,7 +7,7 @@
flex: 1 0 auto;
}
.WorkflowControls-Pan {
flex: 0 0 85px;
flex: 0 0 87px;
}
.WorkflowControls-Pan--button {
color: @default-icon;
@ -49,17 +49,10 @@
.WorkflowControls-Zoom--button:hover {
color: @default-link-hov;
}
.WorkflowControls-Zoom--minus {
margin-left: 20px;
padding-right: 8px;
}
.WorkflowControls-Zoom--plus {
padding-left: 8px;
}
.WorkflowControls-zoomSlider {
width: 150px;
padding-left: 10px;
padding-right: 10px;
padding-left: 8px;
padding-right: 8px;
}
.WorkflowControls-zoomPercentage {
text-align: center;
@ -67,6 +60,16 @@
height: 24px;
line-height: 24px;
}
.WorkflowControls-ZoomToFit {
display: flex;
flex: 0 0 62px;
align-items: center;
justify-content: center;
color: @default-icon;
}
.WorkflowControls-ZoomToFit:hover {
color: @default-link-hov;
}
.ui-slider-handle.ui-state-default.ui-corner-all {
border-radius: 50%;

View File

@ -10,7 +10,8 @@ export default ['templateUrl',
scope: {
panChart: '&',
resetChart: '&',
zoomChart: '&'
zoomChart: '&',
zoomToFitChart: '&'
},
templateUrl: templateUrl('templates/workflows/workflow-controls/workflow-controls'),
restrict: 'E',
@ -60,6 +61,10 @@ export default ['templateUrl',
});
};
scope.zoomToFit = function() {
scope.zoomToFitChart();
};
scope.$on('workflowZoomed', function(evt, params) {
scope.zoom = Math.round(params.zoom * 10) * 10;
$("#slider").slider('value',scope.zoom);

View File

@ -1,3 +1,6 @@
<div class="WorkflowControls-ZoomToFit">
<i class="fa fa-desktop" ng-click="zoomToFit()"></i>
</div>
<div class="WorkflowControls-Zoom">
<div class="WorkflowControls-Zoom--button WorkflowControls-Zoom--minus" ng-click="zoomOut()">
<i class="fa fa-minus" aria-hidden="true"></i>

View File

@ -168,7 +168,7 @@
flex: 1 0 auto;
}
.WorkflowLegend-maker--right {
flex: 0 0 215px;
flex: 0 0 217px;
text-align: right;
padding-right: 20px;
position: relative;
@ -246,9 +246,9 @@
}
.WorkflowMaker-manualControls {
position: absolute;
left: -77px;
left: -106px;
height: 60px;
width: 293px;
width: 322px;
background-color: @default-bg;
display: flex;
border: 1px solid @b7grey;
@ -259,10 +259,10 @@
}
.WorkflowLegend-manualControls {
position: absolute;
left: -239px;
left: -272px;
top: 38px;
height: 60px;
width: 290px;
width: 322px;
background-color: @default-bg;
display: flex;
border: 1px solid @d7grey;

View File

@ -31,9 +31,9 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
showTypeOptions: false
};
$scope.editRequests = [];
$scope.associateRequests = [];
$scope.disassociateRequests = [];
$scope.editRequests = [];
$scope.associateRequests = [];
$scope.disassociateRequests = [];
$scope.showKey = false;
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
@ -940,9 +940,9 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
};
$scope.$on('WorkflowDialogReady', function(){
$scope.modalOpen = true;
});
$scope.zoomToFitChart = function() {
$scope.$broadcast('zoomToFitChart');
};
init();

View File

@ -57,6 +57,8 @@ export default ['templateUrl', 'CreateDialog', 'Wait', '$state', '$window',
scope.removeWorkflowDialogReady = scope.$on('WorkflowDialogReady', function() {
$('#workflow-modal-dialog').dialog('open');
scope.modalOpen = true;
scope.$broadcast("refreshWorkflowChart");
});

View File

@ -69,7 +69,7 @@
<span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span>
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()"></workflow-controls>
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
</div>
</div>
</div>

View File

@ -165,6 +165,10 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
$scope.$broadcast('resetWorkflowChart');
};
$scope.zoomToFitChart = function() {
$scope.$broadcast('zoomToFitChart');
};
$scope.workflowZoomed = function(zoom) {
$scope.$broadcast('workflowZoomed', {
zoom: zoom

View File

@ -289,7 +289,7 @@
<div class="WorkflowLegend-details--right">
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
<div ng-show="showManualControls" class="WorkflowLegend-manualControls noselect">
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()"></workflow-controls>
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
</div>
</div>
</div>