From c1569bc195865fa5c25c6945bbad78c872fa2046 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Fri, 8 Mar 2013 15:32:32 +0100 Subject: [PATCH] Pflichtenhefte bearbeiten --- SL/Controller/RequirementSpec.pm | 17 ++- SL/Controller/RequirementSpecItem.pm | 20 +++- SL/DB/RequirementSpec.pm | 6 + SL/Presenter.pm | 1 + SL/Presenter/RequirementSpec.pm | 17 +-- SL/Presenter/RequirementSpecItem.pm | 32 +++++ css/requirement_spec.css | 21 +++- .../webpages/requirement_spec/_version.html | 9 ++ templates/webpages/requirement_spec/show.html | 112 ++++++++++++++++++ templates/webpages/requirement_spec/tree.html | 87 ++++++-------- .../requirement_spec_item/_section_form.html | 39 +++--- .../_section_header.html | 12 ++ .../_single_section.html | 90 ++++++++++++++ .../_single_subitem.html | 48 ++++++++ 14 files changed, 422 insertions(+), 89 deletions(-) create mode 100644 SL/Presenter/RequirementSpecItem.pm create mode 100644 templates/webpages/requirement_spec/_version.html create mode 100644 templates/webpages/requirement_spec/show.html create mode 100644 templates/webpages/requirement_spec_item/_section_header.html create mode 100644 templates/webpages/requirement_spec_item/_single_section.html create mode 100644 templates/webpages/requirement_spec_item/_single_subitem.html diff --git a/SL/Controller/RequirementSpec.pm b/SL/Controller/RequirementSpec.pm index d7d897867..8aac6dfa8 100644 --- a/SL/Controller/RequirementSpec.pm +++ b/SL/Controller/RequirementSpec.pm @@ -19,11 +19,11 @@ use SL::Locale::String; use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(requirement_spec customers projects types statuses db_args flat_filter is_template) ], + scalar => [ qw(requirement_spec requirement_spec_item customers projects types statuses db_args flat_filter is_template) ], ); __PACKAGE__->run_before('setup'); -__PACKAGE__->run_before('load_requirement_spec', only => [ qw( edit update destroy tree) ]); +__PACKAGE__->run_before('load_requirement_spec', only => [ qw( edit update show destroy tree) ]); __PACKAGE__->run_before('load_select_options', only => [ qw(new edit create update list) ]); __PACKAGE__->run_before('load_search_select_options', only => [ qw( list) ]); @@ -77,6 +77,15 @@ sub action_edit { $self->render('requirement_spec/form', title => t8('Edit requirement spec')); } +sub action_show { + my ($self) = @_; + + my $item = $::form->{requirement_spec_item_id} ? SL::DB::RequirementSpecItem->new(id => $::form->{requirement_spec_item_id})->load : @{ $self->requirement_spec->sections }[0]; + $self->requirement_spec_item($item); + + $self->render('requirement_spec/show', title => t8('Show requirement spec')); +} + sub action_create { my ($self) = @_; @@ -122,8 +131,8 @@ sub setup { my ($self) = @_; $::auth->assert('config'); - $::request->{layout}->use_stylesheet("${_}.css") for qw(requirement_spec yaml/core/base.min); - $::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree requirement_spec); + $::request->{layout}->use_stylesheet("${_}.css") for qw(jquery.contextMenu requirement_spec); + $::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree jquery/jquery.contextMenu requirement_spec); $self->is_template($::form->{is_template} ? 1 : 0); return 1; diff --git a/SL/Controller/RequirementSpecItem.pm b/SL/Controller/RequirementSpecItem.pm index 6ddf3a63a..9dfdad042 100644 --- a/SL/Controller/RequirementSpecItem.pm +++ b/SL/Controller/RequirementSpecItem.pm @@ -18,7 +18,7 @@ use Rose::Object::MakeMethods::Generic ); # __PACKAGE__->run_before('load_requirement_spec'); -__PACKAGE__->run_before('load_requirement_spec_item', only => [qw(dragged_and_dropped)]); +__PACKAGE__->run_before('load_requirement_spec_item', only => [qw(dragged_and_dropped edit_section update_section)]); # # actions @@ -64,6 +64,24 @@ sub action_dragged_and_dropped { $self->render(\'', { type => 'json' }); } +sub action_edit_section { + my ($self, %params) = @_; + $self->render('requirement_spec_item/_section_form', { layout => 0 }); +} + +sub action_update_section { + my ($self, %params) = @_; + + $self->item->update_attributes(title => $::form->{title}, description => $::form->{description}); + + my $result = { + id => $self->item->id, + header_html => $self->render('requirement_spec_item/_section_header', { layout => 0, output => 0 }, requirement_spec_item => $self->item), + node_name => join(' ', map { $_ || '' } ($self->item->fb_number, $self->item->title)), + }; + $self->render(\to_json($result), { type => 'json' }); +} + # # filters # diff --git a/SL/DB/RequirementSpec.pm b/SL/DB/RequirementSpec.pm index 2c2725e50..3a3f4ccf4 100644 --- a/SL/DB/RequirementSpec.pm +++ b/SL/DB/RequirementSpec.pm @@ -57,4 +57,10 @@ sub sections { return [ sort { $a->position <=> $b->position } grep { !$_->parent_id } @{ $self->items } ]; } +sub displayable_name { + my ($self) = @_; + + return sprintf('%s: "%s"', $self->type->description, $self->title); +} + 1; diff --git a/SL/Presenter.pm b/SL/Presenter.pm index f0a0259a2..67b37df5c 100644 --- a/SL/Presenter.pm +++ b/SL/Presenter.pm @@ -16,6 +16,7 @@ use SL::Presenter::Part; use SL::Presenter::Project; use SL::Presenter::Record; use SL::Presenter::RequirementSpec; +use SL::Presenter::RequirementSpecItem; use SL::Presenter::SepaExport; use SL::Presenter::Text; use SL::Presenter::Tag; diff --git a/SL/Presenter/RequirementSpec.pm b/SL/Presenter/RequirementSpec.pm index fe9df960c..b8a202ddb 100644 --- a/SL/Presenter/RequirementSpec.pm +++ b/SL/Presenter/RequirementSpec.pm @@ -5,8 +5,7 @@ use strict; use parent qw(Exporter); use Exporter qw(import); -our @EXPORT = qw(requirement_spec_text_block_jstree_data - requirement_spec_item_jstree_data); +our @EXPORT = qw(requirement_spec_text_block_jstree_data); use Carp; @@ -22,18 +21,4 @@ sub requirement_spec_text_block_jstree_data { }; } -sub requirement_spec_item_jstree_data { - my ($self, $item, %params) = @_; - - my @children = map { $self->requirement_spec_item_jstree_data($_, %params) } @{ $item->sorted_children }; - my $type = !$item->parent_id ? 'section' : 'functionblock'; - - return { - data => join(' ', map { $_ || '' } ($item->fb_number, $item->title)), - metadata => { id => $item->id, type => $type }, - attr => { id => "fb-" . $item->id, href => $params{href} || '#' }, - children => \@children, - }; -} - 1; diff --git a/SL/Presenter/RequirementSpecItem.pm b/SL/Presenter/RequirementSpecItem.pm new file mode 100644 index 000000000..cdf05cf36 --- /dev/null +++ b/SL/Presenter/RequirementSpecItem.pm @@ -0,0 +1,32 @@ +package SL::Presenter::RequirementSpecItem; + +use strict; + +use parent qw(Exporter); + +use Exporter qw(import); +our @EXPORT = qw(requirement_spec_item_jstree_data requirement_spec_item_dependency_list); + +use Carp; + +sub requirement_spec_item_jstree_data { + my ($self, $item, %params) = @_; + + my @children = map { $self->requirement_spec_item_jstree_data($_, %params) } @{ $item->sorted_children }; + my $type = !$item->parent_id ? 'section' : 'functionblock'; + + return { + data => join(' ', map { $_ || '' } ($item->fb_number, $item->title)), + metadata => { id => $item->id, type => $type }, + attr => { id => "fb-" . $item->id, href => $params{href} || '#' }, + children => \@children, + }; +} + +sub requirement_spec_item_dependency_list { + my ($self, $item) = @_; + + $::locale->language_join([ map { $_->fb_number } @{ $item->dependencies } ]); +} + +1; diff --git a/css/requirement_spec.css b/css/requirement_spec.css index 08b6d2be9..82b895e41 100644 --- a/css/requirement_spec.css +++ b/css/requirement_spec.css @@ -3,6 +3,25 @@ table.rs_input_field input, table.rs_input_field select { width: 300px; } +#column-container { + width: 100%; + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; +} + +#tree-column { + float: left; + width: 25%; + border-right: 1px solid black; +} + #content-column { - margin-left: 10px; + float: left; + padding-left: 10px; +} + +.section-empty-description { + color: #bbb; } diff --git a/templates/webpages/requirement_spec/_version.html b/templates/webpages/requirement_spec/_version.html new file mode 100644 index 000000000..8a73f54ad --- /dev/null +++ b/templates/webpages/requirement_spec/_version.html @@ -0,0 +1,9 @@ +[%- USE L -%][%- USE LxERP -%][%- USE HTML -%] +[% L.stuff %] +[% LxERP.t8("Current version") %]: +[% IF !requirement_spec.version_id %] + [% LxERP.t8("Working copy without version") %] +[% ELSE %] + [% LxERP.t8("Version") %] [% HTML.escape(requirement_spec.version.version_number) %] + [% LxERP.t8("dated") %] [% HTML.escape(requirement_spec.version.itime.displayable_date) %] +[%- END -%] diff --git a/templates/webpages/requirement_spec/show.html b/templates/webpages/requirement_spec/show.html new file mode 100644 index 000000000..f6c15c2d2 --- /dev/null +++ b/templates/webpages/requirement_spec/show.html @@ -0,0 +1,112 @@ +[%- USE JSON -%][%- USE HTML %][%- USE L %][%- USE LxERP %][%- USE P -%] + +

