Make angular timeline more modular, add toolbar directive

pull/913/head
Till Breuer 11 years ago
parent e2267d59c3
commit cb8479afcc
  1. 47
      app/assets/javascripts/angular/controllers/timelines_controller.js
  2. 92
      app/assets/javascripts/angular/directives/timeline-container-directive.js
  3. 87
      app/assets/javascripts/angular/directives/timeline-table-container-directive.js
  4. 47
      app/assets/javascripts/angular/directives/timeline-toolbar-directive.js
  5. 2
      app/assets/javascripts/angular/services/timeline-loader-service.js
  6. 8
      app/views/timelines/_timeline.html.erb
  7. 0
      public/templates/timelines/timeline_table_container.html
  8. 0
      public/templates/timelines/toolbar.html

@ -16,55 +16,20 @@ openprojectApp.controller('TimelinesController', ['$scope', '$window', 'Timeline
// Setup
// Get server-side stuff into scope
$scope.currentTimelineId = gon.current_timeline_id;
$scope.timelines = gon.timelines;
$scope.currentTimelineId = gon.current_timeline_id;
$scope.timelineOptions = gon.timeline_options;
// Get timelines stuff into scope and apply defaults
$scope.slider = null;
// Hide charts until tables are drawn
$scope.underConstruction = true;
$scope.currentScaleName = 'monthly';
// Create timeline
// Create timeline object
$scope.timeline = Timeline.create($scope.timelineOptions);
// Set initial expansion index
$scope.timeline.expansionIndex = getInitialOutlineExpansion($scope.timelineOptions);
// Provide id for timeline container
$scope.timelineContainerNo = 1;
$scope.getTimelineContainerElementId = function() {
return 'timeline-container-' + $scope.timelineContainerNo;
};
$scope.$watch('currentScaleName', function(newScaleName, oldScaleName){
if (newScaleName !== oldScaleName) {
$scope.currentScale = Timeline.ZOOM_CONFIGURATIONS[$scope.currentScaleName].scale;
$scope.timeline.scale = $scope.currentScale;
$scope.currentScaleIndex = Timeline.ZOOM_SCALES.indexOf($scope.currentScaleName);
$scope.slider.slider('value', $scope.currentScaleIndex + 1);
$scope.timeline.zoom($scope.currentScaleIndex); // TODO replace event-driven adaption by bindings
}
});
$scope.$watch('currentOutlineLevel', function(outlineLevel, formerLevel) {
if (outlineLevel !== formerLevel) {
$scope.timeline.expansionIndex = Timeline.OUTLINE_LEVELS.indexOf(outlineLevel);
$scope.timeline.expandToOutlineLevel(outlineLevel); // TODO replace event-driven adaption by bindings
}
});
$scope.increaseZoom = function() {
if($scope.currentScaleIndex < Object.keys(Timeline.ZOOM_CONFIGURATIONS).length - 1) {
$scope.currentScaleIndex++;
}
};
$scope.decreaseZoom = function() {
if($scope.currentScaleIndex > 0) {
$scope.currentScaleIndex--;
}
};
// Count timeline containers
$scope.timelineContainerCount = 0;
}]);

