mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 11:20:39 -03:30
Merge pull request #531 from mabashian/4796-workflow-resize-v2
Zoom workflow graph to fit screen on initial load
This commit is contained in:
commit
2f689fffbe
@ -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}}',
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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%;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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");
|
||||
});
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user