[%- HTML.escape(SELF.requirement_spec.displayable_name('format', 'with_customer')) %] + [% LxERP.t8("for") %] + [% HTML.escape(SELF.requirement_spec.customer.displayable_name) -%] +

+ +[%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id) -%] + +
+ [%- INCLUDE 'requirement_spec/_version.html' requirement_spec=SELF.requirement_spec -%] +
+ +
+
+
+
+ [% L.button_tag("new_section_form()", LxERP.t8("New section"), id="new-section-button") %] +
+ +
+ +
+
+ +
+
+ +
+ [%- IF SELF.requirement_spec_item && SELF.requirement_spec_item.id -%] + [%- INCLUDE 'requirement_spec_item/_single_section.html' requirement_spec_item=SELF.requirement_spec_item -%] + [%- ELSE -%] + no section + [%#- render :partial => 'requirement_spec_items/no_section' -%] + [%- END -%] +
+
+
+
+ + diff --git a/templates/webpages/requirement_spec/tree.html b/templates/webpages/requirement_spec/tree.html index 85ac0e35e..2c5b306ea 100644 --- a/templates/webpages/requirement_spec/tree.html +++ b/templates/webpages/requirement_spec/tree.html @@ -2,58 +2,55 @@ [%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id) -%] -
-
+
+
[% L.button_tag("new_section_form()", LxERP.t8("New section"), id="new-section-button") %]
-
-
-
-

