commit 8e082571fb1ea2d8a46b863a764a56fb26823226
Author: Moritz Bunkus <m.bunkus@linet.de>
Date:   Mon Jan 20 13:37:59 2014 +0100

    Pflichtenheft: Projektverknüpfung anlegen, bearbeiten
    
    - Pflichtenhefte mit einem bestehenden Projekt verknüpfen,
    - neues Projekt anlegen,
    - nicht mit einem Projekt verknüpfen.

diff --git a/SL/Controller/RequirementSpec.pm b/SL/Controller/RequirementSpec.pm
index b36d9b9ea..2a04cf7fb 100644
--- a/SL/Controller/RequirementSpec.pm
+++ b/SL/Controller/RequirementSpec.pm
@@ -18,6 +18,8 @@ use SL::Controller::Helper::ReportGenerator;
 use SL::Controller::Helper::RequirementSpec;
 use SL::DB::Customer;
 use SL::DB::Project;
+use SL::DB::ProjectStatus;
+use SL::DB::ProjectType;
 use SL::DB::RequirementSpecComplexity;
 use SL::DB::RequirementSpecRisk;
 use SL::DB::RequirementSpecStatus;
@@ -29,12 +31,12 @@ use SL::Template::LaTeX;
 
 use Rose::Object::MakeMethods::Generic
 (
-  scalar                  => [ qw(requirement_spec_item customers types statuses visible_item visible_section) ],
-  'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects copy_source js current_text_block_output_position) ],
+  scalar                  => [ qw(requirement_spec_item visible_item visible_section) ],
+  'scalar --get_set_init' => [ qw(requirement_spec customers types statuses complexities risks projects project_types project_statuses default_project_type default_project_status copy_source js
+                                  current_text_block_output_position) ],
 );
 
 __PACKAGE__->run_before('setup');
