From 55e399ab36e9b688a4bfbb7b90422fe33e9e14e7 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Wed, 15 May 2013 12:02:13 +0200 Subject: [PATCH] =?utf8?q?Pflichtenheftvorlagen=20einf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- SL/Controller/RequirementSpec.pm | 64 ++++++++++++++++++- SL/DB/RequirementSpec.pm | 48 +++++++++++--- js/requirement_spec.js | 22 +++++++ .../select_template_to_paste.html | 2 +- 4 files changed, 126 insertions(+), 10 deletions(-) diff --git a/SL/Controller/RequirementSpec.pm b/SL/Controller/RequirementSpec.pm index a90152608..689ef19a8 100644 --- a/SL/Controller/RequirementSpec.pm +++ b/SL/Controller/RequirementSpec.pm @@ -26,7 +26,7 @@ use SL::Template::LaTeX; use Rose::Object::MakeMethods::Generic ( scalar => [ qw(requirement_spec_item customers types statuses db_args flat_filter visible_item visible_section) ], - 'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects copy_source js) ], + 'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects copy_source js current_text_block_output_position) ], ); __PACKAGE__->run_before('setup'); @@ -218,6 +218,24 @@ sub action_select_template_to_paste { $self->render('requirement_spec/select_template_to_paste', { layout => 0 }, TEMPLATES => \@templates); } +sub action_paste_template { + my ($self, %params) = @_; + + my $template = SL::DB::RequirementSpec->new(id => $::form->{template_id})->load; + my %result = $self->requirement_spec->paste_template($template); + + return $self->js->error($self->requirement_spec->error)->render($self) if !%result; + + $self->render_pasted_text_block($_) for sort { $a->position <=> $b->position } @{ $result{text_blocks} }; + $self->render_pasted_section($_) for sort { $a->position <=> $b->position } @{ $result{sections} }; + + if (@{ $result{sections} } && (($::form->{current_content_type} || 'sections') eq 'sections') && !$::form->{current_content_id}) { + $self->render_first_pasted_section_as_list($result{sections}->[0]); + } + + $self->invalidate_version->render($self); +} + # # filters # @@ -263,6 +281,11 @@ sub init_js { $self->js(SL::ClientJS->new); } +sub init_current_text_block_output_position { + my ($self) = @_; + $self->current_text_block_output_position($::form->{current_content_type} !~ m/^(?:text-blocks|tb)-(front|back)/ ? -1 : $1 eq 'front' ? 0 : 1); +} + sub load_select_options { my ($self) = @_; @@ -414,4 +437,43 @@ sub invalidate_version { return $self->js->html('#requirement_spec_version', $html); } +sub render_pasted_text_block { + my ($self, $text_block, %params) = @_; + + if ($self->current_text_block_output_position == $text_block->output_position) { + my $html = $self->render('requirement_spec_text_block/_text_block', { output => 0 }, text_block => $text_block); + $self->js + ->appendTo($html, '#text-block-list') + ->hide('#text-block-list-empty'); + } + + my $node = $self->presenter->requirement_spec_text_block_jstree_data($text_block); + my $front_back = $text_block->output_position == 0 ? 'front' : 'back'; + $self->js + ->jstree->create_node('#tree', "#tb-${front_back}", 'last', $node) + ->jstree->open_node( '#tree', "#tb-${front_back}"); +} + +sub render_pasted_section { + my ($self, $item, $parent_id) = @_; + + my $node = $self->presenter->requirement_spec_item_jstree_data($item); + $self->js + ->jstree->create_node('#tree', $parent_id ? "#fb-${parent_id}" : '#sections', 'last', $node) + ->jstree->open_node( '#tree', $parent_id ? "#fb-${parent_id}" : '#sections'); + + $self->render_pasted_section($_, $item->id) for @{ $item->children_sorted }; +} + +sub render_first_pasted_section_as_list { + my ($self, $section, %params) = @_; + + my $html = $self->render('requirement_spec_item/_section', { output => 0 }, requirement_spec_item => $section); + $self->js + ->html('#column-content', $html) + ->val( '#current_content_type', $section->item_type) + ->val( '#current_content_id', $section->id) + ->jstree->select_node('#tree', '#fb-' . $section->id); +} + 1; diff --git a/SL/DB/RequirementSpec.pm b/SL/DB/RequirementSpec.pm index f7fd2d525..abeac1c0d 100644 --- a/SL/DB/RequirementSpec.pm +++ b/SL/DB/RequirementSpec.pm @@ -111,16 +111,35 @@ sub _create_copy { } sub _copy_from { - my ($self, $source, %attributes) = @_; + my ($self, $params, %attributes) = @_; + + my $source = $params->{source}; croak "Missing parameter 'source'" unless $source; # Copy attributes. - $self->assign_attributes(map({ ($_ => $source->$_) } qw(type_id status_id customer_id project_id title hourly_rate net_sum previous_section_number previous_fb_number is_template)), - %attributes); + if (!$params->{paste_template}) { + $self->assign_attributes(map({ ($_ => $source->$_) } qw(type_id status_id customer_id project_id title hourly_rate net_sum previous_section_number previous_fb_number is_template)), + %attributes); + } + + my %paste_template_result; # Clone text blocks. - $self->text_blocks(map { Rose::DB::Object::Helpers::clone_and_reset($_) } @{ $source->text_blocks }); + my $clone_text_block = sub { + my ($text_block) = @_; + my $cloned = Rose::DB::Object::Helpers::clone_and_reset($text_block); + $cloned->position(undef); + return $cloned; + }; + + $paste_template_result{text_blocks} = [ map { $clone_text_block->($_) } @{ $source->text_blocks_sorted } ]; + + if (!$params->{paste_template}) { + $self->text_blocks($paste_template_result{text_blocks}); + } else { + $self->add_text_blocks($paste_template_result{text_blocks}); + } # Save new object -- we need its ID for the items. $self->save; @@ -133,6 +152,7 @@ sub _copy_from { my ($item) = @_; my $cloned = Rose::DB::Object::Helpers::clone_and_reset($item); $cloned->requirement_spec_id($self->id); + $cloned->position(undef); $cloned->children(map { $clone_item->($_) } @{ $item->children }); $id_to_clone{ $item->id } = $cloned; @@ -140,7 +160,13 @@ sub _copy_from { return $cloned; }; - $self->items(map { $clone_item->($_) } @{ $source->sections }); + $paste_template_result{sections} = [ map { $clone_item->($_) } @{ $source->sections_sorted } ]; + + if (!$params->{paste_template}) { + $self->items($paste_template_result{sections}); + } else { + $self->add_items($paste_template_result{sections}); + } # Save the items -- need to do that before setting dependencies. $self->save; @@ -151,15 +177,21 @@ sub _copy_from { $id_to_clone{ $item->id }->update_attributes(dependencies => [ map { $id_to_clone{$_->id} } @{ $item->dependencies } ]); } - $self->update_attributes(%attributes); + $self->update_attributes(%attributes) unless $params->{paste_template}; - return $self; + return %paste_template_result; } sub copy_from { my ($self, $source, %attributes) = @_; - $self->db->with_transaction(sub { $self->_copy_from($source, %attributes); }); + $self->db->with_transaction(sub { $self->_copy_from({ source => $source, paste_template => 0 }, %attributes); }); +} + +sub paste_template { + my ($self, $template) = @_; + + $self->db->with_transaction(sub { $self->_copy_from({ source => $template, paste_template => 1 }); }); } sub highest_version { diff --git a/js/requirement_spec.js b/js/requirement_spec.js index ae79443e3..effcf3d86 100644 --- a/js/requirement_spec.js +++ b/js/requirement_spec.js @@ -269,10 +269,32 @@ ns.item_popup_menu_hidden = function(opt) { return ns.handle_item_popup_menu_markings(opt, false); }; +// ------------------------------------------------------------------------- +// ------------------------------- templates ------------------------------- +// ------------------------------------------------------------------------- + ns.paste_template = function(key, opt, other_data) { open_jqm_window({ url: 'controller.pl?action=RequirementSpec/select_template_to_paste' }); }; +ns.paste_selected_template = function(template_id) { + $('#jqm_popup_dialog').jqmClose(); + + var data = { + action: "RequirementSpec/paste_template", + id: $('#requirement_spec_id').val(), + template_id: template_id, + current_content_type: $('#current_content_type').val(), + current_content_id: $('#current_content_id').val() + }; + + // console.log("I would normally POST the following now:"); + // console.log(data); + $.post("controller.pl", data, kivi.eval_json_result); + + return true; +}; + // ------------------------------------------------------------------------- // -------------------------- time/cost estimate --------------------------- // ------------------------------------------------------------------------- diff --git a/templates/webpages/requirement_spec/select_template_to_paste.html b/templates/webpages/requirement_spec/select_template_to_paste.html index ff2eea7a3..f73441b4f 100644 --- a/templates/webpages/requirement_spec/select_template_to_paste.html +++ b/templates/webpages/requirement_spec/select_template_to_paste.html @@ -37,7 +37,7 @@ [-] - [%- LxERP.t8("Paste template") %] + [%- LxERP.t8("Paste template") %] [%- HTML.escape(template.title) %] [% template.mtime ? template.mtime.to_kivitendo(precision='minute') : template.itime.to_kivitendo(precision='minute') %] -- 2.20.1