Pflichtenhefte: Auflisten von Abschnitten
authorMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 8 Mar 2013 10:13:46 +0000 (11:13 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Tue, 1 Apr 2014 11:02:25 +0000 (13:02 +0200)
17 files changed:
SL/Controller/RequirementSpecItem.pm
SL/Controller/RequirementSpecTextBlock.pm
SL/DB/RequirementSpecItem.pm
SL/Presenter/RequirementSpecItem.pm
css/requirement_spec.css
js/requirement_spec.js
locale/de/all
templates/webpages/requirement_spec/show.html
templates/webpages/requirement_spec_item/_function_block.html [new file with mode: 0644]
templates/webpages/requirement_spec_item/_function_block_content_bottom.html [new file with mode: 0644]
templates/webpages/requirement_spec_item/_function_block_content_top.html [new file with mode: 0644]
templates/webpages/requirement_spec_item/_no_section.html [new file with mode: 0644]
templates/webpages/requirement_spec_item/_section.html [new file with mode: 0644]
templates/webpages/requirement_spec_item/_section_header.html
templates/webpages/requirement_spec_item/_single_section.html [deleted file]
templates/webpages/requirement_spec_item/_single_subitem.html [deleted file]
templates/webpages/requirement_spec_item/_sub_function_block.html [new file with mode: 0644]

index 9dfdad0..c4f6f6d 100644 (file)
@@ -14,7 +14,7 @@ use SL::Locale::String;
 
 use Rose::Object::MakeMethods::Generic
 (
scalar => [ qw(requirement_spec item) ],
 scalar => [ qw(requirement_spec item visible_item visible_section) ],
 );
 
 # __PACKAGE__->run_before('load_requirement_spec');
@@ -24,6 +24,29 @@ __PACKAGE__->run_before('load_requirement_spec_item', only => [qw(dragged_and_dr
 # actions
 #
 
+sub action_ajax_list {
+  my ($self) = @_;
+
+  my $js = SL::ClientJS->new;
+
+  if (!$::form->{clicked_id}) {
+    # Clicked on "sections" in the tree. Do nothing.
+    return $self->render($js);
+  }
+
+  $self->init_visible_section($::form->{current_content_id}, $::form->{current_content_type});
+  $self->item(SL::DB::RequirementSpecItem->new(id => $::form->{clicked_id})->load->get_section);
+
+  if (!$self->visible_section || ($self->visible_section->id != $self->item->id)) {
+    my $html = $self->render('requirement_spec_item/_section', { output => 0 }, requirement_spec_item => $self->item);
+    $js->html('#column-content', $html)
+       ->val('#current_content_type', $self->item->get_type)
+       ->val('#current_content_id', $self->item->id);
+  }
+
+  $self->render($js);
+}
+
 sub action_new {
   my ($self) = @_;
 
@@ -108,4 +131,14 @@ sub format_exception {
   return join "\n", (split m/\n/, $@)[0..4];
 }
 
+sub init_visible_section {
+  my ($self, $content_id, $content_type) = @_;
+
+  return undef unless $content_id;
+  return undef unless $content_type =~ m/section|function-block/;
+
+  $self->visible_item(SL::DB::RequirementSpecItem->new(id => $content_id)->load);
+  return $self->visible_section($self->visible_item->get_section);
+}
+
 1;
index fb1f364..ca62021 100644 (file)
@@ -48,6 +48,8 @@ sub action_ajax_list {
     my $html        = $self->render('requirement_spec_text_block/ajax_list', { output => 0 }, TEXT_BLOCKS => $text_blocks, output_position => $new_where);
 
     $js->html('#column-content', $html)
+       ->val('#current_content_type', 'text-blocks-' . (0 == $new_where ? 'front' : 'back'))
+       ->val('#current_content_id',   $::form->{clicked_id});
   }
 
   $self->render($js);
index 9322c32..072b59b 100644 (file)
@@ -37,4 +37,19 @@ sub sorted_children {
   return [ sort { $a->position <=> $b->position } @{ $self->children } ];
 }
 
+sub get_section {
+  my ($self) = @_;
+
+  $self = $self->parent while $self->parent_id;
+
+  return $self;
+}
+
+sub get_type {
+  my ($self) = @_;
+
+  return 'section' if !$self->parent_id;
+  return $self->parent->parent_id ? 'sub-function-block' : 'function-block';
+}
+
 1;
index cdf05cf..ed4f567 100644 (file)
@@ -13,12 +13,12 @@ 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';
+  my $type     = !$item->parent_id ? 'section' : 'function-block';
 
   return {
-    data     => join(' ', map { $_ || '' } ($item->fb_number, $item->title)),
+    data     => join(' ', map { $_ || '' } ($item->fb_number, $item->title, '<' . $item->id . '>')),
     metadata => { id =>         $item->id, type => $type },
-    attr     => { id => "fb-" . $item->id, href => $params{href} || '#' },
+    attr     => { id => "fb-" . $item->id, href => $params{href} || '#', class => $type . '-context-menu' },
     children => \@children,
   };
 }
index 2901452..90bce82 100644 (file)
@@ -25,3 +25,34 @@ table.rs_input_field input, table.rs_input_field select {
 .section-empty-description {
   color: #bbb;
 }
+
+.function-block {
+  border-bottom: 1px solid #bbb;
+}
+
+.section-description-heading {
+  font-weight: bold;
+}
+
+.section-description {
+  color: #000;
+  background: rgb(235, 235, 235);
+  border: 1px solid #ccc;
+  margin-bottom: 15px;
+}
+
+.sub-function-block {
+  border-bottom: 1px solid #ccc;
+}
+
+.sub-function-block-container {
+  margin: 10px 0px 10px 20px;
+  border: 1px solid #ccc;
+}
+
+.sub-function-block-header {
+  padding: 5px;
+  font-weight: bold;
+  color: #fff;
+  background: #ccc;
+}
index de3e8d5..6e9aaf4 100644 (file)
@@ -1,5 +1,9 @@
 /* Functions used for the requirement specs tree view */
 
+// -----------------------------------------------------------------------------
+// ------------------------------ the tree itself ------------------------------
+// -----------------------------------------------------------------------------
+
 function requirement_spec_tree_check_move(data) {
   var dragged_type = data.o.data('type');
   var dropped_type = data.r.data('type');
@@ -31,7 +35,7 @@ function requirement_spec_tree_check_move(data) {
   if ((dropped_type == "text-block") || (dropped_type == "text-blocks-front") || (dropped_type == "text-blocks-back"))
     return false;
 
-  var dropped_depth = dropped_type == "sections" ? 0 : dropped_type == "section" ? 1 : data.r.parent().parent().data('type') != "functionblock" ? 2 : 3;
+  var dropped_depth = dropped_type == "sections" ? 0 : dropped_type == "section" ? 1 : data.r.parent().parent().data('type') != "function-block" ? 2 : 3;
   if ((data.p == "inside") || (data.p == "last"))
     dropped_depth++;
 
@@ -73,68 +77,20 @@ function requirement_spec_tree_node_clicked(event) {
   if (!type)
     return;
 
-  if ('sections' ==  type) {
-    $('#current_content_type').val('sections');
-    $('#current_content_id').val('');
-    return;
-  }
-
   var url = 'controller.pl?action='
   $.get('controller.pl', {
-    action:               (/^text-block/ ? 'RequirementSpecTextBlock' : 'RequirementSpecItem') + '/ajax_list.js',
+    action:               (/^text-block/.test(type) ? 'RequirementSpecTextBlock' : 'RequirementSpecItem') + '/ajax_list.js',
     requirement_spec_id:  $('#requirement_spec_id').val(),
     current_content_type: $('#current_content_type').val(),
     current_content_id:   $('#current_content_id').val(),
     clicked_type:         type,
     clicked_id:           node.data('id')
-  }, function(new_data) {
-    $('#current_content_type').val(type);
-    $('#current_content_id').val(node.data('id'));
-    eval_json_result(new_data);
-  });
-}
-
-function section_form_requested(data) {
-  $('#new-section-button').removeAttr('disabled');
-  if (data.status == "ok")
-    $('#content-column').html(data.html);
-  else
-    alert('oh yeah response: ' + data.status + "\n" + data.error);
-}
-
-function section_form_submitted(data) {
-  alert('oh yeah response: ' + data.status);
-}
-
-function server_side_error(things_to_enable) {
-  alert('Server-side error.');
-  if (things_to_enable)
-    $(things_to_enable).removeAttr('disabled');
+  }, eval_json_result);
 }
 
-function new_section_form() {
-  $('#new-section-button').attr('disabled', 'disabled');
-  $.ajax({
-    type: 'POST',
-    url: 'controller.pl',
-    data: 'action=RequirementSpecItem/new.json&requirement_spec_id=' + $('#requirement_spec_id').val() + '&item_type=section',
-    success: section_form_requested,
-    error: function() { server_side_error('#new-section-button'); }
-  });
-}
-
-function submit_section_form(id) {
-  $.ajax({
-    type: 'POST',
-    url: 'controller.pl',
-    data: 'action=RequirementSpecItem/create.json&' + $('section-form-' + id).serialize(),
-    success: section_form_submitted
-  });
-}
-
-function cancel_section_form(id) {
-  $('#content-column').html('intentionally empty');
-}
+// -------------------------------------------------------------------------
+// ------------------------------ text blocks ------------------------------
+// -------------------------------------------------------------------------
 
 function find_text_block_id(clicked_elt) {
   // console.log("id: " + $(clicked_elt).attr('id'));
@@ -209,3 +165,46 @@ function cancel_edit_text_block_form(id_base) {
   if (id)
     $('#text-block-' + id).show();
 }
+
+// --------------------------------------------------------------------------------
+// ------------------------------ sections and items ------------------------------
+// --------------------------------------------------------------------------------
+
+function find_item_id(clicked_elt) {
+  console.log("clicked id: " + $(clicked_elt).attr('id'));
+  var id     = $(clicked_elt).attr('id');
+  var result = /^(function-block|function-block-content|sub-function-block|sub-function-block-content|section|section-header)-(\d+)$/.exec(id);
+  if (result) {
+    console.log("find_item_id: case 1: " + result[2]);
+    return result[2];
+  }
+
+  id = $(clicked_elt).closest("[id*=fb-]").attr('id')
+  if (/^fb-\d+$/.test(id)) {
+    console.log("find_item_id: case 2: " + id.substr(3));
+    return id.substr(3) * 1;
+  }
+
+  console.log("find_item_id: case undef");
+  return undefined;
+}
+
+function standard_item_ajax_call(key, opt, other_data) {
+  var data = {
+    action:               "RequirementSpecTextBlock/ajax_" + key,
+    requirement_spec_id:  $('#requirement_spec_id').val(),
+    id:                   find_item_id(opt.$trigger),
+    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", $.extend(data, other_data || {}), eval_json_result);
+
+  return true;
+}
+
+function disable_edit_item_commands(key, opt) {
+  return false; // find_item_id(opt.$trigger) == undefined;
+}
index 6cb20d0..44587be 100755 (executable)
@@ -167,6 +167,7 @@ $self->{texts} = {
   'Add and edit units'          => 'Einheiten erfassen und bearbeiten',
   'Add bank account'            => 'Bankkonto erfassen',
   'Add custom variable'         => 'Benutzerdefinierte Variable erfassen',
+  'Add function block'          => 'Funktionsblock hinzufügen',
   'Add link: select records to link with' => 'Verknüpfungen hinzufügen: zu verknüpfende Belege auswählen',
   'Add linked record'           => 'Verknüpften Beleg hinzufügen',
   'Add links'                   => 'Verknüpfungen hinzufügen',
@@ -174,6 +175,8 @@ $self->{texts} = {
   'Add new custom variable'     => 'Neue benutzerdefinierte Variable erfassen',
   'Add note'                    => 'Notiz erfassen',
   'Add printer'                 => 'Drucker hinzufügen',
+  'Add section'                 => 'Abschnitt hinzufügen',
+  'Add sub function block'      => 'Unterfunktionsblock hinzufügen',
   'Add text block'              => 'Textblock erfassen',
   'Add unit'                    => 'Einheit hinzuf&uuml;gen',
   'Address'                     => 'Adresse',
@@ -709,7 +712,6 @@ $self->{texts} = {
   'Delete drafts'               => 'Entwürfe löschen',
   'Delete links'                => 'Verknüpfungen löschen',
   'Delete profile'              => 'Profil löschen',
-  'Delete section'              => 'Abschnitt löschen',
   'Delete text block'           => 'Textblock löschen',
   'Delete transaction'          => 'Buchung löschen',
   'Deleted'                     => 'Gelöscht',
@@ -889,7 +891,6 @@ $self->{texts} = {
   'Edit requirement spec status' => 'Pflichtenheftstatus bearbeiten',
   'Edit requirement spec type'  => 'Pflichtenhefttypen bearbeiten',
   'Edit risk level'             => 'Risikograd bearbeiten',
-  'Edit section'                => 'Abschnitt bearbeiten',
   'Edit section #1'             => 'Abschnitt #1 bearbeiten',
   'Edit templates'              => 'Vorlagen bearbeiten',
   'Edit text block'             => 'Textblock bearbeiten',
@@ -1438,7 +1439,6 @@ $self->{texts} = {
   'No default currency'         => 'Keine Standardwährung',
   'No delivery term has been created yet.' => 'Es wurden noch keine Lieferbedingungen angelegt',
   'No department has been created yet.' => 'Es wurde noch keine Abteilung erfasst.',
-  'No description has been entered yet.' => 'Es wurde noch keine Beschreibung eingegeben.',
   'No dunnings have been selected for printing.' => 'Es wurden keine Mahnungen zum Drucken ausgew&auml;hlt.',
   'No file has been uploaded yet.' => 'Es wurde noch keine Datei hochgeladen.',
   'No function blocks have been created yet.' => 'Es wurden noch keine Funktionsblöcke angelegt.',
@@ -1457,6 +1457,7 @@ $self->{texts} = {
   'No requirement spec statuses has been created yet.' => 'Es wurden noch keine Pflichtenheftstatus angelegt.',
   'No requirement spec type has been created yet.' => 'Es wurden noch keine Pflichtenhefttypen angelegt.',
   'No risks level has been created yet.' => 'Es wurden noch keine Risikograde angelegt.',
+  'No sections have been created so far.' => '',
   'No shipto selected to delete' => 'Keine Lieferadresse zum Löschen ausgewählt',
   'No summary account'          => 'Kein Sammelkonto',
   'No text blocks have been created for this position.' => 'Für diese Position wurden noch keine Textblöcke angelegt.',
@@ -1676,6 +1677,7 @@ $self->{texts} = {
   'Postscript'                  => 'Postscript',
   'Posustva_coa'                => 'USTVA Kennz.',
   'Pre-defined Texts'           => 'Vordefinierte Textblöcke',
+  'Preamble'                    => 'Einleitung',
   'Preferences'                 => 'Einstellungen',
   'Preferences saved!'          => 'Einstellungen gespeichert!',
   'Prefix for the new bins\' names' => 'Namenspr&auml;fix f&uuml;r die neuen Lagerpl&auml;tze',
index 53fb52d..71c5b34 100644 (file)
 
   <div id="column-content">
    [%- IF SELF.requirement_spec_item -%]
-    [%- INCLUDE 'requirement_spec_item/_single_section.html' requirement_spec_item=SELF.requirement_spec_item -%]
+    [%- INCLUDE 'requirement_spec_item/_section.html' requirement_spec_item=SELF.requirement_spec_item -%]
    [%- ELSE -%]
-    no section
-    [%#- render :partial => 'requirement_spec_items/no_section' -%]
+    [%- INCLUDE 'requirement_spec_item/_no_section.html' -%]
    [%- END -%]
   </div>
  </div>
@@ -48,7 +47,7 @@
 
        { data:     [% JSON.json(LxERP.t8("Sections")) %],
          metadata: { type: "sections" },
-         attr:     { id: "sections" },
+         attr:     { id: "sections", class: "section-context-menu" },
          children: [
 
 [% FOREACH section = SELF.requirement_spec.sections %]
@@ -108,19 +107,83 @@ function ask_delete_text_block(key, opt) {
   return true;
 }
 
+function ask_delete_item(key, opt) {
+  if (confirm("[% LxERP.t8("Are you sure?") %]"))
+    standard_item_ajax_call(key, opt);
+  return true;
+}
+
 $(function(){
-    $.contextMenu({
-        selector: '.text-block-context-menu',
-        items: {
-          add:    { name: "[% LxERP.t8('Add text block') %]", icon: "add", callback: standard_text_block_ajax_call },
-          edit:   { name: "[% LxERP.t8('Edit text block') %]", icon: "edit", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands },
-          delete: { name: "[% LxERP.t8('Delete text block') %]", icon: "delete", callback: ask_delete_text_block, disabled: disable_edit_text_block_commands },
-          sep1:   "---------",
-          copy:   { name: "[% LxERP.t8('Copy') %]", icon: "copy", disabled: disable_edit_text_block_commands },
-          paste:  { name: "[% LxERP.t8('Paste') %]", icon: "paste", disabled: disable_edit_text_block_commands }
-        }
-      });
+  $.contextMenu({
+    selector: '.text-block-context-menu',
+    items: {
+      add:    { name: "[% LxERP.t8('Add text block') %]",    icon: "add",    callback: standard_text_block_ajax_call },
+      edit:   { name: "[% LxERP.t8('Edit text block') %]",   icon: "edit",   callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands },
+      delete: { name: "[% LxERP.t8('Delete text block') %]", icon: "delete", callback: ask_delete_text_block,         disabled: disable_edit_text_block_commands },
+      sep1:   "---------",
+      copy:   { name: "[% LxERP.t8('Copy') %]",              icon: "copy",  disabled: disable_edit_text_block_commands },
+      paste:  { name: "[% LxERP.t8('Paste') %]",             icon: "paste", disabled: disable_edit_text_block_commands }
+    }
+  });
+
+
+  $.contextMenu({
+    selector: '.section-context-menu',
+    items: {
+      add_section:        { name: "[% LxERP.t8('Add section') %]",        icon: "add",    callback: standard_item_ajax_call },
+      add_function_block: { name: "[% LxERP.t8('Add function block') %]", icon: "add",    callback: standard_text_block_ajax_call },
+      sep1:               "---------",
+      edit:               { name: "[% LxERP.t8('Edit') %]",               icon: "edit",   callback: standard_item_ajax_call, disabled: disable_edit_item_commands },
+      delete:             { name: "[% LxERP.t8('Delete') %]",             icon: "delete", callback: ask_delete_item,         disabled: disable_edit_item_commands },
+      sep2:               "---------",
+      copy:               { name: "[% LxERP.t8('Copy') %]",               icon: "copy",  disabled: disable_edit_item_commands },
+      paste:              { name: "[% LxERP.t8('Paste') %]",              icon: "paste", disabled: disable_edit_item_commands }
+    }
+  });
+
+  $.contextMenu({
+    selector: '.function-block-context-menu,.sub-function-block-context-menu',
+    items: {
+      new_item:     { name: "[% LxERP.t8('Add function block') %]",     icon: "add", callback: standard_item_ajax_call },
+      new_sub_item: { name: "[% LxERP.t8('Add sub function block') %]", icon: "add", callback: standard_item_ajax_call },
+      sep1:         "---------",
+      edit:         { name: "[% LxERP.t8('Edit') %]",   icon: "edit",   callback: standard_item_ajax_call, disabled: disable_edit_item_commands },
+      delete:       { name: "[% LxERP.t8('Delete') %]", icon: "delete", callback: standard_item_ajax_call, disabled: disable_edit_item_commands },
+      sep2:         "---------",
+      copy:         { name: "[% LxERP.t8('Copy') %]",  icon: "copy",  disabled: disable_edit_item_commands },
+      paste:        { name: "[% LxERP.t8('Paste') %]", icon: "paste", disabled: disable_edit_item_commands }
+    }
+  });
 });
 
+function edit_section_header() {
+  $.post("controller.pl?action=RequirementSpecItem/edit_section&id=" + encodeURIComponent($('#active_section_id').val()), function(data) {
+    var header = $('#section-header');
+    header.data('old-elements', header.children().detach());
+    header.html(data);
+  });
+}
+
+function submit_section_form() {
+  $.post("controller.pl?action=RequirementSpecItem/update_section&id=" + $('#section-form form').serialize(), function(data) {
+    var header = $('#section-header');
+    header.removeData('old-elements');
+    header.html(data['header_html']);
+    $('#tree').jstree('rename_node', '#fb-' + data['id'], data['node_name']);
+  });
+}
+
+function cancel_section_form() {
+  var header = $('#section-header');
+  header.empty();
+  header.append(header.data('old-elements'));
+  header.removeData('old-elements');
+}
+
+
+
+
+
+
   -->
 </script>
diff --git a/templates/webpages/requirement_spec_item/_function_block.html b/templates/webpages/requirement_spec_item/_function_block.html
new file mode 100644 (file)
index 0000000..576667e
--- /dev/null
@@ -0,0 +1,19 @@
+[%- USE HTML -%][%- USE LxERP -%][%- USE P -%][%- USE L -%]
+<div id="function-block-[% requirement_spec_item.id %]" class="function-block">
+
+ <div id="function-block-content-[%- requirement_spec_item.id -%]" class="function-block-content[%- IF requirement_spec_item.flagged -%] flagged[%- END -%] function-block-context-menu">
+
+  [% INCLUDE 'requirement_spec_item/_function_block_content_top.html' id_prefix='' %]
+
+  <div class="sub-function-block-container" id="sub-function-block_container-[%- requirement_spec_item.id -%]"[%- IF !requirement_spec_item.children.size -%] style="display: none"[%- END -%]>
+   <div class="sub-function-block-header" id="sub-function-block_header_[%- requirement_spec_item.id -%]">
+    [%- LxERP.t8("Sub function blocks") -%]
+   </div>
+   [%- FOREACH sub_function_block = requirement_spec_item.children -%]
+    [%- INCLUDE 'requirement_spec_item/_sub_function_block.html' requirement_spec_item=sub_function_block -%]
+   [%- END -%]
+  </div>
+
+  [% INCLUDE 'requirement_spec_item/_function_block_content_bottom.html' id_prefix='' %]
+ </div>
+</div>
diff --git a/templates/webpages/requirement_spec_item/_function_block_content_bottom.html b/templates/webpages/requirement_spec_item/_function_block_content_bottom.html
new file mode 100644 (file)
index 0000000..71eb245
--- /dev/null
@@ -0,0 +1,15 @@
+[%- USE LxERP -%][%- USE P -%]<div id="[% id_prefix %]function-block-content-bottom-[% requirement_spec_item.id %]" class="smaller" style="text-align:right">
+ [%- IF requirement_spec_item.dependencies.size -%]
+ <span class="gray">
+  [%- LxERP.t8("Dependencies") -%]: [%- P.requirement_spec_item_dependency_list(requirement_spec_item.dependencies) -%]
+ </span><br>
+ [%- END -%]
+ <span class="gray">
+  [%- LxERP.t8("Complexity") -%]: [%- requirement_spec_item.requirement_spec_complexity.description IF requirement_spec_item.requirement_spec_complexity -%]
+  &nbsp; | &nbsp;
+  [%- LxERP.t8("Risk") -%]: [%- requirement_spec_item.requirement_spec_risk.description IF requirement_spec_item.requirement_spec_risk -%]
+  &nbsp; | &nbsp;
+  [%- LxERP.t8("Effort") -%]: [%#- render :partial => 'requirement_spec_items/time_estimation_item', :locals => { :item => requirement_spec_item } -%]
+ </span>
+
+</div>
diff --git a/templates/webpages/requirement_spec_item/_function_block_content_top.html b/templates/webpages/requirement_spec_item/_function_block_content_top.html
new file mode 100644 (file)
index 0000000..c52e177
--- /dev/null
@@ -0,0 +1,4 @@
+[%- USE HTML -%][%- USE L -%]<div id="[% id_prefix %]function-block-content-top-[% requirement_spec_item.id %]">
+ <b>[%- HTML.escape(requirement_spec_item.fb_number) -%]</b> &lt;[% requirement_spec_item.id %]&gt;
+ [%- L.simple_format(requirement_spec_item.description) -%]
+</div>
diff --git a/templates/webpages/requirement_spec_item/_no_section.html b/templates/webpages/requirement_spec_item/_no_section.html
new file mode 100644 (file)
index 0000000..2ef6f1a
--- /dev/null
@@ -0,0 +1,5 @@
+[%- USE LxERP -%]
+<span class="section-context-menu">
+ [%- LxERP.t8("No sections have been created so far.") %]
+ [% LxERP.t8("Create one from the context menu by right-clicking on this text.") %]
+</span>
diff --git a/templates/webpages/requirement_spec_item/_section.html b/templates/webpages/requirement_spec_item/_section.html
new file mode 100644 (file)
index 0000000..79509c7
--- /dev/null
@@ -0,0 +1,17 @@
+[%- USE HTML -%][%- USE LxERP -%][%- USE L -%]
+<div id="full-section-content">
+ <div class="section-context-menu" id="section-header-[% requirement_spec_item.id %]">
+  [%- INCLUDE 'requirement_spec_item/_section_header.html' %]
+ </div>
+
+ <div id="section-list-empty" class="section-context-menu"[% IF requirement_spec_item.children.size %] style="display: none"[% END %]>
+  [%- LxERP.t8("No function blocks have been created yet.") %]
+  [% LxERP.t8("Create one from the context menu by right-clicking on this text.") %]
+ </div>
+
+ <div id="section-list" class="section">
+  [%- FOREACH function_block = requirement_spec_item.children -%]
+   [%- INCLUDE 'requirement_spec_item/_function_block.html' requirement_spec_item=function_block -%]
+  [%- END -%]
+ </div>
+</div>
index 60c9deb..db3a998 100644 (file)
@@ -1,12 +1,20 @@
 [%- USE HTML -%][%- USE L -%][%- USE LxERP -%]
 <h1>
- [%- HTML.escape(requirement_spec_item.fb_number) %]: [% HTML.escape(requirement_spec_item.title) -%]
+ [%- HTML.escape(requirement_spec_item.fb_number) %]: &lt;[% requirement_spec_item.id %]&gt;
+ [% IF requirement_spec_item.title %]
+  [% HTML.escape(requirement_spec_item.title) %]
+ [% ELSE %]
+  <div class="dimmed-text">
+   [%- LxERP.t8("No text has been entered yet.") %]
+  </div>
+ [% END %]
 </h1>
 
-[% IF requirement_spec_item.description %]
- <div class="section-description">
+<div class="section-description">
+ <div class="section-description-heading">[%- LxERP.t8("Preamble") %]</div>
+ [% IF requirement_spec_item.description %]
   [%- L.simple_format(requirement_spec_item.description) -%]
- </div>
-[%- ELSE %]
- <div class="section-empty-description">[%- LxERP.t8("No description has been entered yet.") %]</div>
-[%- END %]
+ [%- ELSE %]
+  <span class="dimmed-text">[%- LxERP.t8("No text has been entered yet.") %]</span>
+ [%- END %]
+</div>
diff --git a/templates/webpages/requirement_spec_item/_single_section.html b/templates/webpages/requirement_spec_item/_single_section.html
deleted file mode 100644 (file)
index 836ac89..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-[%- USE HTML -%][%- USE LxERP -%][%- USE L -%]
-<div class="section-context-menu" id="section-header">
- [%- INCLUDE 'requirement_spec_item/_section_header.html' %]
-</div>
-
-[%- L.hidden_tag('active_section_id', requirement_spec_item.id) -%]
-
-<ul id="section" class="section function-block-context-menu">
-  [%- FOREACH subitem = requirement_spec_item.children -%]
-    [%- INCLUDE 'requirement_spec_item/_single_subitem.html' requirement_spec_item=subitem -%]
-  [%- END -%]
-</ul>
-
-<div id="new_subitem_form" class="subitem-form clearfix">
-</div>
-<div id="new_subitem_link" class="highlight-box" style="[%- 'display:none' IF requirement_spec_item.children.size -%]">
- [%- LxERP.t8("No function blocks have been created yet.") %]
-</div>
-
-<script type="text/javascript">
- <!--
-$(function(){
-    $.contextMenu({
-        selector: '.section-context-menu',
-        callback: function(key, options) {
-            var m = "clicked: " + key;
-            window.console && console.log(m) || alert(m);
-        },
-        items: {
-          edit:   { name: "[% LxERP.t8('Edit section') %]", icon: "edit", callback: edit_section_header },
-          delete: { name: "[% LxERP.t8('Delete section') %]", icon: "delete" },
-          sep1:   "---------",
-          copy:   { name: "[% LxERP.t8('Copy') %]", icon: "copy" },
-          paste:  { name: "[% LxERP.t8('Paste') %]", icon: "paste" }
-        }
-      });
-
-    $.contextMenu({
-        selector: '.function-block-context-menu',
-        callback: function(key, options) {
-            var m = "clicked: " + key;
-            window.console && console.log(m) || alert(m);
-        },
-        items: {
-          new_item:     { name: "[% LxERP.t8('New function block') %]",     icon: "add"},
-          new_sub_item: { name: "[% LxERP.t8('New sub function block') %]", icon: "add"},
-          sep1:   "---------",
-          edit:   { name: "[% LxERP.t8('Edit') %]",   icon: "edit"},
-          delete: { name: "[% LxERP.t8('Delete') %]", icon: "delete"},
-          sep2:   "---------",
-          copy:   { name: "[% LxERP.t8('Copy') %]", icon: "copy" },
-          paste:  { name: "[% LxERP.t8('Paste') %]", icon: "paste" }
-        }
-    });
-
-    $('.section-context-menu').on('click', function(e){
-        console.log('clicked', this);
-    });
-});
-
-function edit_section_header() {
-  $.post("controller.pl?action=RequirementSpecItem/edit_section&id=" + encodeURIComponent($('#active_section_id').val()), function(data) {
-    var header = $('#section-header');
-    header.data('old-elements', header.children().detach());
-    header.html(data);
-  });
-}
-
-function submit_section_form() {
-  $.post("controller.pl?action=RequirementSpecItem/update_section&id=" + $('#section-form form').serialize(), function(data) {
-    var header = $('#section-header');
-    header.removeData('old-elements');
-    header.html(data['header_html']);
-    $('#tree').jstree('rename_node', '#fb-' + data['id'], data['node_name']);
-  });
-}
-
-function cancel_section_form() {
-  var header = $('#section-header');
-  header.empty();
-  header.append(header.data('old-elements'));
-  header.removeData('old-elements');
-}
--->
-</script>
diff --git a/templates/webpages/requirement_spec_item/_single_subitem.html b/templates/webpages/requirement_spec_item/_single_subitem.html
deleted file mode 100644 (file)
index c2af84c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-[%- USE HTML -%][%- USE LxERP -%][%- USE P -%]
-<li id="subitem_[%- requirement_spec_item.id -%]" class="subitem">
-
-  <div id="subitem_content_[%- requirement_spec_item.id -%]" class="subitem-content[%- IF requirement_spec_item.flagged -%] flagged[%- END -%]">
-
-    [%#- 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}" -%]
-
-    <b>[%- HTML.escape(requirement_spec_item.fb_number) -%]</b>
-    [%- HTML.escape(requirement_spec_item.description) -%]
-
-    <div class="subsubitem-container" id="subsubitem_container_[%- requirement_spec_item.id -%]">
-     <div class="subsubitem-header" id="subsubitem_header_[%- requirement_spec_item.id -%]"[%- IF !requirement_spec_item.children.size -%] style="display: none"[%- END -%]>
-      [%- LxERP.t8("Sub function blocks") -%]
-     </div>
-      [%- 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 -%]
-    </div>
-
-    <div id="new_subsubitem_form_[%- requirement_spec_item.id -%]" class="subsubitem_form"></div>
-
-    <div class="smaller" style="text-align:right">
-      [%- IF requirement_spec_item.dependencies.size -%]
-        <span class="gray">
-          [%- LxERP.t8("Dependencies") -%]: [%- P.requirement_spec_item_dependency_list(requirement_spec_item.dependencies) -%]
-        </span><br>
-      [%- END -%]
-      <span class="gray">
-        [%- LxERP.t8("Complexity") -%]: [%- requirement_spec_item.requirement_spec_complexity.description IF requirement_spec_item.requirement_spec_complexity -%]
-        &nbsp; | &nbsp;
-        [%- LxERP.t8("Risk") -%]: [%- requirement_spec_item.requirement_spec_risk.description IF requirement_spec_item.requirement_spec_risk -%]
-        &nbsp; | &nbsp;
-        [%- LxERP.t8("Effort") -%]: [%#- render :partial => 'requirement_spec_items/time_estimation_item', :locals => { :item => requirement_spec_item } -%]
-      </span>
-
-    </div>
-  </div>
-</li>
diff --git a/templates/webpages/requirement_spec_item/_sub_function_block.html b/templates/webpages/requirement_spec_item/_sub_function_block.html
new file mode 100644 (file)
index 0000000..576d237
--- /dev/null
@@ -0,0 +1,8 @@
+[%- USE HTML -%][%- USE LxERP -%][%- USE P -%]
+<div id="sub-function-block-[% requirement_spec_item.id %]" class="sub-function-block">
+
+ <div id="sub-function-block-content-[%- requirement_spec_item.id -%]" class="sub-function-block-content[%- IF requirement_spec_item.flagged -%] flagged[%- END -%] sub-function-block-context-menu">
+  [% INCLUDE 'requirement_spec_item/_function_block_content_top.html' id_prefix='sub-' %]
+  [% INCLUDE 'requirement_spec_item/_function_block_content_bottom.html' id_prefix='sub-' %]
+ </div>
+</div>