Revision c1569bc1
Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt
SL/Controller/RequirementSpec.pm | ||
---|---|---|
19 | 19 |
|
20 | 20 |
use Rose::Object::MakeMethods::Generic |
21 | 21 |
( |
22 |
scalar => [ qw(requirement_spec customers projects types statuses db_args flat_filter is_template) ], |
|
22 |
scalar => [ qw(requirement_spec requirement_spec_item customers projects types statuses db_args flat_filter is_template) ],
|
|
23 | 23 |
); |
24 | 24 |
|
25 | 25 |
__PACKAGE__->run_before('setup'); |
26 |
__PACKAGE__->run_before('load_requirement_spec', only => [ qw( edit update destroy tree) ]); |
|
26 |
__PACKAGE__->run_before('load_requirement_spec', only => [ qw( edit update show destroy tree) ]);
|
|
27 | 27 |
__PACKAGE__->run_before('load_select_options', only => [ qw(new edit create update list) ]); |
28 | 28 |
__PACKAGE__->run_before('load_search_select_options', only => [ qw( list) ]); |
29 | 29 |
|
... | ... | |
77 | 77 |
$self->render('requirement_spec/form', title => t8('Edit requirement spec')); |
78 | 78 |
} |
79 | 79 |
|
80 |
sub action_show { |
|
81 |
my ($self) = @_; |
|
82 |
|
|
83 |
my $item = $::form->{requirement_spec_item_id} ? SL::DB::RequirementSpecItem->new(id => $::form->{requirement_spec_item_id})->load : @{ $self->requirement_spec->sections }[0]; |
|
84 |
$self->requirement_spec_item($item); |
|
85 |
|
|
86 |
$self->render('requirement_spec/show', title => t8('Show requirement spec')); |
|
87 |
} |
|
88 |
|
|
80 | 89 |
sub action_create { |
81 | 90 |
my ($self) = @_; |
82 | 91 |
|
... | ... | |
122 | 131 |
my ($self) = @_; |
123 | 132 |
|
124 | 133 |
$::auth->assert('config'); |
125 |
$::request->{layout}->use_stylesheet("${_}.css") for qw(requirement_spec yaml/core/base.min);
|
|
126 |
$::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree requirement_spec); |
|
134 |
$::request->{layout}->use_stylesheet("${_}.css") for qw(jquery.contextMenu requirement_spec);
|
|
135 |
$::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree jquery/jquery.contextMenu requirement_spec);
|
|
127 | 136 |
$self->is_template($::form->{is_template} ? 1 : 0); |
128 | 137 |
|
129 | 138 |
return 1; |
SL/Controller/RequirementSpecItem.pm | ||
---|---|---|
18 | 18 |
); |
19 | 19 |
|
20 | 20 |
# __PACKAGE__->run_before('load_requirement_spec'); |
21 |
__PACKAGE__->run_before('load_requirement_spec_item', only => [qw(dragged_and_dropped)]); |
|
21 |
__PACKAGE__->run_before('load_requirement_spec_item', only => [qw(dragged_and_dropped edit_section update_section)]);
|
|
22 | 22 |
|
23 | 23 |
# |
24 | 24 |
# actions |
... | ... | |
64 | 64 |
$self->render(\'', { type => 'json' }); |
65 | 65 |
} |
66 | 66 |
|
67 |
sub action_edit_section { |
|
68 |
my ($self, %params) = @_; |
|
69 |
$self->render('requirement_spec_item/_section_form', { layout => 0 }); |
|
70 |
} |
|
71 |
|
|
72 |
sub action_update_section { |
|
73 |
my ($self, %params) = @_; |
|
74 |
|
|
75 |
$self->item->update_attributes(title => $::form->{title}, description => $::form->{description}); |
|
76 |
|
|
77 |
my $result = { |
|
78 |
id => $self->item->id, |
|
79 |
header_html => $self->render('requirement_spec_item/_section_header', { layout => 0, output => 0 }, requirement_spec_item => $self->item), |
|
80 |
node_name => join(' ', map { $_ || '' } ($self->item->fb_number, $self->item->title)), |
|
81 |
}; |
|
82 |
$self->render(\to_json($result), { type => 'json' }); |
|
83 |
} |
|
84 |
|
|
67 | 85 |
# |
68 | 86 |
# filters |
69 | 87 |
# |
SL/DB/RequirementSpec.pm | ||
---|---|---|
57 | 57 |
return [ sort { $a->position <=> $b->position } grep { !$_->parent_id } @{ $self->items } ]; |
58 | 58 |
} |
59 | 59 |
|
60 |
sub displayable_name { |
|
61 |
my ($self) = @_; |
|
62 |
|
|
63 |
return sprintf('%s: "%s"', $self->type->description, $self->title); |
|
64 |
} |
|
65 |
|
|
60 | 66 |
1; |
SL/Presenter.pm | ||
---|---|---|
16 | 16 |
use SL::Presenter::Project; |
17 | 17 |
use SL::Presenter::Record; |
18 | 18 |
use SL::Presenter::RequirementSpec; |
19 |
use SL::Presenter::RequirementSpecItem; |
|
19 | 20 |
use SL::Presenter::SepaExport; |
20 | 21 |
use SL::Presenter::Text; |
21 | 22 |
use SL::Presenter::Tag; |
SL/Presenter/RequirementSpec.pm | ||
---|---|---|
5 | 5 |
use parent qw(Exporter); |
6 | 6 |
|
7 | 7 |
use Exporter qw(import); |
8 |
our @EXPORT = qw(requirement_spec_text_block_jstree_data |
|
9 |
requirement_spec_item_jstree_data); |
|
8 |
our @EXPORT = qw(requirement_spec_text_block_jstree_data); |
|
10 | 9 |
|
11 | 10 |
use Carp; |
12 | 11 |
|
... | ... | |
22 | 21 |
}; |
23 | 22 |
} |
24 | 23 |
|
25 |
sub requirement_spec_item_jstree_data { |
|
26 |
my ($self, $item, %params) = @_; |
|
27 |
|
|
28 |
my @children = map { $self->requirement_spec_item_jstree_data($_, %params) } @{ $item->sorted_children }; |
|
29 |
my $type = !$item->parent_id ? 'section' : 'functionblock'; |
|
30 |
|
|
31 |
return { |
|
32 |
data => join(' ', map { $_ || '' } ($item->fb_number, $item->title)), |
|
33 |
metadata => { id => $item->id, type => $type }, |
|
34 |
attr => { id => "fb-" . $item->id, href => $params{href} || '#' }, |
|
35 |
children => \@children, |
|
36 |
}; |
|
37 |
} |
|
38 |
|
|
39 | 24 |
1; |
SL/Presenter/RequirementSpecItem.pm | ||
---|---|---|
1 |
package SL::Presenter::RequirementSpecItem; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(Exporter); |
|
6 |
|
|
7 |
use Exporter qw(import); |
|
8 |
our @EXPORT = qw(requirement_spec_item_jstree_data requirement_spec_item_dependency_list); |
|
9 |
|
|
10 |
use Carp; |
|
11 |
|
|
12 |
sub requirement_spec_item_jstree_data { |
|
13 |
my ($self, $item, %params) = @_; |
|
14 |
|
|
15 |
my @children = map { $self->requirement_spec_item_jstree_data($_, %params) } @{ $item->sorted_children }; |
|
16 |
my $type = !$item->parent_id ? 'section' : 'functionblock'; |
|
17 |
|
|
18 |
return { |
|
19 |
data => join(' ', map { $_ || '' } ($item->fb_number, $item->title)), |
|
20 |
metadata => { id => $item->id, type => $type }, |
|
21 |
attr => { id => "fb-" . $item->id, href => $params{href} || '#' }, |
|
22 |
children => \@children, |
|
23 |
}; |
|
24 |
} |
|
25 |
|
|
26 |
sub requirement_spec_item_dependency_list { |
|
27 |
my ($self, $item) = @_; |
|
28 |
|
|
29 |
$::locale->language_join([ map { $_->fb_number } @{ $item->dependencies } ]); |
|
30 |
} |
|
31 |
|
|
32 |
1; |
css/requirement_spec.css | ||
---|---|---|
3 | 3 |
width: 300px; |
4 | 4 |
} |
5 | 5 |
|
6 |
#column-container { |
|
7 |
width: 100%; |
|
8 |
padding-left: 0; |
|
9 |
padding-right: 0; |
|
10 |
margin-left: 0; |
|
11 |
margin-right: 0; |
|
12 |
} |
|
13 |
|
|
14 |
#tree-column { |
|
15 |
float: left; |
|
16 |
width: 25%; |
|
17 |
border-right: 1px solid black; |
|
18 |
} |
|
19 |
|
|
6 | 20 |
#content-column { |
7 |
margin-left: 10px; |
|
21 |
float: left; |
|
22 |
padding-left: 10px; |
|
23 |
} |
|
24 |
|
|
25 |
.section-empty-description { |
|
26 |
color: #bbb; |
|
8 | 27 |
} |
templates/webpages/requirement_spec/_version.html | ||
---|---|---|
1 |
[%- USE L -%][%- USE LxERP -%][%- USE HTML -%] |
|
2 |
[% L.stuff %] |
|
3 |
[% LxERP.t8("Current version") %]: |
|
4 |
[% IF !requirement_spec.version_id %] |
|
5 |
[% LxERP.t8("Working copy without version") %] |
|
6 |
[% ELSE %] |
|
7 |
[% LxERP.t8("Version") %] [% HTML.escape(requirement_spec.version.version_number) %] |
|
8 |
[% LxERP.t8("dated") %] [% HTML.escape(requirement_spec.version.itime.displayable_date) %] |
|
9 |
[%- END -%] |
templates/webpages/requirement_spec/show.html | ||
---|---|---|
1 |
[%- USE JSON -%][%- USE HTML %][%- USE L %][%- USE LxERP %][%- USE P -%] |
|
2 |
|
|
3 |
<h1>[%- HTML.escape(SELF.requirement_spec.displayable_name('format', 'with_customer')) %] |
|
4 |
[% LxERP.t8("for") %] |
|
5 |
[% HTML.escape(SELF.requirement_spec.customer.displayable_name) -%] |
|
6 |
</h1> |
|
7 |
|
|
8 |
[%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id) -%] |
|
9 |
|
|
10 |
<div id="requirement_spec_version"> |
|
11 |
[%- INCLUDE 'requirement_spec/_version.html' requirement_spec=SELF.requirement_spec -%] |
|
12 |
</div> |
|
13 |
|
|
14 |
<div id="column-container"> |
|
15 |
<div id="tree-column" style="border-right: 1px solid black"> |
|
16 |
<div style="min-height: 32px; height: 32px;"> |
|
17 |
<div style="float: left"> |
|
18 |
[% L.button_tag("new_section_form()", LxERP.t8("New section"), id="new-section-button") %] |
|
19 |
</div> |
|
20 |
<div id="spinner" class="clearfix" style="float: right; display: none; background:url('js/themes/requirement-spec/throbber.gif') center center no-repeat !important; min-height: 32px; height: 32px; min-width: 32px; width: 32px;"></div> |
|
21 |
</div> |
|
22 |
|
|
23 |
<div id="tree"></div> |
|
24 |
</div> |
|
25 |
|
|
26 |
<div id="content-column" class="clearfix"> |
|
27 |
<div id="section-container" class="section-container"> |
|
28 |
|
|
29 |
<div id="section_content" class="section-content"> |
|
30 |
[%- IF SELF.requirement_spec_item && SELF.requirement_spec_item.id -%] |
|
31 |
[%- INCLUDE 'requirement_spec_item/_single_section.html' requirement_spec_item=SELF.requirement_spec_item -%] |
|
32 |
[%- ELSE -%] |
|
33 |
no section |
|
34 |
[%#- render :partial => 'requirement_spec_items/no_section' -%] |
|
35 |
[%- END -%] |
|
36 |
</div> |
|
37 |
</div> |
|
38 |
</div> |
|
39 |
</div> |
|
40 |
|
|
41 |
<script type="text/javascript"> |
|
42 |
<!-- |
|
43 |
var tree_data = [ |
|
44 |
{ "data": [% JSON.json(LxERP.t8("Text blocks front")) %], |
|
45 |
"metadata": { "type": "textblocks-front" }, |
|
46 |
"attr": { "id": "tb-front" }, |
|
47 |
"children": [ |
|
48 |
[% FOREACH tb = SELF.requirement_spec.text_blocks_for_position(0) %] |
|
49 |
[% P.requirement_spec_text_block_jstree_data(tb).json %][% IF !loop.last %],[% END %] |
|
50 |
[% END %] |
|
51 |
] |
|
52 |
}, |
|
53 |
|
|
54 |
{ "data": [% JSON.json(LxERP.t8("Sections")) %], |
|
55 |
"metadata": { "type": "sections" }, |
|
56 |
"attr": { "id": "sections" }, |
|
57 |
"children": [ |
|
58 |
|
|
59 |
[% FOREACH section = SELF.requirement_spec.sections %] |
|
60 |
[% P.requirement_spec_item_jstree_data(section).json %][% IF !loop.last %],[% END %] |
|
61 |
[% END %] |
|
62 |
] |
|
63 |
}, |
|
64 |
|
|
65 |
{ "data": [% JSON.json(LxERP.t8("Text blocks back")) %], |
|
66 |
"metadata": { "type": "textblocks-back" }, |
|
67 |
"attr": { "id": "tb-back" }, |
|
68 |
"children": [ |
|
69 |
[% FOREACH tb = SELF.requirement_spec.text_blocks_for_position(1) %] |
|
70 |
[% P.requirement_spec_text_block_jstree_data(tb).json %][% IF !loop.last %],[% END %] |
|
71 |
[% END %] |
|
72 |
] |
|
73 |
} |
|
74 |
]; |
|
75 |
|
|
76 |
$(function() { |
|
77 |
$('#tree').jstree({ |
|
78 |
"core": { |
|
79 |
"animation": 0, |
|
80 |
"initially_open": [ "tb-front", "tb-back", "sections" |
|
81 |
[%- FOREACH section = SELF.requirement_spec.sections -%] |
|
82 |
, "fb-[% section.id %]" |
|
83 |
[%- FOREACH function_block = section.children -%] |
|
84 |
, "fb-[% function_block.id -%]" |
|
85 |
[%- END -%] |
|
86 |
[%- END -%] |
|
87 |
] |
|
88 |
}, |
|
89 |
"json_data": { |
|
90 |
"data": tree_data |
|
91 |
}, |
|
92 |
"crrm": { |
|
93 |
"move": { |
|
94 |
"check_move": check_move, |
|
95 |
"open_move": true |
|
96 |
} |
|
97 |
}, |
|
98 |
"themes": { |
|
99 |
"theme": "requirement-spec" |
|
100 |
}, |
|
101 |
"plugins": [ "themes", "json_data", "ui", "crrm", "dnd" ] |
|
102 |
}) |
|
103 |
.bind("move_node.jstree", node_moved); |
|
104 |
|
|
105 |
$(document).ajaxSend(function() { |
|
106 |
$('#spinner').show(); |
|
107 |
}).ajaxStop(function() { |
|
108 |
$('#spinner').hide(); |
|
109 |
}); |
|
110 |
}); |
|
111 |
--> |
|
112 |
</script> |
templates/webpages/requirement_spec/tree.html | ||
---|---|---|
2 | 2 |
|
3 | 3 |
[%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id) -%] |
4 | 4 |
|
5 |
<div id="page" class="ym-grid ym-equalize">
|
|
6 |
<div class="ym-g25 ym-gl" style="border-right: 1px solid black">
|
|
5 |
<div id="column-container">
|
|
6 |
<div id="tree-column">
|
|
7 | 7 |
<div style="min-height: 32px; height: 32px;"> |
8 | 8 |
<div style="float: left"> |
9 | 9 |
[% L.button_tag("new_section_form()", LxERP.t8("New section"), id="new-section-button") %] |
10 | 10 |
</div> |
11 |
<div id="spinner" style="float: right; display: none; background:url('js/themes/requirement-spec/throbber.gif') center center no-repeat !important; min-height: 32px; height: 32px; min-width: 32px; width: 32px;"></div> |
|
12 | 11 |
<div style="clear: both"></div> |
13 | 12 |
</div> |
14 | 13 |
|
15 | 14 |
<div id="tree"></div> |
16 | 15 |
</div> |
17 | 16 |
|
18 |
<div class="ym-gl"> |
|
19 |
<div id="content-column"> |
|
20 |
<p>There's beauty in the breakdown. 0</p> |
|
21 |
<p>There's beauty in the breakdown. 1</p> |
|
22 |
<p>There's beauty in the breakdown. 2</p> |
|
23 |
<p>There's beauty in the breakdown. 3</p> |
|
24 |
<p>There's beauty in the breakdown. 4</p> |
|
25 |
<p>There's beauty in the breakdown. 5</p> |
|
26 |
<p>There's beauty in the breakdown. 6</p> |
|
27 |
<p>There's beauty in the breakdown. 7</p> |
|
28 |
<p>There's beauty in the breakdown. 8</p> |
|
29 |
<p>There's beauty in the breakdown. 9</p> |
|
30 |
<p>There's beauty in the breakdown. 10</p> |
|
31 |
<p>There's beauty in the breakdown. 11</p> |
|
32 |
<p>There's beauty in the breakdown. 12</p> |
|
33 |
<p>There's beauty in the breakdown. 13</p> |
|
34 |
<p>There's beauty in the breakdown. 14</p> |
|
35 |
<p>There's beauty in the breakdown. 15</p> |
|
36 |
<p>There's beauty in the breakdown. 16</p> |
|
37 |
<p>There's beauty in the breakdown. 17</p> |
|
38 |
<p>There's beauty in the breakdown. 18</p> |
|
39 |
<p>There's beauty in the breakdown. 19</p> |
|
40 |
<p>There's beauty in the breakdown. 20</p> |
|
41 |
<p>There's beauty in the breakdown. 21</p> |
|
42 |
<p>There's beauty in the breakdown. 22</p> |
|
43 |
<!-- <p>There's beauty in the breakdown. 23</p> --> |
|
44 |
<!-- <p>There's beauty in the breakdown. 24</p> --> |
|
45 |
<!-- <p>There's beauty in the breakdown. 25</p> --> |
|
46 |
<!-- <p>There's beauty in the breakdown. 26</p> --> |
|
47 |
<!-- <p>There's beauty in the breakdown. 27</p> --> |
|
48 |
<!-- <p>There's beauty in the breakdown. 28</p> --> |
|
49 |
<!-- <p>There's beauty in the breakdown. 29</p> --> |
|
50 |
<!-- <p>There's beauty in the breakdown. 30</p> --> |
|
51 |
<!-- <p>There's beauty in the breakdown. 31</p> --> |
|
52 |
<!-- <p>There's beauty in the breakdown. 32</p> --> |
|
53 |
<!-- <p>There's beauty in the breakdown. 33</p> --> |
|
54 |
<!-- <p>There's beauty in the breakdown. 34</p> --> |
|
55 |
<!-- <p>There's beauty in the breakdown. 35</p> --> |
|
56 |
</div> |
|
17 |
<div id="content-column" class="clearfix"> |
|
18 |
<p>There's beauty in the breakdown. 0</p> |
|
19 |
<p>There's beauty in the breakdown. 1</p> |
|
20 |
<p>There's beauty in the breakdown. 2</p> |
|
21 |
<p>There's beauty in the breakdown. 3</p> |
|
22 |
<p>There's beauty in the breakdown. 4</p> |
|
23 |
<p>There's beauty in the breakdown. 5</p> |
|
24 |
<p>There's beauty in the breakdown. 6</p> |
|
25 |
<p>There's beauty in the breakdown. 7</p> |
|
26 |
<p>There's beauty in the breakdown. 8</p> |
|
27 |
<p>There's beauty in the breakdown. 9</p> |
|
28 |
<p>There's beauty in the breakdown. 10</p> |
|
29 |
<p>There's beauty in the breakdown. 11</p> |
|
30 |
<p>There's beauty in the breakdown. 12</p> |
|
31 |
<p>There's beauty in the breakdown. 13</p> |
|
32 |
<p>There's beauty in the breakdown. 14</p> |
|
33 |
<p>There's beauty in the breakdown. 15</p> |
|
34 |
<p>There's beauty in the breakdown. 16</p> |
|
35 |
<p>There's beauty in the breakdown. 17</p> |
|
36 |
<p>There's beauty in the breakdown. 18</p> |
|
37 |
<p>There's beauty in the breakdown. 19</p> |
|
38 |
<p>There's beauty in the breakdown. 20</p> |
|
39 |
<p>There's beauty in the breakdown. 21</p> |
|
40 |
<p>There's beauty in the breakdown. 22</p> |
|
41 |
<!-- <p>There's beauty in the breakdown. 23</p> --> |
|
42 |
<!-- <p>There's beauty in the breakdown. 24</p> --> |
|
43 |
<!-- <p>There's beauty in the breakdown. 25</p> --> |
|
44 |
<!-- <p>There's beauty in the breakdown. 26</p> --> |
|
45 |
<!-- <p>There's beauty in the breakdown. 27</p> --> |
|
46 |
<!-- <p>There's beauty in the breakdown. 28</p> --> |
|
47 |
<!-- <p>There's beauty in the breakdown. 29</p> --> |
|
48 |
<!-- <p>There's beauty in the breakdown. 30</p> --> |
|
49 |
<!-- <p>There's beauty in the breakdown. 31</p> --> |
|
50 |
<!-- <p>There's beauty in the breakdown. 32</p> --> |
|
51 |
<!-- <p>There's beauty in the breakdown. 33</p> --> |
|
52 |
<!-- <p>There's beauty in the breakdown. 34</p> --> |
|
53 |
<!-- <p>There's beauty in the breakdown. 35</p> --> |
|
57 | 54 |
</div> |
58 | 55 |
</div> |
59 | 56 |
|
... | ... | |
121 | 118 |
}) |
122 | 119 |
.bind("move_node.jstree", node_moved); |
123 | 120 |
}); |
124 |
|
|
125 |
$(document).ajaxSend(function() { |
|
126 |
$('#spinner').show(); |
|
127 |
}).ajaxStop(function() { |
|
128 |
$('#spinner').hide(); |
|
129 |
}); |
|
130 | 121 |
--> |
131 | 122 |
</script> |
templates/webpages/requirement_spec_item/_section_form.html | ||
---|---|---|
1 | 1 |
[%- USE HTML %][%- USE L %][%- USE LxERP %] |
2 |
[%- SET id_base="section-form-" _ HTML.escape(id) %] |
|
3 |
[%- IF title %] |
|
4 |
<div class="listtop">[%- HTML.escape(title) %]</div> |
|
5 |
[%- END -%] |
|
2 |
[%- SET id_base="section-form" %] |
|
3 |
<div id="[% id_base %]"> |
|
4 |
<h1>[%- LxERP.t8("Edit section #1", SELF.item.fb_number) %]</h1> |
|
6 | 5 |
|
7 |
<form id="[% id_base %]"> |
|
8 |
[% L.hidden_tag("requirment_spec_id", SELF.item.requirement_spec_id, id=(id_base _ "-requirement-spec-id")) %] |
|
6 |
<form> |
|
7 |
[% L.hidden_tag("requirement_spec_id", SELF.item.requirement_spec_id, id=(id_base _ "-requirement-spec-id")) %] |
|
8 |
[% L.hidden_tag("id", SELF.item.id, id=(id_base _ "-requirement-spec-item-id")) %] |
|
9 | 9 |
|
10 |
<p> |
|
11 |
[%- LxERP.t8("Title") %]:<br> |
|
12 |
[% L.input_tag("title", SELF.item.title, id=(id_base _ "-title")) %] |
|
13 |
</p> |
|
10 |
<p>
|
|
11 |
[%- LxERP.t8("Title") %]:<br>
|
|
12 |
[% L.input_tag("title", SELF.item.title, id=(id_base _ "-title")) %]
|
|
13 |
</p>
|
|
14 | 14 |
|
15 |
<p> |
|
16 |
[%- LxERP.t8("Description") %]:<br> |
|
17 |
[% L.textarea_tag("description", SELF.item.description, id=(id_base _ "-title"), rows=8, cols=80) %]
|
|
18 |
</p> |
|
15 |
<p>
|
|
16 |
[%- LxERP.t8("Description") %]:<br>
|
|
17 |
[% L.textarea_tag("description", SELF.item.description, id=(id_base _ "-description"), rows=8, cols=80) %]
|
|
18 |
</p>
|
|
19 | 19 |
|
20 |
<p> |
|
21 |
[% L.button_tag("submit_section_form('" _ HTML.escape(id) _ "')", LxERP.t8("Save")) %] |
|
22 |
[% L.button_tag("cancel_section_form('" _ HTML.escape(id) _ "')", LxERP.t8("Cancel")) %] |
|
23 |
</p> |
|
24 |
</form> |
|
20 |
<p> |
|
21 |
[% L.button_tag("submit_section_form()", LxERP.t8("Save")) %] |
|
22 |
<a href="#" onclick="cancel_section_form()">[% LxERP.t8("Cancel") %]</a> |
|
23 |
</p> |
|
24 |
</form> |
|
25 |
</div> |
templates/webpages/requirement_spec_item/_section_header.html | ||
---|---|---|
1 |
[%- USE HTML -%][%- USE L -%][%- USE LxERP -%] |
|
2 |
<h1> |
|
3 |
[%- HTML.escape(requirement_spec_item.fb_number) %]: [% HTML.escape(requirement_spec_item.title) -%] |
|
4 |
</h1> |
|
5 |
|
|
6 |
[% IF requirement_spec_item.description %] |
|
7 |
<div class="section-description"> |
|
8 |
[%- L.simple_format(requirement_spec_item.description) -%] |
|
9 |
</div> |
|
10 |
[%- ELSE %] |
|
11 |
<div class="section-empty-description">[%- LxERP.t8("No description has been entered yet.") %]</div> |
|
12 |
[%- END %] |
templates/webpages/requirement_spec_item/_single_section.html | ||
---|---|---|
1 |
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%] |
|
2 |
<div class="section-context-menu" id="section-header"> |
|
3 |
[%- INCLUDE 'requirement_spec_item/_section_header.html' %] |
|
4 |
</div> |
|
5 |
|
|
6 |
[%- L.hidden_tag('active_section_id', requirement_spec_item.id) -%] |
|
7 |
|
|
8 |
<ul id="section" class="section function-block-context-menu"> |
|
9 |
[%- FOREACH subitem = requirement_spec_item.children -%] |
|
10 |
[%- INCLUDE 'requirement_spec_item/_single_subitem.html' requirement_spec_item=subitem -%] |
|
11 |
[%- END -%] |
|
12 |
</ul> |
|
13 |
|
|
14 |
<div id="new_subitem_form" class="subitem-form clearfix"> |
|
15 |
</div> |
|
16 |
<div id="new_subitem_link" class="highlight-box" style="[%- 'display:none' IF requirement_spec_item.children.size -%]"> |
|
17 |
[%#- link_to_remote LxERP.t8("FIXME no_function_blocks_have_been_created_for_this_section_yet) + " " + t(:create_a_function_block_now"), |
|
18 |
:url => new_requirement_spec_requirement_spec_item_url(requirement_spec_item.requirement_spec, |
|
19 |
:requirement_spec_item_id => requirement_spec_item.id), |
|
20 |
:method => :get, |
|
21 |
:update => "new_subitem_form", |
|
22 |
:loading => "$('new_subitem_link').hide();" -%] |
|
23 |
</div> |
|
24 |
|
|
25 |
<script type="text/javascript"> |
|
26 |
<!-- |
|
27 |
$(function(){ |
|
28 |
$.contextMenu({ |
|
29 |
selector: '.section-context-menu', |
|
30 |
callback: function(key, options) { |
|
31 |
var m = "clicked: " + key; |
|
32 |
window.console && console.log(m) || alert(m); |
|
33 |
}, |
|
34 |
items: { |
|
35 |
edit: { name: "[% LxERP.t8('Edit section') %]", icon: "edit", callback: edit_section_header }, |
|
36 |
delete: { name: "[% LxERP.t8('Delete section') %]", icon: "delete" }, |
|
37 |
sep1: "---------", |
|
38 |
copy: { name: "[% LxERP.t8('Copy') %]", icon: "copy" }, |
|
39 |
paste: { name: "[% LxERP.t8('Paste') %]", icon: "paste" } |
|
40 |
} |
|
41 |
}); |
|
42 |
|
|
43 |
$.contextMenu({ |
|
44 |
selector: '.function-block-context-menu', |
|
45 |
callback: function(key, options) { |
|
46 |
var m = "clicked: " + key; |
|
47 |
window.console && console.log(m) || alert(m); |
|
48 |
}, |
|
49 |
items: { |
|
50 |
new_item: { name: "[% LxERP.t8('New function block') %]", icon: "add"}, |
|
51 |
new_sub_item: { name: "[% LxERP.t8('New sub function block') %]", icon: "add"}, |
|
52 |
sep1: "---------", |
|
53 |
edit: { name: "[% LxERP.t8('Edit') %]", icon: "edit"}, |
|
54 |
delete: { name: "[% LxERP.t8('Delete') %]", icon: "delete"}, |
|
55 |
sep2: "---------", |
|
56 |
copy: { name: "[% LxERP.t8('Copy') %]", icon: "copy" }, |
|
57 |
paste: { name: "[% LxERP.t8('Paste') %]", icon: "paste" } |
|
58 |
} |
|
59 |
}); |
|
60 |
|
|
61 |
$('.section-context-menu').on('click', function(e){ |
|
62 |
console.log('clicked', this); |
|
63 |
}); |
|
64 |
}); |
|
65 |
|
|
66 |
function edit_section_header() { |
|
67 |
$.post("controller.pl?action=RequirementSpecItem/edit_section&id=" + encodeURIComponent($('#active_section_id').val()), function(data) { |
|
68 |
var header = $('#section-header'); |
|
69 |
header.data('old-elements', header.children().detach()); |
|
70 |
header.html(data); |
|
71 |
}); |
|
72 |
} |
|
73 |
|
|
74 |
function submit_section_form() { |
|
75 |
$.post("controller.pl?action=RequirementSpecItem/update_section&id=" + $('#section-form form').serialize(), function(data) { |
|
76 |
var header = $('#section-header'); |
|
77 |
header.removeData('old-elements'); |
|
78 |
header.html(data['header_html']); |
|
79 |
$('#tree').jstree('rename_node', '#fb-' + data['id'], data['node_name']); |
|
80 |
}); |
|
81 |
} |
|
82 |
|
|
83 |
function cancel_section_form() { |
|
84 |
var header = $('#section-header'); |
|
85 |
header.empty(); |
|
86 |
header.append(header.data('old-elements')); |
|
87 |
header.removeData('old-elements'); |
|
88 |
} |
|
89 |
--> |
|
90 |
</script> |
templates/webpages/requirement_spec_item/_single_subitem.html | ||
---|---|---|
1 |
[%- USE HTML -%][%- USE LxERP -%][%- USE P -%] |
|
2 |
<li id="subitem_[%- requirement_spec_item.id -%]" class="subitem"> |
|
3 |
|
|
4 |
<div id="subitem_content_[%- requirement_spec_item.id -%]" class="subitem-content[%- IF requirement_spec_item.flagged -%] flagged[%- END -%]"> |
|
5 |
|
|
6 |
[%#- IF !@requirement_spec.project.nil? -%] |
|
7 |
[%#- link_to image_tag("chronometer.png"), account_time_requirement_spec_requirement_spec_item_path(requirement_spec_item.requirement_spec, requirement_spec_item) -%] |
|
8 |
[%#- END -%] |
|
9 |
[%#- link_to_new_sub(requirement_spec_item.parent) -%] |
|
10 |
[%#- link_to_remote image_tag("new_subsub.png"), |
|
11 |
:url => new_requirement_spec_requirement_spec_item_url(requirement_spec_item.requirement_spec, :requirement_spec_item_id => requirement_spec_item.id), |
|
12 |
:method => :get, |
|
13 |
:condition => "check_for_editbox()", |
|
14 |
:update => "new_subsubitem_form_#{requirement_spec_item.id}" -%] |
|
15 |
|
|
16 |
<b>[%- HTML.escape(requirement_spec_item.fb_number) -%]</b> |
|
17 |
[%- HTML.escape(requirement_spec_item.description) -%] |
|
18 |
|
|
19 |
<div class="subsubitem-container" id="subsubitem_container_[%- requirement_spec_item.id -%]"> |
|
20 |
<div class="subsubitem-header" id="subsubitem_header_[%- requirement_spec_item.id -%]"[%- IF !requirement_spec_item.children.size -%] style="display: none"[%- END -%]> |
|
21 |
[%- LxERP.t8("Sub function blocks") -%] |
|
22 |
</div> |
|
23 |
[%- IF requirement_spec_item.children.size -%] |
|
24 |
[%- FOREACH subsubitem = requirement_spec_item.children -%] |
|
25 |
[%#- render :partial => "requirement_spec_items/single_subsubitem", :locals => {:requirement_spec_item => subsubitem} -%] |
|
26 |
[%- END -%] |
|
27 |
[%- END -%] |
|
28 |
</div> |
|
29 |
|
|
30 |
<div id="new_subsubitem_form_[%- requirement_spec_item.id -%]" class="subsubitem_form"></div> |
|
31 |
|
|
32 |
<div class="smaller" style="text-align:right"> |
|
33 |
[%- IF requirement_spec_item.dependencies.size -%] |
|
34 |
<span class="gray"> |
|
35 |
[%- LxERP.t8("Dependencies") -%]: [%- P.requirement_spec_item_dependency_list(requirement_spec_item.dependencies) -%] |
|
36 |
</span><br> |
|
37 |
[%- END -%] |
|
38 |
<span class="gray"> |
|
39 |
[%- LxERP.t8("Complexity") -%]: [%- requirement_spec_item.requirement_spec_complexity.description IF requirement_spec_item.requirement_spec_complexity -%] |
|
40 |
| |
|
41 |
[%- LxERP.t8("Risk") -%]: [%- requirement_spec_item.requirement_spec_risk.description IF requirement_spec_item.requirement_spec_risk -%] |
|
42 |
| |
|
43 |
[%- LxERP.t8("Effort") -%]: [%#- render :partial => 'requirement_spec_items/time_estimation_item', :locals => { :item => requirement_spec_item } -%] |
|
44 |
</span> |
|
45 |
|
|
46 |
</div> |
|
47 |
</div> |
|
48 |
</li> |
Auch abrufbar als: Unified diff
Pflichtenhefte bearbeiten