There's beauty in the breakdown. 0

-

There's beauty in the breakdown. 1

-

There's beauty in the breakdown. 2

-

There's beauty in the breakdown. 3

-

There's beauty in the breakdown. 4

-

There's beauty in the breakdown. 5

-

There's beauty in the breakdown. 6

-

There's beauty in the breakdown. 7

-

There's beauty in the breakdown. 8

-

There's beauty in the breakdown. 9

-

There's beauty in the breakdown. 10

-

There's beauty in the breakdown. 11

-

There's beauty in the breakdown. 12

-

There's beauty in the breakdown. 13

-

There's beauty in the breakdown. 14

-

There's beauty in the breakdown. 15

-

There's beauty in the breakdown. 16

-

There's beauty in the breakdown. 17

-

There's beauty in the breakdown. 18

-

There's beauty in the breakdown. 19

-

There's beauty in the breakdown. 20

-

There's beauty in the breakdown. 21

-

There's beauty in the breakdown. 22

- - - - - - - - - - - - - -
+
+

There's beauty in the breakdown. 0

+

There's beauty in the breakdown. 1

+

There's beauty in the breakdown. 2

+

There's beauty in the breakdown. 3

+

There's beauty in the breakdown. 4

+

There's beauty in the breakdown. 5

+

There's beauty in the breakdown. 6