@ -1,93 +1,11 @@
openprojectApp.directive('timelineContainer', ['TimelineLoaderService', 'TimelineTableHelper', function(TimelineLoaderService, TimelineTableHelper) {
openprojectApp.directive('timelineContainer', [function() {
return {
restrict: 'E',
replace: true,
templateUrl: '/templates/timelines/timeline_container.html',
link: function(scope, element, attributes) {
updateToolbar = function() {
scope.slider.slider('value', scope.timeline.zoomIndex + 1);
scope.currentOutlineLevel = Timeline.OUTLINE_LEVELS[scope.timeline.expansionIndex];
scope.currentScaleName = Timeline.ZOOM_SCALES[scope.timeline.zoomIndex];
};
completeUI = function() {
// lift the curtain, paper otherwise doesn't show w/ VML.
scope.underConstruction = false;
scope.timeline.paper = new Raphael(scope.timeline.paperElement, 640, 480);
// perform some zooming. if there is a zoom level stored with the
// report, zoom to it. otherwise, zoom out. this also constructs
// timeline graph.
if (scope.timeline.options.zoom_factor &&
scope.timeline.options.zoom_factor.length === 1) {
scope.timeline.zoom(
scope.timeline.pnum(scope.timeline.options.zoom_factor[0])
);
} else {
scope.timeline.zoomOut();
}
// perform initial outline expansion.
if (scope.timeline.options.initial_outline_expansion &&
scope.timeline.options.initial_outline_expansion.length === 1) {
scope.timeline.expandTo(
scope.timeline.pnum(scope.timeline.options.initial_outline_expansion[0])
);
}
// zooming and initial outline expansion have consequences in the
// select inputs in the toolbar.
updateToolbar();
scope.timeline.getChart().scroll(function() {
scope.timeline.adjustTooltip();
});
jQuery(window).scroll(function() {
scope.timeline.adjustTooltip();
});
};
buildWorkPackageTable = function(timeline){
if (timeline.isGrouping() && timeline.options.grouping_two_enabled) {
timeline.secondLevelGroupingAdjustments();
}
tree = timeline.getLefthandTree();
if (tree.containsPlanningElements() || tree.containsProjects()) {
timeline.adjustForPlanningElements();
scope.rows = TimelineTableHelper.getTableRowsFromTimelineTree(tree, timeline.options);
} else{
scope.rows = [];
}
return scope.rows;
};
drawChart = function(tree) {
timeline = scope.timeline;
try {
window.clearTimeout(timeline.safetyHook);
if (rows.length > 0) {
completeUI();
} else {
timeline.warn(I18n.t('js.label_no_data'), 'warning');
}
} catch (e) {
timeline.die(e);
}
};
// start timeline
scope.timeline.registerTimelineContainer(element);
TimelineLoaderService.loadTimelineData(scope.timeline)
.then(buildWorkPackageTable)
.then(drawChart);
transclude: true,
template: '<div ng-transclude id="{{timelineContainerElementId}}"/>',
link: function(scope) {
scope.timelineContainerElementId = 'timeline-container-' + (++scope.timelineContainerCount);
}
};
}]);

@ -0,0 +1,87 @@
openprojectApp.directive('timelineTableContainer', ['TimelineLoaderService', 'TimelineTableHelper', function(TimelineLoaderService, TimelineTableHelper) {
return {
restrict: 'E',
replace: true,
templateUrl: '/templates/timelines/timeline_table_container.html',
link: function(scope, element, attributes) {
completeUI = function() {
// lift the curtain, paper otherwise doesn't show w/ VML.
scope.underConstruction = false;
scope.timeline.paper = new Raphael(scope.timeline.paperElement, 640, 480);
// perform some zooming. if there is a zoom level stored with the
// report, zoom to it. otherwise, zoom out. this also constructs
// timeline graph.
if (scope.timeline.options.zoom_factor &&
scope.timeline.options.zoom_factor.length === 1) {
scope.timeline.zoom(
scope.timeline.pnum(scope.timeline.options.zoom_factor[0])
);
} else {
scope.timeline.zoomOut();
}
// perform initial outline expansion.
if (scope.timeline.options.initial_outline_expansion &&
scope.timeline.options.initial_outline_expansion.length === 1) {
scope.timeline.expandTo(
scope.timeline.pnum(scope.timeline.options.initial_outline_expansion[0])
);
}
// zooming and initial outline expansion have consequences in the
// select inputs in the toolbar.
if(scope.updateToolbar) scope.updateToolbar();
scope.timeline.getChart().scroll(function() {
scope.timeline.adjustTooltip();
});
jQuery(window).scroll(function() {
scope.timeline.adjustTooltip();
});
};
buildWorkPackageTable = function(timeline){
if (timeline.isGrouping() && timeline.options.grouping_two_enabled) {
timeline.secondLevelGroupingAdjustments();
}
tree = timeline.getLefthandTree();
if (tree.containsPlanningElements() || tree.containsProjects()) {
timeline.adjustForPlanningElements();
scope.rows = TimelineTableHelper.getTableRowsFromTimelineTree(tree, timeline.options);
} else{
scope.rows = [];
}
return scope.rows;
};
drawChart = function(tree) {
timeline = scope.timeline;
try {
window.clearTimeout(timeline.safetyHook);
if (rows.length > 0) {
completeUI();
} else {
timeline.warn(I18n.t('js.label_no_data'), 'warning');
}
} catch (e) {
timeline.die(e);
}
};
// start timeline
scope.timeline.registerTimelineContainer(element);
TimelineLoaderService.loadTimelineData(scope.timeline)
.then(buildWorkPackageTable)
.then(drawChart);
}
};
}]);

@ -0,0 +1,47 @@
openprojectApp.directive('timelineToolbar', [function() {
return {
restrict: 'E',
replace: true,
templateUrl: '/templates/timelines/toolbar.html',
link: function(scope) {
scope.currentScaleName = 'monthly';
scope.updateToolbar = function() {
scope.slider.slider('value', scope.timeline.zoomIndex + 1);
scope.currentOutlineLevel = Timeline.OUTLINE_LEVELS[scope.timeline.expansionIndex];
scope.currentScaleName = Timeline.ZOOM_SCALES[scope.timeline.zoomIndex];
};
scope.increaseZoom = function() {
if(scope.currentScaleIndex < Object.keys(Timeline.ZOOM_CONFIGURATIONS).length - 1) {
scope.currentScaleIndex++;
}
};
scope.decreaseZoom = function() {
if(scope.currentScaleIndex > 0) {
scope.currentScaleIndex--;
}
};
scope.$watch('currentScaleName', function(newScaleName, oldScaleName){
if (newScaleName !== oldScaleName) {
scope.currentScale = Timeline.ZOOM_CONFIGURATIONS[scope.currentScaleName].scale;
scope.timeline.scale = scope.currentScale;
scope.currentScaleIndex = Timeline.ZOOM_SCALES.indexOf(scope.currentScaleName);
scope.slider.slider('value', scope.currentScaleIndex + 1);
scope.timeline.zoom(scope.currentScaleIndex); // TODO replace event-driven adaption by bindings
}
});
scope.$watch('currentOutlineLevel', function(outlineLevel, formerLevel) {
if (outlineLevel !== formerLevel) {
scope.timeline.expansionIndex = Timeline.OUTLINE_LEVELS.indexOf(outlineLevel);
scope.timeline.expandToOutlineLevel(outlineLevel); // TODO replace event-driven adaption by bindings
}
});
}
};
}]);

@ -197,8 +197,6 @@ openprojectApp.service('TimelineLoaderService', ['$q', 'FilterQueryStringBuilder
var DataEnhancer = function (timeline) {
this.timeline = timeline;

@ -27,10 +27,10 @@ See doc/COPYRIGHT.rdoc for more details.
++#%>
<div id="{{getTimelineContainerElementId()}}">
<%= render 'toolbar' %>
<timeline-container/>
</div>
<timeline-container>
<timeline-toolbar></timeline-toolbar>
<timeline-table-container/>
</timeline-container>
<% unless User.current.impaired? %>
<%# TODO: Require autocompleter inside select_boxes.js

Loading…
Cancel
Save