Merge pull request #424 from opf/feature/rails3_sortable_timelines_columns

pull/433/head
Hagen Schink 11 years ago
commit 637ddcab47
  1. 2
      app/assets/javascripts/timelines.js
  2. 60
      app/assets/javascripts/timelines_autocompleter.js
  3. 6
      app/assets/javascripts/timelines_select_boxes.js
  4. 2
      app/assets/stylesheets/timelines.css
  5. 9
      app/helpers/timelines_helper.rb
  6. 6
      app/models/timeline.rb
  7. 22
      app/views/timelines/_general.html.erb
  8. 1
      doc/CHANGELOG.md
  9. 15
      features/step_definitions/timelines_then_steps.rb
  10. 21
      features/step_definitions/timelines_when_steps.rb
  11. 13
      features/timelines/timeline_view.feature

@ -4079,7 +4079,7 @@ Timeline = {
rebuildTree: function() { rebuildTree: function() {
var where = this.getUiRoot().find('.tl-left-main'); var where = this.getUiRoot().find('.tl-left-main');
var tree = this.getLefthandTree(); var tree = this.getLefthandTree();
var table = jQuery('<table></table>'); var table = jQuery('<table class="tl-main-table"></table>');
var body = jQuery('<tbody></tbody>'); var body = jQuery('<tbody></tbody>');
var head = jQuery('<thead></thead>'); var head = jQuery('<thead></thead>');
var row, cell, link, span, text; var row, cell, link, span, text;

@ -33,34 +33,41 @@
if (!(this.element.attr("data-ajaxURL") === "" || this.element.attr("data-ajaxURL") === null || this.element.attr("data-ajaxURL") === undefined)) { if (!(this.element.attr("data-ajaxURL") === "" || this.element.attr("data-ajaxURL") === null || this.element.attr("data-ajaxURL") === undefined)) {
this.opts.ajax.url = this.element.attr("data-ajaxURL"); this.opts.ajax.url = this.element.attr("data-ajaxURL");
} }
if (!($(this.element).attr("data-values") === "" || $(this.element).attr("data-values") === null || $(this.element).attr("data-values") === undefined)) {
this.opts.data.results = JSON.parse($(this.element).attr('data-values'));
delete this.opts.ajax;
}
}, },
setupInput: function () { setupInput: function () {
var attrs_to_copy = {}, currentName, select2id, values = []; var attrs_to_copy = {}, currentName, select2id, values = [];
$("input[name='" + $(this.element).attr("name")+"']").remove(); if ($(this.element).is("input")) {
this.fakeInput = $(this.element);
} else {
$("input[name='" + $(this.element).attr("name")+"']").remove();
for(var i = 0; i < $(this.element).get(0).attributes.length; i++) { for(var i = 0; i < $(this.element).get(0).attributes.length; i++) {
currentName = $(this.element).get(0).attributes[i].name; currentName = $(this.element).get(0).attributes[i].name;
if(currentName.indexOf("data-") === 0 || $.inArray(currentName, this.opts.allowedAttributes) !== -1) { //only ones starting with data- if(currentName.indexOf("data-") === 0 || $.inArray(currentName, this.opts.allowedAttributes) !== -1) { //only ones starting with data-
attrs_to_copy[currentName] = $(this.element).attr(currentName); attrs_to_copy[currentName] = $(this.element).attr(currentName);
}
} }
}
select2id = $(this.element).attr("id"); select2id = $(this.element).attr("id");
this.fakeInput = $(this.element).after("<input type='hidden' id='" + select2id + "'></input>").siblings(":input#" + select2id); this.fakeInput = $(this.element).after("<input type='hidden' id='" + select2id + "'></input>").siblings(":input#" + select2id);
this.fakeInput.attr(attrs_to_copy); this.fakeInput.attr(attrs_to_copy);
if (!($(this.element).attr("data-selected") === "" || $(this.element).attr("data-selected") === null || $(this.element).attr("data-selected") === undefined)) { if (!($(this.element).attr("data-selected") === "" || $(this.element).attr("data-selected") === null || $(this.element).attr("data-selected") === undefined)) {
JSON.parse($(this.element).attr('data-selected')).each(function (elem) { JSON.parse($(this.element).attr('data-selected')).each(function (elem) {
values.push(elem[1]); values.push(elem[1]);
}); });
this.fakeInput.val(values); this.fakeInput.val(values);
}
$(this.element).remove();
} }
}, },
initSelect2: function () { initSelect2: function () {
$(this.element).remove();
$(this.fakeInput).select2(this.opts); $(this.fakeInput).select2(this.opts);
if (this.opts.sortable) { if (this.opts.sortable) {
@ -85,10 +92,11 @@
$(this).each(function () { $(this).each(function () {
autocompleter = new TimelinesAutocompleter($(this), args); autocompleter = new TimelinesAutocompleter($(this), args);
}); });
} };
$.fn.timelinesAutocomplete.defaults = { $.fn.timelinesAutocomplete.defaults = {
multiple: true, multiple: true,
data: {},
allowedAttributes: ["title", "placeholder", "id", "name"], allowedAttributes: ["title", "placeholder", "id", "name"],
minimumInputLength: 0, minimumInputLength: 0,
ajax: { ajax: {
@ -147,8 +155,22 @@
JSON.parse($(element).attr('data-selected')).each(function (elem) { JSON.parse($(element).attr('data-selected')).each(function (elem) {
data.push({id: elem[1], name: elem[0]}); data.push({id: elem[1], name: elem[0]});
}); });
} else if (element.is("input") && !(element.attr("data-values") === "" || element.attr("data-values") === null || element.attr("data-values") === undefined)) {
var possible = JSON.parse(element.attr('data-values'));
var vals = element.val().split(",");
var byID = {};
var i;
for (i = 0; i < possible.length; i += 1) {
byID[possible[i].id] = possible[i];
}
for (i = 0; i < vals.length; i += 1) {
data.push(byID[vals[i]]);
}
} }
return callback(data);
callback(data);
} }
} };
}(jQuery)); }(jQuery));

