Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 405a41ef

Von Moritz Bunkus vor fast 11 Jahren hinzugefügt

  • ID 405a41ef0836ac972a3ebb9e99f05de7d13d4275
  • Vorgänger c19b1e03
  • Nachfolger 48aa4607

Pflichtenhefte: Kopieren (clonen) generell und Löschen aus Kontextmenü implementiert

Unterschiede anzeigen:

SL/Controller/RequirementSpec.pm
use parent qw(SL::Controller::Base);
use Rose::DB::Object::Helpers;
use SL::ClientJS;
use SL::Controller::Helper::GetModels;
use SL::Controller::Helper::Paginated;
......
use Rose::Object::MakeMethods::Generic
(
scalar => [ qw(requirement_spec_item customers types statuses db_args flat_filter is_template visible_item visible_section) ],
'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects) ],
'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects copy_source) ],
);
__PACKAGE__->run_before('setup');
__PACKAGE__->run_before('load_select_options', only => [ qw(new ajax_edit create update list) ]);
__PACKAGE__->get_models_url_params('flat_filter');
__PACKAGE__->make_paginated(
MODEL => 'RequirementSpec',
......
my ($self) = @_;
$self->requirement_spec(SL::DB::RequirementSpec->new);
if ($self->copy_source) {
$self->requirement_spec->$_($self->copy_source->$_) for qw(type_id status_id customer_id title hourly_rate)
}
$self->render('requirement_spec/new', title => t8('Create a new requirement spec'));
}
......
$self->requirement_spec(SL::DB::RequirementSpec->new(id => $::form->{id})->load || die "No such requirement spec") if $::form->{id};
}
sub init_copy_source {
my ($self) = @_;
$self->copy_source(SL::DB::RequirementSpec->new(id => $::form->{copy_source_id})->load) if $::form->{copy_source_id};
}
sub load_select_options {
my ($self) = @_;
......
return;
}
$self->requirement_spec->save;
my $db = $self->requirement_spec->db;
if (!$db->do_transaction(sub {
if ($self->copy_source) {
$self->requirement_spec($self->copy_source->create_copy(%{ $params }));
} else {
$self->requirement_spec->save;
}
})) {
$::lxdebug->message(LXDebug::WARN(), "Error: " . $db->error);
@errors = ($::locale->text('Saving failed. Erro message from the database: #1'), $db->error);
return SL::ClientJS->new->error(@errors)->render($self) if $::request->is_ajax;
$self->requirement_spec->id(undef) if $is_new;
flash('error', @errors);
return $self->render('requirement_spec/new', title => $title);
}
if ($::request->is_ajax) {
my $html = $self->render('requirement_spec/_header', { output => 0 });
SL/DB/RequirementSpec.pm
use strict;
use Carp;
use Rose::DB::Object::Helpers;
use SL::DB::MetaSetup::RequirementSpec;
use SL::DB::Manager::RequirementSpec;
......
return sprintf('%s: "%s"', $self->type->description, $self->title);
}
sub create_copy {
my ($self, %params) = @_;
return $self->_create_copy(%params) if $self->db->in_transaction;
my $copy;
if (!$self->db->do_transaction(sub { $copy = $self->_create_copy(%params) })) {
$::lxdebug->message(LXDebug->WARN(), "create_copy failed: " . join("\n", (split(/\n/, $self->db->error))[0..2]));
return undef;
}
return $copy;
}
sub _create_copy {
my ($self, %params) = @_;
my $copy = Rose::DB::Object::Helpers::clone_and_reset($self);
$copy->assign_attributes(%params);
# Clone text blocks.
$copy->text_blocks(map { Rose::DB::Object::Helpers::clone_and_reset($_) } @{ $self->text_blocks });
# Save new object -- we need its ID for the items.
$copy->save;
my %id_to_clone;
# Clone items.
my $clone_item;
$clone_item = sub {
my ($item) = @_;
my $cloned = Rose::DB::Object::Helpers::clone_and_reset($item);
$cloned->requirement_spec_id($copy->id);
$cloned->children(map { $clone_item->($_) } @{ $item->children });
$id_to_clone{ $item->id } = $cloned;
return $cloned;
};
$copy->items(map { $clone_item->($_) } @{ $self->sections });
# Save the items -- need to do that before setting dependencies.
$copy->save;
# Set dependencies.
foreach my $item (@{ $self->items }) {
next unless @{ $item->dependencies };
$id_to_clone{ $item->id }->update_attributes(dependencies => [ map { $id_to_clone{$_->id} } @{ $item->dependencies } ]);
}
return $copy;
}
1;
js/locale/de.js
"Add text block":"Textblock erfassen",
"Are you sure?":"Sind Sie sicher?",
"Copy":"Kopieren",
"Copy requirement spec":"Pflichtenheft kopieren",
"Database Connection Test":"Test der Datenbankverbindung",
"Delete text block":"Textblock löschen",
"Delete":"Löschen",
"Delete requirement spec":"Pflichtenheft löschen",
"Delete text block":"Textblock löschen",
"Do you really want to cancel?":"Wollen Sie wirklich abbrechen?",
"Do you want to set the account number \"#1\" to \"#2\" and the name \"#3\" to \"#4\"?":"Soll die Kontonummer \"#1\" zu \"#2\" und den Name \"#3\" zu \"#4\" geändert werden?",
"Edit text block":"Textblock bearbeiten",
......
"Map":"Karte",
"Part picker":"Artikelauswahl",
"Paste":"Einfügen",
"Requirement spec actions:":"Pflichtenheftaktionen:",
"Save":"Speichern",
"The description is missing.":"Die Beschreibung fehlt.",
"The name is missing.":"Der Name fehlt.",
js/requirement_spec.js
return true;
}
// -------------------------------------------------------------------------
// ---------------------------- general actions ----------------------------
// -------------------------------------------------------------------------
function download_reqspec_pdf(key, opt) {
var data = {
action: "RequirementSpec/download_pdf",
id: $('#requirement_spec_id').val()
};
$.download("controller.pl", data);
}
function copy_reqspec(key, opt) {
window.location.href = "controller.pl?action=RequirementSpec/new&copy_source_id=" + encodeURIComponent($('#requirement_spec_id').val());
return true;
}
function delete_reqspec(key, opt) {
if (confirm(kivi.t8("Are you sure?")))
window.location.href = "controller.pl?action=RequirementSpec/destroy&id=" + encodeURIComponent($('#requirement_spec_id').val());
return true;
}
// -------------------------------------------------------------------------
// ----------------------------- context menus -----------------------------
// -------------------------------------------------------------------------
......
hide: requirement_spec_text_block_popup_menu_hidden
};
var general_actions = {
sep98: "---------"
, general_actions: { name: kivi.t8('Requirement spec actions:') }
, sep99: "---------"
, copy_reqspec: { name: kivi.t8('Copy requirement spec'), icon: "copy", callback: copy_reqspec }
, delete_reqspec: { name: kivi.t8('Delete requirement spec'), icon: "delete", callback: delete_reqspec }
};
$.contextMenu({
selector: '.text-block-context-menu',
events: {
show: requirement_spec_text_block_popup_menu_shown
, hide: requirement_spec_text_block_popup_menu_hidden
},
items: {
add: { name: kivi.t8('Add text block'), icon: "add", callback: standard_text_block_ajax_call }
, edit: { name: kivi.t8('Edit text block'), icon: "edit", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, delete: { name: kivi.t8('Delete text block'), icon: "delete", callback: ask_delete_text_block, disabled: disable_edit_text_block_commands }
, sep1: "---------"
, flag: { name: kivi.t8('Toggle marker'), icon: "flag", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, sep2: "---------"
, copy: { name: kivi.t8('Copy'), icon: "copy", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, paste: { name: kivi.t8('Paste'), icon: "paste", callback: standard_text_block_ajax_call }
}
items: $.extend({
add: { name: kivi.t8('Add text block'), icon: "add", callback: standard_text_block_ajax_call }
, edit: { name: kivi.t8('Edit text block'), icon: "edit", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, delete: { name: kivi.t8('Delete text block'), icon: "delete", callback: ask_delete_text_block, disabled: disable_edit_text_block_commands }
, sep1: "---------"
, flag: { name: kivi.t8('Toggle marker'), icon: "flag", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, sep2: "---------"
, copy: { name: kivi.t8('Copy'), icon: "copy", callback: standard_text_block_ajax_call, disabled: disable_edit_text_block_commands }
, paste: { name: kivi.t8('Paste'), icon: "paste", callback: standard_text_block_ajax_call }
}, general_actions)
});
var events = {
......
$.contextMenu({
selector: '.section-context-menu',
events: events,
items: {
items: $.extend({
add_section: { name: kivi.t8('Add section'), icon: "add", callback: standard_item_ajax_call }
, add_function_block: { name: kivi.t8('Add function block'), icon: "add", callback: standard_item_ajax_call, disabled: disable_add_function_block_command }
, sep1: "---------"
......
, sep3: "---------"
, copy: { name: kivi.t8('Copy'), icon: "copy", callback: standard_item_ajax_call, disabled: disable_edit_item_commands }
, paste: { name: kivi.t8('Paste'), icon: "paste", callback: standard_item_ajax_call }
}
}, general_actions)
});
$.contextMenu({
selector: '.function-block-context-menu,.sub-function-block-context-menu',
events: events,
items: {
items: $.extend({
add_function_block: { name: kivi.t8('Add function block'), icon: "add", callback: standard_item_ajax_call }
, add_sub_function_block: { name: kivi.t8('Add sub function block'), icon: "add", callback: standard_item_ajax_call }
, sep1: "---------"
......
, sep3: "---------"
, copy: { name: kivi.t8('Copy'), icon: "copy", callback: standard_item_ajax_call, disabled: disable_edit_item_commands }
, paste: { name: kivi.t8('Paste'), icon: "paste", callback: standard_item_ajax_call }
}
}, general_actions)
});
$.contextMenu({
selector: '.time-cost-estimate-context-menu',
events: events,
items: { edit: { name: kivi.t8('Edit'), icon: "edit", callback: standard_time_cost_estimate_ajax_call } }
items: $.extend({ edit: { name: kivi.t8('Edit'), icon: "edit", callback: standard_time_cost_estimate_ajax_call } }, general_actions)
});
$.contextMenu({
selector: '.edit-time-cost-estimate-context-menu',
events: events,
items: {
items: $.extend({
save: { name: kivi.t8('Save'), icon: "save", callback: standard_time_cost_estimate_ajax_call }
, cancel: { name: kivi.t8('Cancel'), icon: "close", callback: standard_time_cost_estimate_ajax_call }
}
}, general_actions)
});
}
locale/de/all
'Copies' => 'Kopien',
'Copy file from #1 to #2 failed: #3' => 'Kopieren der Datei von #1 nach #2 schlug fehl: #3',
'Copy' => 'Kopieren',
'Copy requirement spec' => 'Pflichtenheft kopieren',
'Correct taxkey' => 'Richtiger Steuerschlüssel',
'Cost' => 'Kosten',
'Costs' => 'Kosten',
......
'Delete drafts' => 'Entwürfe löschen',
'Delete links' => 'Verknüpfungen löschen',
'Delete profile' => 'Profil löschen',
'Delete requirement spec' => 'Pflichtenheft löschen',
'Delete text block' => 'Textblock löschen',
'Delete transaction' => 'Buchung löschen',
'Deleted' => 'Gelöscht',
......
'Requirement Spec Type' => 'Pflichtenhefttyp',
'Requirement Spec Types' => 'Pflichtenhefttypen',
'Requirement Specs' => 'Pflichtenhefte',
'Requirement spec actions:' => 'Pflichtenheftaktionen:',
'Requirement spec function block #1 with #2 sub function blocks; description: "#3"' => 'Pflichtenheft-Funktionsblock #1 mit #2 Unterfunktionsblöcken; Beschreibung: "#3"',
'Requirement spec section #1 "#2" with #3 function blocks and a total of #4 sub function blocks; preamble: "#5"' => 'Pflichtenheftabschnitt #1 "#2" mit #3 Funktionsblöcken und insgesamt #4 Unterfunktionsblöcken; Einleitung: "#5"',
'Requirement spec sub function block #1; description: "#2"' => 'Pflichtenheft-Unterfunktionsblock #1; Beschreibung: "#2"',
......
'Save draft' => 'Entwurf speichern',
'Save profile' => 'Profil speichern',
'Save settings as' => 'Einstellungen speichern unter',
'Saving failed. Erro message from the database: #1' => 'Speichern schlug fehl. Fehlermeldung der Datenbank: #1',
'Saving the file \'%s\' failed. OS error message: %s' => 'Das Speichern der Datei \'%s\' schlug fehl. Fehlermeldung des Betriebssystems: %s',
'Screen' => 'Bildschirm',
'Search' => 'Suchen',
......
'The name is missing.' => 'Der Name fehlt.',
'The name is not unique.' => 'Der Name ist nicht eindeutig.',
'The name must only consist of letters, numbers and underscores and start with a letter.' => 'Der Name darf nur aus Buchstaben (keine Umlaute), Ziffern und Unterstrichen bestehen und muss mit einem Buchstaben beginnen.',
'The new requirement spec will be a copy of \'#1\' for customer \'#2\'.' => 'Das neue Pflichtenheft wird eine Kopie von \'#1\' für Kunde \'#2\' sein.',
'The number of days for full payment' => 'Die Anzahl Tage, bis die Rechnung in voller Höhe bezahlt werden muss',
'The option field is empty.' => 'Das Optionsfeld ist leer.',
'The package name is invalid.' => 'Der Paketname ist ungültig.',
templates/webpages/requirement_spec/_form.html
</table>
[%- IF SELF.copy_source %]
[%- L.hidden_tag('copy_source_id', SELF.copy_source.id) %]
<p>
[%- LxERP.t8("The new requirement spec will be a copy of '#1' for customer '#2'.", SELF.copy_source.title, SELF.copy_source.customer.name) %]
</p>
[%- END %]
<p>
[% IF submit_as == 'post' %]
[% L.hidden_tag("action", "RequirementSpec/dispatch", id=id_prefix _ '_action') %]

Auch abrufbar als: Unified diff