+

There's beauty in the breakdown. 7

+

There's beauty in the breakdown. 8

+

There's beauty in the breakdown. 9

+

There's beauty in the breakdown. 10

+

There's beauty in the breakdown. 11

+

There's beauty in the breakdown. 12

+

There's beauty in the breakdown. 13

+

There's beauty in the breakdown. 14

+

There's beauty in the breakdown. 15

+

There's beauty in the breakdown. 16

+

There's beauty in the breakdown. 17

+

There's beauty in the breakdown. 18

+

There's beauty in the breakdown. 19

+

There's beauty in the breakdown. 20

+

There's beauty in the breakdown. 21

+

There's beauty in the breakdown. 22

+ + + + + + + + + + + + +
@@ -121,11 +118,5 @@ }) .bind("move_node.jstree", node_moved); }); - - $(document).ajaxSend(function() { - $('#spinner').show(); - }).ajaxStop(function() { - $('#spinner').hide(); - }); --> diff --git a/templates/webpages/requirement_spec_item/_section_form.html b/templates/webpages/requirement_spec_item/_section_form.html index 12f8e6533..c2ae0da8b 100644 --- a/templates/webpages/requirement_spec_item/_section_form.html +++ b/templates/webpages/requirement_spec_item/_section_form.html @@ -1,24 +1,25 @@ [%- USE HTML %][%- USE L %][%- USE LxERP %] -[%- SET id_base="section-form-" _ HTML.escape(id) %] -[%- IF title %] -
[%- HTML.escape(title) %]
-[%- END -%] +[%- SET id_base="section-form" %] +
+

[%- LxERP.t8("Edit section #1", SELF.item.fb_number) %]

-
- [% L.hidden_tag("requirment_spec_id", SELF.item.requirement_spec_id, id=(id_base _ "-requirement-spec-id")) %] + + [% L.hidden_tag("requirement_spec_id", SELF.item.requirement_spec_id, id=(id_base _ "-requirement-spec-id")) %] + [% L.hidden_tag("id", SELF.item.id, id=(id_base _ "-requirement-spec-item-id")) %] -

- [%- LxERP.t8("Title") %]:
- [% L.input_tag("title", SELF.item.title, id=(id_base _ "-title")) %] -

+

+ [%- LxERP.t8("Title") %]:
+ [% L.input_tag("title", SELF.item.title, id=(id_base _ "-title")) %] +

-

- [%- LxERP.t8("Description") %]:
- [% L.textarea_tag("description", SELF.item.description, id=(id_base _ "-title"), rows=8, cols=80) %] -

+

+ [%- LxERP.t8("Description") %]:
+ [% L.textarea_tag("description", SELF.item.description, id=(id_base _ "-description"), rows=8, cols=80) %] +

-

- [% L.button_tag("submit_section_form('" _ HTML.escape(id) _ "')", LxERP.t8("Save")) %] - [% L.button_tag("cancel_section_form('" _ HTML.escape(id) _ "')", LxERP.t8("Cancel")) %] -

-
+

+ [% L.button_tag("submit_section_form()", LxERP.t8("Save")) %] + [% LxERP.t8("Cancel") %] +