@ -15,7 +15,6 @@ jQuery(document).ready(function($) {
[ [
$("#reporting_reported_project_status_id"), $("#reporting_reported_project_status_id"),
$("#timeline_select"), $("#timeline_select"),
$("#timeline_options_columns"),
$("#timeline_options_initial_outline_expansion"), $("#timeline_options_initial_outline_expansion"),
$("#timeline_options_zoom_factor"), $("#timeline_options_zoom_factor"),
$("#timeline_options_compare_to_relative_unit"), $("#timeline_options_compare_to_relative_unit"),
@ -44,6 +43,11 @@ jQuery(document).ready(function($) {
$(item).timelinesAutocomplete({ ajax: {null_element: {id: -1, name: I18n.t("js.timelines.filter.none")}} }) $(item).timelinesAutocomplete({ ajax: {null_element: {id: -1, name: I18n.t("js.timelines.filter.none")}} })
}); });
var item = $("#timeline_options_columns_");
item.timelinesAutocomplete({
sortable: true
});
[ [
$("#reporting_reporting_to_project_id"), $("#reporting_reporting_to_project_id"),
$("#project_association_select_project_b_id") $("#project_association_select_project_b_id")

@ -50,7 +50,7 @@ li.select2-result.select2-visible-selected-parent {
margin-bottom: 8px; margin-bottom: 8px;
} }
#s2id_timeline_options_grouping_one_selection .select2-search-choice { #content .ui-sortable .select2-search-choice {
cursor: move; cursor: move;
} }

@ -270,6 +270,15 @@ module TimelinesHelper
collection collection
end end
def internationalized_columns_select_object(collection)
collection.map do |t|
{
:name => l("timelines.filter.column." + t),
:id => t
}
end
end
def internationalized_columns_select(collection) def internationalized_columns_select(collection)
collection.map do |t| collection.map do |t|
[l("timelines.filter.column." + t), t] [l("timelines.filter.column." + t), t]

@ -167,18 +167,18 @@ class Timeline < ActiveRecord::Base
# that are reporting into the project that this timeline is # that are reporting into the project that this timeline is
# referencing. # referencing.
PlanningElementType.find(:all, :order => :name) Type.find(:all, :order => :name)
end end
def selected_planning_element_types def selected_planning_element_types
resolve_with_none_element(:planning_element_types) do |ary| resolve_with_none_element(:planning_element_types) do |ary|
PlanningElementType.find(ary) Type.find(ary)
end end
end end
def selected_planning_element_time_types def selected_planning_element_time_types
resolve_with_none_element(:planning_element_time_types) do |ary| resolve_with_none_element(:planning_element_time_types) do |ary|
PlanningElementType.find(ary) Type.find(ary)
end end
end end

@ -87,13 +87,21 @@ See doc/COPYRIGHT.rdoc for more details.
<%= label_tag 'timeline_options_columns', <%= label_tag 'timeline_options_columns',
l("timelines.filter.columns") %> l("timelines.filter.columns") %>
<%= select("timeline[options]", <% if User.current.impaired? %>
:columns, <%= select("timeline[options]",
internationalized_columns_select(timeline.available_columns), :columns,
{:selected => timeline.selected_columns}, internationalized_columns_select(timeline.available_columns),
{:multiple => true, {:selected => timeline.selected_columns},
:size => 12}) %> {:multiple => true,
:size => 12}) %>
<% else %>
<%= hidden_field_tag("timeline[options][columns][]",
timeline.selected_columns.join(","),
{
:"data-values" => internationalized_columns_select_object(timeline.available_columns).to_json
}
) %>
<% end %>
</p> </p>
<p class="tl-form-overflow"> <p class="tl-form-overflow">

@ -12,6 +12,7 @@ See doc/COPYRIGHT.rdoc for more details.
# Changelog # Changelog
* `#1913` [Timelines] Enable drag&drop for select2 items in order to rearrange the order of the columns
* `#2019` Migrate auto completes controller tests * `#2019` Migrate auto completes controller tests
## 3.0.0pre16 ## 3.0.0pre16

@ -16,6 +16,21 @@ Then /^I should see a modal window with selector "(.*?)"$/ do |selector|
dialog["class"].include?("ui-dialog-content").should be_true dialog["class"].include?("ui-dialog-content").should be_true
end end
Then(/^I should see the column "(.*?)" before the column "(.*?)" in the timelines table$/) do |content1, content2|
steps %Q{
Then I should see the column "#{content1}" before the column "#{content2}" in ".tl-main-table"
}
end
Then(/^I should see the column "(.*?)" before the column "(.*?)" in "(.*?)"$/) do |content1, content2, table|
#Check that the things really exist and wait until the exist
steps %Q{
Then I should see "#{content1}" within "#{table}"
Then I should see "#{content2}" within "#{table}"
}
elements = find_lowest_containing_element content2, table
elements[-1].should have_xpath("preceding::th/descendant-or-self::*[text()='#{content1}']")
end
Then /^I should see a modal window$/ do Then /^I should see a modal window$/ do
steps 'Then I should see a modal window with selector "#modalDiv"' steps 'Then I should see a modal window with selector "#modalDiv"'
end end

@ -86,7 +86,28 @@ When (/^I set the second level grouping criteria to "(.*?)" for the timeline "(.
page.execute_script("jQuery('#timeline_options_grouping_two_selection').val('#{project_type.id}')") page.execute_script("jQuery('#timeline_options_grouping_two_selection').val('#{project_type.id}')")
page.execute_script("jQuery('#content form').submit()") page.execute_script("jQuery('#content form').submit()")
end end
When(/^I set the columns shown in the timeline to:$/) do |table|
timeline_name = @timeline_name
project_name = @project.name
steps %Q{
When I go to the edit page of the timeline "#{timeline_name}" of the project called "#{project_name}"
}
result = []
table.raw.each do |_perm|
perm = _perm.first
unless perm.blank?
result.push(perm)
end
end
results = result.join(",");
#we need to wait for our submit form to load ...
page.should have_selector("#timeline_options_columns_", :visible => false)
page.execute_script("jQuery('#timeline_options_columns_').val('#{results}')")
page.execute_script("jQuery('#content form').submit()")
end
When (/^I set the first level grouping criteria to:$/) do |table| When (/^I set the first level grouping criteria to:$/) do |table|
timeline_name = @timeline_name timeline_name = @timeline_name
project_name = @project.name project_name = @project.name

@ -47,6 +47,19 @@ Feature: Timeline View Tests
And I wait for timeline to load table And I wait for timeline to load table
Then the first table column should not take more than 25% of the space Then the first table column should not take more than 25% of the space
@javascript
Scenario: Select columns
Given I am working in the timeline "Testline" of the project called "ecookbook"
When there is a timeline "Testline" for project "ecookbook"
And I set the columns shown in the timeline to:
| start_date |
| type |
| end_date |
Then I should see the column "Start date" before the column "End date" in the timelines table
And I should see the column "Start date" before the column "Type" in the timelines table
And I should see the column "Type" before the column "End date" in the timelines table
@javascript @javascript
Scenario: switch timeline Scenario: switch timeline
When there is a timeline "Testline" for project "ecookbook" When there is a timeline "Testline" for project "ecookbook"

Loading…
Cancel
Save