-__PACKAGE__->run_before('load_select_options',  only => [ qw(new ajax_edit create update list) ]);
 
 __PACKAGE__->make_filtered(
   MODEL      => 'RequirementSpec',
@@ -110,6 +112,17 @@ sub action_ajax_edit {
     ->render($self);
 }
 
+sub action_ajax_edit_project_link {
+  my ($self) = @_;
+
+  my $html   = $self->render('requirement_spec/_project_link_form', { output => 0 }, submit_as => 'ajax');
+
+  $self->js
+    ->hide('#basic_settings')
+    ->after('#basic_settings', $html)
+    ->render($self);
+}
+
 sub action_ajax_show_time_and_cost_estimate {
   my ($self) = @_;
 
@@ -186,6 +199,17 @@ sub action_update {
   $self->create_or_update;
 }
 
+sub action_update_project_link {
+  my $self   = shift;
+  my $action = delete($::form->{project_link_action}) || 'keep';
+
+  return $self->update_project_link_none_keep_existing($action) if $action =~ m{none|keep|existing};
+  return $self->update_project_link_new($action)                if $action eq 'new';
+  return $self->update_project_link_create($action)             if $action eq 'create';
+
+  die "Unknown project link action '$action'";
+}
+
 sub action_destroy {
   my ($self) = @_;
 
@@ -273,19 +297,24 @@ sub setup {
   return 1;
 }
 
-sub init_complexities {
+sub init_js                     { SL::ClientJS->new                                           }
+sub init_complexities           { SL::DB::Manager::RequirementSpecComplexity->get_all_sorted  }
+sub init_default_project_status { SL::DB::Manager::ProjectStatus->find_by(name => 'planning') }
+sub init_default_project_type   { SL::DB::ProjectType->new(id => 1)->load                     }
+sub init_project_statuses       { SL::DB::Manager::ProjectStatus->get_all_sorted              }
+sub init_project_types          { SL::DB::Manager::ProjectType->get_all_sorted                }
+sub init_projects               { SL::DB::Manager::Project->get_all_sorted                    }
+sub init_risks                  { SL::DB::Manager::RequirementSpecRisk->get_all_sorted        }
+sub init_statuses               { SL::DB::Manager::RequirementSpecStatus->get_all_sorted      }
+sub init_types                  { SL::DB::Manager::RequirementSpecType->get_all_sorted        }
+
+sub init_customers {
   my ($self) = @_;
-  return SL::DB::Manager::RequirementSpecComplexity->get_all_sorted;
-}
 
-sub init_risks {
-  my ($self) = @_;
-  return SL::DB::Manager::RequirementSpecRisk->get_all_sorted;
-}
+  my @filter = ('!obsolete' => 1);
+  @filter    = ( or => [ @filter, id => $self->requirement_spec->customer_id ] ) if $self->requirement_spec && $self->requirement_spec->customer_id;
 
-sub init_projects {
-  my ($self) = @_;
-  $self->projects(SL::DB::Manager::Project->get_all_sorted);
+  return SL::DB::Manager::Customer->get_all_sorted(where => \@filter);
 }
 
 sub init_requirement_spec {
@@ -298,27 +327,11 @@ sub init_copy_source {
   $self->copy_source(SL::DB::RequirementSpec->new(id => $::form->{copy_source_id})->load) if $::form->{copy_source_id};
 }
 
-sub init_js {
-  my ($self) = @_;
-  $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) = @_;
-
-  my @filter = ('!obsolete' => 1);
-  @filter    = ( or => [ @filter, id => $self->requirement_spec->customer_id ] ) if $self->requirement_spec && $self->requirement_spec->customer_id;
-
-  $self->customers(SL::DB::Manager::Customer->get_all_sorted(where => \@filter));
-  $self->statuses( SL::DB::Manager::RequirementSpecStatus->get_all_sorted);
-  $self->types(    SL::DB::Manager::RequirementSpecType->get_all_sorted);
-}
-
 #
 # helpers
 #
@@ -502,4 +515,56 @@ sub prepare_pictures_for_printing {
   return @files;
 }
 
+sub update_project_link_none_keep_existing {
+  my ($self, $action) = @_;
+
+  $self->requirement_spec->update_attributes(project_id => undef)                     if $action eq 'none';
+  $self->requirement_spec->update_attributes(project_id => $::form->{new_project_id}) if $action eq 'existing';
+
+  return $self->invalidate_version
+    ->replaceWith('#basic_settings', $self->render('requirement_spec/_show_basic_settings', { output => 0 }))
+    ->remove('#project_link_form')
+    ->flash('info', t8('The project link has been updated.'))
+    ->render($self);
+}
+
+sub update_project_link_new {
+  my ($self) = @_;
+
+  return $self->js
+    ->replaceWith('#project_link_form', $self->render('requirement_spec/_new_project_form', { output => 0 }))
+    ->render($self);
+}
+
+sub update_project_link_create {
+  my ($self)  = @_;
+  my $params  = delete($::form->{project}) || {};
+  my $project = SL::DB::Project->new(
+    %{ $params },
+    valid  => 1,
+    active => 1,
+  );
+
+  my @errors = $project->validate;
+
+  return $self->js->error(@errors)->render($self) if @errors;
+
+  my $db = $self->requirement_spec->db;
+  if (!$db->do_transaction(sub {
+    $project->save;
+    $self->requirement_spec->update_attributes(project_id => $project->id);
+
+  })) {
+    $::lxdebug->message(LXDebug::WARN(), "Error: " . $db->error);
+    return $self->js->error(t8('Saving failed. Error message from the database: #1', $db->error))->render($self);
+  }
+
+  return $self->invalidate_version
+    ->replaceWith('#basic_settings', $self->render('requirement_spec/_show_basic_settings', { output => 0 }))
+    ->remove('#project_link_form')
+    ->flash('info', t8('The project has been created.'))
+    ->flash('info', t8('The project link has been updated.'))
+    ->render($self);
+}
+
 1;
diff --git a/js/locale/de.js b/js/locale/de.js
index 2b80e96e9..c0c3c57f3 100644
--- a/js/locale/de.js
+++ b/js/locale/de.js
@@ -32,6 +32,7 @@ namespace("kivi").setupLocale({
 "Edit":"Bearbeiten",
 "Edit article/section assignments":"Zuweisung Artikel/Abschnitte bearbeiten",
 "Edit picture":"Bild bearbeiten",
+"Edit project link":"Projektverknüpfung bearbeiten",
 "Edit text block":"Textblock bearbeiten",
 "Enter longdescription":"Langtext eingeben",
 "Function block actions":"Funktionsblockaktionen",
@@ -40,6 +41,7 @@ namespace("kivi").setupLocale({
 "Part picker":"Artikelauswahl",
 "Paste":"Einfügen",
 "Paste template":"Vorlage einfügen",
+"Project link actions":"Projektverknüpfungs-Aktionen",
 "Quotations/Orders actions":"Aktionen für Angebote/Aufträge",
 "Requirement spec actions":"Pflichtenheftaktionen",
 "Requirement spec template actions":"Pflichtenheftvorlagen-Aktionen",
diff --git a/js/requirement_spec.js b/js/requirement_spec.js
index 535c34eab..a3d6eacb9 100644
--- a/js/requirement_spec.js
+++ b/js/requirement_spec.js
@@ -444,7 +444,7 @@ ns.standard_basic_settings_ajax_call = function(key, opt) {
   if (key == 'cancel') {
     if (confirm(kivi.t8('Do you really want to cancel?'))) {
       $('#basic_settings').show();
-      $('#basic_settings_form').remove();
+      $('#basic_settings_form,#project_link_form').remove();
     }
     return true;
   }
@@ -684,6 +684,14 @@ ns.create_context_menus = function(is_template) {
       , delete_reqspec:  { name: kivi.t8('Delete template'), icon: "delete", callback: kivi.requirement_spec.delete_reqspec }
     };
 
+    $.contextMenu({
+      selector: '.basic-settings-context-menu',
+      items:    $.extend({
+          heading: { name: kivi.t8('Basic settings actions'), className: 'context-menu-heading' }
+        , edit:    { name: kivi.t8('Edit'), icon: "edit", callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
+      }, general_actions)
+    });
+
   } else {                      // if (is_template)
     var general_actions = {
         sep98:              "---------"
@@ -705,6 +713,24 @@ ns.create_context_menus = function(is_template) {
       }, general_actions)
     });
 
+    $.contextMenu({
+      selector: '.basic-settings-context-menu',
+      items:    $.extend({
+          heading:           { name: kivi.t8('Basic settings actions'), className: 'context-menu-heading' }
+        , edit:              { name: kivi.t8('Edit'),              icon: "edit", callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
+        , edit_project_link: { name: kivi.t8('Edit project link'),               callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
+      }, general_actions)
+    });
+
+    $.contextMenu({
+      selector: '.edit-project-link-context-menu',
+      items:    $.extend({
+          heading: { name: kivi.t8('Project link actions'), className: 'context-menu-heading' }
+        , save:    { name: kivi.t8('Save'),   icon: "save",  callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
+        , cancel:  { name: kivi.t8('Cancel'), icon: "close", callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
+      }, general_actions)
+    });
+
     var paste_template_actions = {
     };
   }                             // if (is_template) ... else ...
@@ -747,14 +773,6 @@ ns.create_context_menus = function(is_template) {
     }, general_actions)
   });
 
-  $.contextMenu({
-    selector: '.basic-settings-context-menu',
-    items:    $.extend({
-        heading: { name: kivi.t8('Basic settings actions'), className: 'context-menu-heading' }
-      , edit:    { name: kivi.t8('Edit'), icon: "edit", callback: kivi.requirement_spec.standard_basic_settings_ajax_call }
-    }, general_actions)
-  });
-
   $.contextMenu({
     selector: '.edit-basic-settings-context-menu',
     items:    $.extend({
diff --git a/locale/de/all b/locale/de/all
index d066fd6a4..756247713 100755
--- a/locale/de/all
+++ b/locale/de/all
@@ -562,6 +562,7 @@ $self->{texts} = {
   'Create a new predefined text' => 'Einen neuen vordefinierten Textblock anlegen',
   'Create a new printer'        => 'Einen neuen Drucker anlegen',
   'Create a new project'        => 'Neues Projekt anlegen',
+  'Create a new project and link to it.' => 'Neues Projekt anlegen und damit verknüpfen.',
   'Create a new project status' => 'Einen neuen Projektstatus anlegen',
   'Create a new project type'   => 'Einen neuen Projekttypen anlegen',
   'Create a new requirement spec' => 'Ein neues Pflichtenheft anlegen',
@@ -803,6 +804,7 @@ $self->{texts} = {
   'Display options'             => 'Anzeigeoptionen',
   'Do not change the tax rate of taxkey 0.' => 'Ändern Sie nicht den Steuersatz vom Steuerschlüssel 0.',
   'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
+  'Do not link to a project.'   => 'Nicht mit einem Projekt verknüpfen.',
   'Do not modify this position' => 'Diese Position nicht verändern',
   'Do not set default buchungsgruppe' => 'Nie Standardbuchungsgruppe setzen',
   'Do you really want to cancel?' => 'Wollen Sie wirklich abbrechen?',
@@ -926,6 +928,7 @@ $self->{texts} = {
   'Edit delivery term'          => 'Lieferbedingungen bearbeiten',
   'Edit department'             => 'Abteilung bearbeiten',
   'Edit file'                   => 'Datei bearbeiten',
+  'Edit general settings'       => 'Grundeinstellungen bearbeiten',
   'Edit greetings'              => 'Anreden bearbeiten',
   'Edit note'                   => 'Notiz bearbeiten',
   'Edit payment term'           => 'Zahlungsbedingungen bearbeiten',
@@ -934,6 +937,7 @@ $self->{texts} = {
   'Edit prices and discount (if not used, textfield is ONLY set readonly)' => 'Preise und Rabatt in Formularen frei anpassen (falls deaktiviert, wird allerdings NUR das textfield auf READONLY gesetzt / kann je nach Browserversion und technischen Fähigkeiten des Anwenders noch umgangen werden)',
   'Edit project'                => 'Projekt bearbeiten',
   'Edit project #1'             => 'Projekt #1 bearbeiten',
+  'Edit project link'           => 'Projektverknüpfung bearbeiten',
   'Edit project status'         => 'Projektstatus bearbeiten',
   'Edit project type'           => 'Projekttypen bearbeiten',
   'Edit requirement spec'       => 'Pflichtenheft bearbeiten',
@@ -1300,6 +1304,7 @@ $self->{texts} = {
   'June'                        => 'Juni',
   'KNE-Export erfolgreich!'     => 'KNE-Export erfolgreich!',
   'KNr. beim Kunden'            => 'KNr. beim Kunden',
+  'Keep the project link the way it is.' => 'Die aktuelle Verknüpfung beibehalten.',
   'Keine Suchergebnisse gefunden!' => 'Keine Suchergebnisse gefunden!',
   'Knowledge'                   => 'Wissen',
   'Konten'                      => 'Konten',
@@ -1350,6 +1355,7 @@ $self->{texts} = {
   'Line endings'                => 'Zeilenumbr&uuml;che',
   'Link direction'              => 'Verknüpfungsrichtung',
   'Link to'                     => 'Verknüpfen mit',
+  'Link to the following project:' => 'Mit dem folgenden Projekt verknüpfen:',
   'Linked Records'              => 'Verknüpfte Belege',
   'List Accounts'               => 'Konten anzeigen',
   'List Languages'              => 'Sprachen anzeigen',
@@ -1809,6 +1815,7 @@ $self->{texts} = {
   'Project Transactions'        => 'Projektbuchungen',
   'Project Type'                => 'Projekttyp',
   'Project Types'               => 'Projekttypen',
+  'Project link actions'        => 'Projektverknüpfungs-Aktionen',
   'Project type'                => 'Projekttyp',
   'Projects'                    => 'Projekte',
   'Projecttransactions'         => 'Projektbuchungen',
@@ -2434,6 +2441,7 @@ $self->{texts} = {
   'The project has been deleted.' => 'Das Projekt wurde gelöscht.',
   'The project has been saved.' => 'Das Projekt wurde gespeichert.',
   'The project is in use and cannot be deleted.' => 'Das Projekt ist in Verwendung und kann nicht gelöscht werden.',
+  'The project link has been updated.' => 'Die Projektverknüpfung wurde aktualisiert.',
   'The project number is already in use.' => 'Die Projektnummer wird bereits verwendet.',
   'The project number is missing.' => 'Die Projektnummer fehlt.',
   'The project status has been created.' => 'Der Projektstatus wurde angelegt.',
@@ -2565,6 +2573,7 @@ $self->{texts} = {
   'This option controls the method used for profit determination.' => 'Dieser Parameter legt die Berechnungsmethode für die Gewinnermittlung fest.',
   'This option controls the posting and calculation behavior for the accounting method.' => 'Dieser Parameter steuert die Buchungs- und Berechnungsmethoden für die Versteuerungsart.',
   'This partnumber is not unique. You should change it.' => 'Diese Artikelnummer ist nicht eindeutig. Bitte wählen Sie eine andere.',
+  'This requirement spec is currently linked to the following project:' => 'Dieses Pflichtenheft ist mit dem folgenden Projekt verknüpft:',
   'This requirement spec is currently not linked to a project.' => 'Dieses Pflichtenheft ist noch nicht mit einem Projekt verknüpft.',
   'This requires you to manually correct entries for which an automatic conversion failed and to check those for which it succeeded.' => 'Dies erfordert, dass Sie diejenigen Einträge manuell korrigieren, für die die automatische Umstellung fehlschlug, sowie dass Sie diejenigen überprüfen, für die die Umstellung erfolgreich war.',
   'This transaction has to be split into several transactions manually.' => 'Diese Buchung muss manuell in mehrere Buchungen aufgeteilt werden.',
diff --git a/templates/webpages/requirement_spec/_form.html b/templates/webpages/requirement_spec/_form.html
index dd760ed5d..5512294b8 100644
--- a/templates/webpages/requirement_spec/_form.html
+++ b/templates/webpages/requirement_spec/_form.html
@@ -3,6 +3,8 @@
             submit_as = 'post'
 %]
 <form method="post" action="controller.pl" id="[% id_prefix %]"[% UNLESS submit_as == 'post' %] class="edit-basic-settings-context-menu"[% END %]>
+ <h2>[% LxERP.t8("Edit general settings") %]</h2>
+
  [% L.hidden_tag("id", SELF.requirement_spec.id, id=id_prefix _ '_id') %]
  [% L.hidden_tag("requirement_spec.is_template", SELF.requirement_spec.is_template, id=id_prefix _ '_is_template') %]
 
diff --git a/templates/webpages/requirement_spec/_new_project_form.html b/templates/webpages/requirement_spec/_new_project_form.html
new file mode 100644
index 000000000..4b553dfd8
--- /dev/null
+++ b/templates/webpages/requirement_spec/_new_project_form.html
@@ -0,0 +1,51 @@
+[%- USE LxERP -%][%- USE L -%]
+[%- SET id_prefix = "project_link_form"
+        style     = "width: 300px" %]
+<form method="post" action="controller.pl" id="[% id_prefix %]"[% UNLESS submit_as == 'post' %] class="edit-project-link-context-menu"[% END %]>
+ <h2>[% LxERP.t8("Edit project link") %]: [% LxERP.t8("Create a new project") %]</h2>
+
+ [% L.hidden_tag("id", SELF.requirement_spec.id, id=id_prefix _ "_id") %]
+ [% L.hidden_tag("project_link_action", "create", id=id_prefix _ "_project_link_action") %]
+
+ <table class="rs_input_field">
+  <tr>
+   <td>[% LxERP.t8("Project Number") %]</td>
+   <td>[% L.input_tag("project.projectnumber", "", id=id_prefix _ "_projectnumber", style=style) %]</td>
+  </tr>
+
+  <tr>
+   <td>[% LxERP.t8("Description") %]</td>
+   <td>[% L.input_tag("project.description", SELF.requirement_spec.title, id=id_prefix _ "_description", style=style) %]</td>
+  </tr>
+
+  <tr>
+   <td>[% LxERP.t8("Project Type") %]</td>
+   <td>[% L.select_tag("project.project_type_id", SELF.project_types, default=SELF.default_project_type.id, title_key="description", id=id_prefix _ "_project_type_id", style=style) %]</td>
+  </tr>
+
+  <tr>
+   <td>[% LxERP.t8("Project Status") %]</td>
+   <td>[% L.select_tag("project.project_status_id", SELF.project_statuses, default=SELF.default_project_status.id, title_key="description", id=id_prefix _ "_project_status_id", style=style) %]</td>
+  </tr>
+
+  <tr>
+   <td>[% LxERP.t8("Customer") %]</td>
+   <td>[% L.select_tag("project.customer_id", SELF.customers, default=SELF.requirement_spec.customer_id, title_key="name", with_empty=1, id=id_prefix _ "_customer_id", style=style) %]</td>
+  </tr>
+ </table>
+
+ <p>
+  [% L.ajax_submit_tag("controller.pl?action=RequirementSpec/update_project_link",  "#" _ id_prefix, LxERP.t8("Save"), id=id_prefix _ '_submit') %]
+  <script type="text/javascript"><!--
+  $(function() {
+    $("#[% id_prefix %] INPUT[type=text]").keydown(function(event) {
+      if(event.keyCode == 13) {
+        event.preventDefault();
+        $('#[% id_prefix %]_submit').click();
+        return false;
+      }
+    });
+  });
+--></script>
+ </p>
+</form>
diff --git a/templates/webpages/requirement_spec/_project_link_details.html b/templates/webpages/requirement_spec/_project_link_details.html
new file mode 100644
index 000000000..2e45da50c
--- /dev/null
+++ b/templates/webpages/requirement_spec/_project_link_details.html
@@ -0,0 +1,27 @@
+[%- USE HTML -%][%- USE LxERP -%]
+<table>
+ <tr class="listrow">
+  <td>[% LxERP.t8("Project Number") %]:</td>
+  <td>[% HTML.escape(requirement_spec.project.projectnumber) %]</td>
+ </tr>
+
+ <tr class="listrow">
+  <td>[% LxERP.t8("Description") %]:</td>
+  <td>[% HTML.escape(requirement_spec.project.description) %]</td>
+ </tr>
+
+ <tr class="listrow">
+  <td>[% LxERP.t8("Customer") %]:</td>
+  <td>[% HTML.escape(requirement_spec.project.customer.name) %]</td>
+ </tr>
+
+ <tr class="listrow">
+  <td>[% LxERP.t8("Type") %]:</td>
+  <td>[% HTML.escape(requirement_spec.project.project_type.description) %]</td>
+ </tr>
+
+ <tr class="listrow">
+  <td>[% LxERP.t8("Status") %]:</td>
+  <td>[% HTML.escape(requirement_spec.project.project_status.description) %]</td>
+ </tr>
+</table>
diff --git a/templates/webpages/requirement_spec/_project_link_form.html b/templates/webpages/requirement_spec/_project_link_form.html
new file mode 100644
index 000000000..50951e8ee
--- /dev/null
+++ b/templates/webpages/requirement_spec/_project_link_form.html
@@ -0,0 +1,46 @@
+[%- USE LxERP -%][%- USE L -%]
+[%- SET id_prefix = "project_link_form" %]
+<form method="post" action="controller.pl" id="[% id_prefix %]"[% UNLESS submit_as == 'post' %] class="edit-project-link-context-menu"[% END %]>
+ <h2>[% LxERP.t8("Edit project link") %]</h2>
+
+ [% L.hidden_tag("id", SELF.requirement_spec.id, id=id_prefix _ "_id") %]
+
+ [% IF !SELF.requirement_spec.project_id %]
+  <p>[% LxERP.t8("This requirement spec is currently not linked to a project.") %]</p>
+
+ [% ELSE %]
+  <p>[% LxERP.t8("This requirement spec is currently linked to the following project:") %]</p>
+  [% INCLUDE "requirement_spec/_project_link_details.html" requirement_spec=SELF.requirement_spec %]
+ [% END %]
+
+ <table>
+  <tr><td colspan="2">[% L.radio_button_tag("project_link_action", id=id_prefix _ "_project_link_action_keep", value="keep", label=LxERP.t8("Keep the project link the way it is."), checked="1") %]</td></tr>
+  [% IF SELF.requirement_spec.project_id %]
+   <tr><td colspan="2">[% L.radio_button_tag("project_link_action", id=id_prefix _ "_project_link_action_none", value="none", label=LxERP.t8("Do not link to a project.")) %]</td></tr>
+  [% END %]
+  <tr><td colspan="2">[% L.radio_button_tag("project_link_action", id=id_prefix _ "_project_link_action_new", value="new", label=LxERP.t8("Create a new project and link to it.")) %]</td></tr>
+  <tr>
+   <td>[% L.radio_button_tag("project_link_action", id=id_prefix _ "_project_link_action_existing", value="existing", label=LxERP.t8("Link to the following project:")) %]</td>
+   <td>[% L.select_tag("new_project_id", SELF.projects, id=id_prefix _ "_new_project_id", title_key="full_description", disabled="true") %]</td>
+  </tr>
+ </table>
+
+ <p>
+  [% L.ajax_submit_tag("controller.pl?action=RequirementSpec/update_project_link",  "#" _ id_prefix, LxERP.t8("Save"), id=id_prefix _ "_submit") %]
+  <script type="text/javascript"><!--
+  $(function() {
+    $("#[% id_prefix %] INPUT[type=text]").keydown(function(event) {
+      if(event.keyCode == 13) {
+        event.preventDefault();
+        $('#[% id_prefix %]_submit').click();
+        return false;
+      }
+    });
+
+    $('[name=project_link_action]').change(function() {
+      $('#[% id_prefix %]_new_project_id').prop('disabled', !$('#[% id_prefix %]_project_link_action_existing').prop('checked'));
+    });
+  });
+--></script>
+ </p>
+</form>
diff --git a/templates/webpages/requirement_spec/_show_basic_settings.html b/templates/webpages/requirement_spec/_show_basic_settings.html
index 83b6d1ea8..db7bf49c2 100644
--- a/templates/webpages/requirement_spec/_show_basic_settings.html
+++ b/templates/webpages/requirement_spec/_show_basic_settings.html
@@ -48,33 +48,7 @@
   <p>[% LxERP.t8("This requirement spec is currently not linked to a project.") %]</p>
 
  [% ELSE %]
-  <table>
-   <tr class="listrow">
-    <td>[% LxERP.t8("Project Number") %]:</td>
-    <td>[% HTML.escape(SELF.requirement_spec.project.projectnumber) %]</td>
-   </tr>
-
-   <tr class="listrow">
-    <td>[% LxERP.t8("Description") %]:</td>
-    <td>[% HTML.escape(SELF.requirement_spec.project.description) %]</td>
-   </tr>
-
-   <tr class="listrow">
-    <td>[% LxERP.t8("Customer") %]:</td>
-    <td>[% HTML.escape(SELF.requirement_spec.project.customer.name) %]</td>
-   </tr>
-
-   <tr class="listrow">
-    <td>[% LxERP.t8("Type") %]:</td>
-    <td>[% HTML.escape(SELF.requirement_spec.project.project_type.description) %]</td>
-   </tr>
-
-   <tr class="listrow">
-    <td>[% LxERP.t8("Status") %]:</td>
-    <td>[% HTML.escape(SELF.requirement_spec.project.project_status.description) %]</td>
-   </tr>
-  </table>
-
+  [% INCLUDE 'requirement_spec/_project_link_details.html' requirement_spec=SELF.requirement_spec %]
  [% END %]
 [% END %]
 </div>