+ +
diff --git a/templates/webpages/requirement_spec_item/_section_header.html b/templates/webpages/requirement_spec_item/_section_header.html new file mode 100644 index 000000000..60c9debc7 --- /dev/null +++ b/templates/webpages/requirement_spec_item/_section_header.html @@ -0,0 +1,12 @@ +[%- USE HTML -%][%- USE L -%][%- USE LxERP -%] +

+ [%- HTML.escape(requirement_spec_item.fb_number) %]: [% HTML.escape(requirement_spec_item.title) -%] +

+ +[% IF requirement_spec_item.description %] +
+ [%- L.simple_format(requirement_spec_item.description) -%] +
+[%- ELSE %] +
[%- LxERP.t8("No description has been entered yet.") %]
+[%- END %] diff --git a/templates/webpages/requirement_spec_item/_single_section.html b/templates/webpages/requirement_spec_item/_single_section.html new file mode 100644 index 000000000..dc499336c --- /dev/null +++ b/templates/webpages/requirement_spec_item/_single_section.html @@ -0,0 +1,90 @@ +[%- USE HTML -%][%- USE LxERP -%][%- USE L -%] +
+ [%- INCLUDE 'requirement_spec_item/_section_header.html' %] +
+ +[%- L.hidden_tag('active_section_id', requirement_spec_item.id) -%] + +
    + [%- FOREACH subitem = requirement_spec_item.children -%] + [%- INCLUDE 'requirement_spec_item/_single_subitem.html' requirement_spec_item=subitem -%] + [%- END -%] +
+ +
+
+ + + diff --git a/templates/webpages/requirement_spec_item/_single_subitem.html b/templates/webpages/requirement_spec_item/_single_subitem.html new file mode 100644 index 000000000..c2af84c08 --- /dev/null +++ b/templates/webpages/requirement_spec_item/_single_subitem.html @@ -0,0 +1,48 @@ +[%- USE HTML -%][%- USE LxERP -%][%- USE P -%] +
  • + +
    + + [%#- IF !@requirement_spec.project.nil? -%] + [%#- link_to image_tag("chronometer.png"), account_time_requirement_spec_requirement_spec_item_path(requirement_spec_item.requirement_spec, requirement_spec_item) -%] + [%#- END -%] + [%#- link_to_new_sub(requirement_spec_item.parent) -%] + [%#- link_to_remote image_tag("new_subsub.png"), + :url => new_requirement_spec_requirement_spec_item_url(requirement_spec_item.requirement_spec, :requirement_spec_item_id => requirement_spec_item.id), + :method => :get, + :condition => "check_for_editbox()", + :update => "new_subsubitem_form_#{requirement_spec_item.id}" -%] + + [%- HTML.escape(requirement_spec_item.fb_number) -%] + [%- HTML.escape(requirement_spec_item.description) -%] + +
    + + [%- IF requirement_spec_item.children.size -%] + [%- FOREACH subsubitem = requirement_spec_item.children -%] + [%#- render :partial => "requirement_spec_items/single_subsubitem", :locals => {:requirement_spec_item => subsubitem} -%] + [%- END -%] + [%- END -%] +
    + +
    + +
    + [%- IF requirement_spec_item.dependencies.size -%] + + [%- LxERP.t8("Dependencies") -%]: [%- P.requirement_spec_item_dependency_list(requirement_spec_item.dependencies) -%] +
    + [%- END -%] + + [%- LxERP.t8("Complexity") -%]: [%- requirement_spec_item.requirement_spec_complexity.description IF requirement_spec_item.requirement_spec_complexity -%] +   |   + [%- LxERP.t8("Risk") -%]: [%- requirement_spec_item.requirement_spec_risk.description IF requirement_spec_item.requirement_spec_risk -%] +   |   + [%- LxERP.t8("Effort") -%]: [%#- render :partial => 'requirement_spec_items/time_estimation_item', :locals => { :item => requirement_spec_item } -%] + + +
    +
    +
  • -- 2.20.1