View | Details | Raw Unified | Return to bug 17297
Collapse All | Expand All

(-)a/catalogue/moredetail.pl (-2 / +7 lines)
Lines 30-43 use C4::Acquisition; Link Here
30
use C4::Output;
30
use C4::Output;
31
use C4::Auth;
31
use C4::Auth;
32
use C4::Serials;
32
use C4::Serials;
33
use C4::Members; # to use GetMember
33
use C4::Members;    # to use GetMember
34
use C4::Search;		# enabled_staff_search_views
34
use C4::Search;     # enabled_staff_search_views
35
use C4::Reserves qw(GetReservesFromBiblionumber);
35
use C4::Reserves qw(GetReservesFromBiblionumber);
36
36
37
use Koha::Acquisition::Booksellers;
37
use Koha::Acquisition::Booksellers;
38
use Koha::AuthorisedValues;
38
use Koha::AuthorisedValues;
39
use Koha::DateUtils;
39
use Koha::DateUtils;
40
use Koha::Items;
40
use Koha::Items;
41
use Koha::Item::Messages;
41
use Koha::Patrons;
42
use Koha::Patrons;
42
43
43
my $query=new CGI;
44
my $query=new CGI;
Lines 133-140 foreach ( keys %{$data} ) { Link Here
133
}
134
}
134
135
135
($itemnumber) and @items = (grep {$_->{'itemnumber'} == $itemnumber} @items);
136
($itemnumber) and @items = (grep {$_->{'itemnumber'} == $itemnumber} @items);
137
my $item_messages;
136
foreach my $item (@items){
138
foreach my $item (@items){
137
    $item->{object} = Koha::Items->find( $item->{itemnumber} );
139
    $item->{object} = Koha::Items->find( $item->{itemnumber} );
140
    $item_messages->{ $item->{itemnumber} } = ( Koha::Item::Messages->search( { itemnumber => $item->{itemnumber} } )->unblessed );
138
    $item->{'collection'}              = $ccodes->{ $item->{ccode} } if ($ccodes);
141
    $item->{'collection'}              = $ccodes->{ $item->{ccode} } if ($ccodes);
139
    $item->{'itype'}                   = $itemtypes->{ $item->{'itype'} }->{'translated_description'};
142
    $item->{'itype'}                   = $itemtypes->{ $item->{'itype'} }->{'translated_description'};
140
    $item->{'replacementprice'}        = sprintf( "%.2f", $item->{'replacementprice'} );
143
    $item->{'replacementprice'}        = sprintf( "%.2f", $item->{'replacementprice'} );
Lines 226-231 $template->param( Link Here
226
    z3950_search_params => C4::Search::z3950_search_args(GetBiblioData($biblionumber)),
229
    z3950_search_params => C4::Search::z3950_search_args(GetBiblioData($biblionumber)),
227
    subtitle            => $subtitle,
230
    subtitle            => $subtitle,
228
    hidepatronname      => $hidepatronname,
231
    hidepatronname      => $hidepatronname,
232
    item_messages       => $item_messages,
229
);
233
);
230
$template->param(ONLY_ONE => 1) if ( $itemnumber && $showncount != @items );
234
$template->param(ONLY_ONE => 1) if ( $itemnumber && $showncount != @items );
231
$template->{'VARS'}->{'searchid'} = $query->param('searchid');
235
$template->{'VARS'}->{'searchid'} = $query->param('searchid');
Lines 261-266 $template->param (countdeletedorders => $count_deletedorders_using_biblio); Link Here
261
my $holds = GetReservesFromBiblionumber({ biblionumber => $biblionumber, all_dates => 1 });
265
my $holds = GetReservesFromBiblionumber({ biblionumber => $biblionumber, all_dates => 1 });
262
my $holdcount = scalar( @$holds );
266
my $holdcount = scalar( @$holds );
263
$template->param( holdcount => scalar ( @$holds ) );
267
$template->param( holdcount => scalar ( @$holds ) );
268
warn Data::Dumper::Dumper( $item_messages );
264
269
265
output_html_with_http_headers $query, $cookie, $template->output;
270
output_html_with_http_headers $query, $cookie, $template->output;
266
271
(-)a/koha-tmpl/intranet-tmpl/prog/css/staff-global.css (-44 / +52 lines)
Lines 75-86 h3 { Link Here
75
}
75
}
76
76
77
h4 {
77
h4 {
78
	font-size : 116%;	
78
	font-size : 116%;
79
	font-weight : bold;
79
	font-weight : bold;
80
}
80
}
81
81
82
h5 {
82
h5 {
83
	font-size : 100%;	
83
	font-size : 100%;
84
	font-weight : bold;
84
	font-weight : bold;
85
}
85
}
86
86
Lines 614-620 div.yui-b fieldset.brief fieldset legend { Link Here
614
    margin-left: 20px;
614
    margin-left: 20px;
615
}
615
}
616
616
617
fieldset.rows {  
617
fieldset.rows {
618
border-width : 1px;
618
border-width : 1px;
619
border:2px solid #b9d8d9;
619
border:2px solid #b9d8d9;
620
float : left;
620
float : left;
Lines 622-628 font-size : 90%; Link Here
622
clear : left;
622
clear : left;
623
margin: .9em 0 0 0;
623
margin: .9em 0 0 0;
624
padding: 0;
624
padding: 0;
625
width: 100%; 
625
width: 100%;
626
}
626
}
627
627
628
fieldset.rows.unselected {
628
fieldset.rows.unselected {
Lines 631-647 fieldset.rows.unselected { Link Here
631
    border: 0;
631
    border: 0;
632
}
632
}
633
633
634
fieldset.rows legend {  
634
fieldset.rows legend {
635
	margin-left: 1em;
635
	margin-left: 1em;
636
	font-weight: bold;
636
	font-weight: bold;
637
	font-size : 110%;
637
	font-size : 110%;
638
}
638
}
639
639
640
fieldset.rows label, fieldset.rows span.label {  
640
fieldset.rows label, fieldset.rows span.label {
641
	float: left;  
641
	float: left;
642
	font-weight : bold;
642
	font-weight : bold;
643
	width: 6em;  
643
	width: 6em;
644
	margin-right: 1em;  
644
	margin-right: 1em;
645
	text-align: right;
645
	text-align: right;
646
}
646
}
647
647
Lines 652-659 fieldset.rows fieldset { Link Here
652
	padding : .3em;
652
	padding : .3em;
653
}
653
}
654
654
655
.yui-b fieldset.rows label, .yui-b fieldset.rows span.label {  
655
.yui-b fieldset.rows label, .yui-b fieldset.rows span.label {
656
	width: 9em;  
656
	width: 9em;
657
}
657
}
658
658
659
.yui-b fieldset.rows td label, .yui-b fieldset.rows td span.label {
659
.yui-b fieldset.rows td label, .yui-b fieldset.rows td span.label {
Lines 664-671 fieldset.rows fieldset { Link Here
664
	margin-left : 10.5em;
664
	margin-left : 10.5em;
665
}
665
}
666
666
667
.yui-u fieldset.rows label, .yui-u fieldset.rows span.label {  
667
.yui-u fieldset.rows label, .yui-u fieldset.rows span.label {
668
	width: 10em;  
668
	width: 10em;
669
}
669
}
670
670
671
.yui-u fieldset.rows div.hint {
671
.yui-u fieldset.rows div.hint {
Lines 674-693 fieldset.rows fieldset { Link Here
674
674
675
fieldset.rows.left label, fieldset.rows.left span.label {
675
fieldset.rows.left label, fieldset.rows.left span.label {
676
	width : 8em;
676
	width : 8em;
677
	text-align : left;	
677
	text-align : left;
678
}
678
}
679
679
680
fieldset.rows ol {  
680
fieldset.rows ol {
681
padding: 1em 1em 0 1em;  
681
padding: 1em 1em 0 1em;
682
list-style-type: none;
682
list-style-type: none;
683
}
683
}
684
684
685
fieldset.rows li {  
685
fieldset.rows li {
686
float : left;
686
float : left;
687
clear : left;
687
clear : left;
688
padding-bottom: 1em;
688
padding-bottom: 1em;
689
list-style-type: none;
689
list-style-type: none;
690
width: 100%; 
690
width: 100%;
691
}
691
}
692
692
693
fieldset.rows.left li {
693
fieldset.rows.left li {
Lines 783-799 div.rows+div.rows { Link Here
783
div.rows {
783
div.rows {
784
float : left;
784
float : left;
785
clear : left;
785
clear : left;
786
margin: 0 0 0 0;  
786
margin: 0 0 0 0;
787
padding: 0;
787
padding: 0;
788
width: 100%; 
788
width: 100%;
789
}
789
}
790
790
791
791
792
div.rows span.label {  
792
div.rows span.label {
793
	float: left;  
793
	float: left;
794
	font-weight : bold;
794
	font-weight : bold;
795
	width: 9em;
795
	width: 9em;
796
	margin-right: 1em;  
796
	margin-right: 1em;
797
	text-align: left;
797
	text-align: left;
798
        padding-top: 0;
798
        padding-top: 0;
799
}
799
}
Lines 802-809 div.rows span.label { Link Here
802
    white-space: normal;
802
    white-space: normal;
803
}
803
}
804
804
805
div.rows ol {  
805
div.rows ol {
806
padding: .5em 1em 0 0;  
806
padding: .5em 1em 0 0;
807
list-style-type: none;
807
list-style-type: none;
808
}
808
}
809
809
Lines 818-824 clear : left; Link Here
818
padding-bottom: .2em;
818
padding-bottom: .2em;
819
padding-top: .1em;
819
padding-top: .1em;
820
list-style-type: none;
820
list-style-type: none;
821
width: 100%; 
821
width: 100%;
822
}
822
}
823
823
824
a.cancel {
824
a.cancel {
Lines 946-953 ol.bibliodetails span.label { Link Here
946
	border-right : 1px solid #E8E8E8;
946
	border-right : 1px solid #E8E8E8;
947
	float : left;
947
	float : left;
948
	font-weight: bold;
948
	font-weight: bold;
949
	width: 12em;  
949
	width: 12em;
950
	margin-right: 1em;  
950
	margin-right: 1em;
951
}
951
}
952
952
953
div.listgroup {
953
div.listgroup {
Lines 966-971 div.listgroup input { Link Here
966
	font-size: 80%;
966
	font-size: 80%;
967
}
967
}
968
968
969
div.listgroup ol li span.label i {
970
    margin-right : .5em;
971
}
972
973
div.listgroup ol li button,a {
974
    margin-left : .5em;
975
}
976
969
div.sysprefs h3 {
977
div.sysprefs h3 {
970
	margin : .2em 0 .2em .4em;
978
	margin : .2em 0 .2em .4em;
971
}
979
}
Lines 1035-1041 span.expired { Link Here
1035
}
1043
}
1036
1044
1037
div.help {
1045
div.help {
1038
	margin: .9em 0 0 0;  
1046
	margin: .9em 0 0 0;
1039
}
1047
}
1040
1048
1041
.blocker {
1049
.blocker {
Lines 1092-1103 div.first fieldset { Link Here
1092
.dialog table td {
1100
.dialog table td {
1093
	text-align : left;
1101
	text-align : left;
1094
}
1102
}
1095
  
1103
1096
.dialog  h2, .dialog h3, .dialog h4 {
1104
.dialog  h2, .dialog h3, .dialog h4 {
1097
  	margin : auto;
1105
  	margin : auto;
1098
	text-align : center;
1106
	text-align : center;
1099
  }
1107
  }
1100
  
1108
1101
.dialog input {
1109
.dialog input {
1102
 	background-color : #FFF;
1110
 	background-color : #FFF;
1103
 	border : 1px solid #bcbcbc;
1111
 	border : 1px solid #bcbcbc;
Lines 1252-1262 div.note i.fa-exclamation { Link Here
1252
 div.results {
1260
 div.results {
1253
 	padding : .7em 0;
1261
 	padding : .7em 0;
1254
 }
1262
 }
1255
 
1263
1256
 .accesskey {
1264
 .accesskey {
1257
 	text-decoration : underline;
1265
 	text-decoration : underline;
1258
 }
1266
 }
1259
 
1267
1260
label.required,
1268
label.required,
1261
span.required {
1269
span.required {
1262
    color : #C00;
1270
    color : #C00;
Lines 1388-1394 h1#logo a { Link Here
1388
}
1396
}
1389
1397
1390
#closewindow a {
1398
#closewindow a {
1391
	font-weight : bold;	
1399
	font-weight : bold;
1392
}
1400
}
1393
1401
1394
.patroninfo+#menu {
1402
.patroninfo+#menu {
Lines 1421-1430 li.email { Link Here
1421
}
1429
}
1422
1430
1423
.clearfix:after {
1431
.clearfix:after {
1424
    content: "."; 
1432
    content: ".";
1425
    display: block; 
1433
    display: block;
1426
    height: 0; 
1434
    height: 0;
1427
    clear: both; 
1435
    clear: both;
1428
    visibility: hidden;
1436
    visibility: hidden;
1429
}
1437
}
1430
1438
Lines 1664-1670 input.warning { Link Here
1664
}
1672
}
1665
1673
1666
#displayexample {
1674
#displayexample {
1667
	padding: 5px; 
1675
	padding: 5px;
1668
	margin-bottom: 10px;
1676
	margin-bottom: 10px;
1669
	background-color: #CCCCCC;
1677
	background-color: #CCCCCC;
1670
}
1678
}
Lines 1781-1787 span.permissiondesc { Link Here
1781
1789
1782
.results_summary {
1790
.results_summary {
1783
  display: block;
1791
  display: block;
1784
  font-size : 85%; 
1792
  font-size : 85%;
1785
  color: #707070;
1793
  color: #707070;
1786
  padding : 0 0 .5em 0;
1794
  padding : 0 0 .5em 0;
1787
}
1795
}
Lines 1886-1895 fieldset.rows+h3 {clear:both;padding-top:.5em;} Link Here
1886
}
1894
}
1887
1895
1888
.m880 {
1896
.m880 {
1889
    display:block; 
1897
    display:block;
1890
    text-align:right; 
1898
    text-align:right;
1891
    float:right; 
1899
    float:right;
1892
    width:50%; 
1900
    width:50%;
1893
    padding-left:20px
1901
    padding-left:20px
1894
}
1902
}
1895
1903
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt (+11 lines)
Lines 1-5 Link Here
1
[% USE To %]
1
[% USE Koha %]
2
[% USE Koha %]
2
[% USE Branches %]
3
[% USE Branches %]
4
[% USE AuthorisedValues %]
3
[% INCLUDE 'doc-head-open.inc' %]
5
[% INCLUDE 'doc-head-open.inc' %]
4
<title>Koha &rsaquo; Catalog &rsaquo; Item details for [% title | html %] [% FOREACH subtitl IN subtitle %] [% subtitl.subfield | html %][% END %]</title>
6
<title>Koha &rsaquo; Catalog &rsaquo; Item details for [% title | html %] [% FOREACH subtitl IN subtitle %] [% subtitl.subfield | html %][% END %]</title>
5
[% INCLUDE 'doc-head-close.inc' %]
7
[% INCLUDE 'doc-head-close.inc' %]
Lines 13-20 Link Here
13
//<![CDATA[
15
//<![CDATA[
14
    var browser = KOHA.browser('[% searchid %]', parseInt('[% biblionumber %]', 10));
16
    var browser = KOHA.browser('[% searchid %]', parseInt('[% biblionumber %]', 10));
15
    browser.show();
17
    browser.show();
18
19
    var authorised_values = [% To.json( AuthorisedValues.Get('ITEM_MESSAGE_TYPE') ) %]
20
    var item_messages = [% To.json( item_messages ) %];
21
22
    var CANCEL = _("Cancel");
23
    var ADD_MESSAGE = _("Add message");
24
    var ARE_YOU_SURE = _("Are you sure you want to delete the following message: ");
16
//]]>
25
//]]>
17
</script>
26
</script>
27
<script type="text/javascript" src="[% interface %]/[% theme %]/js/app/moredetail.js"></script>
18
</head>
28
</head>
19
<body id="catalog_moredetail" class="catalog">
29
<body id="catalog_moredetail" class="catalog">
20
[% USE KohaDates %]
30
[% USE KohaDates %]
Lines 199-204 Link Here
199
            [% END %]
209
            [% END %]
200
210
201
            </ol></div>
211
            </ol></div>
212
            <div id="item-messages-[% ITEM_DAT.itemnumber %]" class="item-messages"></div>
202
            <div class="listgroup"><h4>History</h4>
213
            <div class="listgroup"><h4>History</h4>
203
            <ol class="bibliodetails">
214
            <ol class="bibliodetails">
204
215
(-)a/koha-tmpl/intranet-tmpl/prog/js/public/moredetail.js (-1 / +150 lines)
Line 0 Link Here
0
- 
1
var React = require('react');
2
var ReactDOM = require('react-dom');
3
4
var av_descriptions = [];
5
$( document ).ready(function() {
6
    for (var i = 0; i < authorised_values.length; i++) {
7
        var av = authorised_values[i];
8
        av_descriptions[av.authorised_value] = av.lib;
9
    }
10
11
    $('.item-messages').each(function() {
12
        var itemnumber = parseInt( $(this).attr('id').split('item-messages-')[1] );
13
        ReactDOM.render(
14
            <ItemMessages itemnumber={itemnumber} messages={item_messages[itemnumber]}/>,
15
            this
16
        );
17
    });
18
});
19
20
var ItemMessages = React.createClass({
21
    propTypes: {
22
        messages: React.PropTypes.array.isRequired,
23
        itemnumber: React.PropTypes.number.isRequired,
24
    },
25
    getInitialState: function() {
26
        return { messages: this.props.messages };
27
    },
28
    addMessage: function(message) {
29
        this.setState(function(state) {
30
            var newData = state.messages.slice();
31
            newData.push( message );
32
            return {messages: newData};
33
        });
34
    },
35
    removeMessage: function(index) {
36
        var message = this.state.messages[index];
37
        var itemMessage = this;
38
        $.ajax({
39
            url: '/api/v1/items/' + message.itemnumber + '/messages/' + message.item_message_id,
40
            type: 'DELETE',
41
            success: function( result ) {
42
                itemMessage.setState(function(state) {
43
                    var newData = state.messages.slice();
44
                    newData.splice(index, 1);
45
                    return {messages: newData};
46
                });
47
            }
48
        });
49
    },
50
    render: function () {
51
        var item_messages = this;
52
        return  <div className="listgroup">
53
                    <h4>Messages</h4>
54
                    <ol className="bibliodetails">
55
                        {this.state.messages.map(function(message, index) {
56
                            return <ItemMessage key={message.item_message_id} message={message} index={index} onRemove={item_messages.removeMessage} />
57
                        })}
58
                        <ItemMessageCreator itemnumber={this.props.itemnumber}  onAdd={item_messages.addMessage}/>
59
                    </ol>
60
                </div>;
61
    }
62
});
63
64
var ItemMessage = React.createClass({
65
    propTypes: {
66
        message: React.PropTypes.object.isRequired,
67
        index: React.PropTypes.number.isRequired,
68
        onRemove: React.PropTypes.func.isRequired,
69
    },
70
    removeMessage: function() {
71
        if ( confirm( ARE_YOU_SURE + this.props.message.message ) ) {
72
            this.props.onRemove(this.props.index);
73
        }
74
    },
75
    render: function () {
76
        return  <li>
77
                    <span className="label">
78
                        <i className="fa fa-minus-circle" onClick={this.removeMessage}></i>
79
                        {av_descriptions[this.props.message.type]}
80
                    </span>
81
                    {this.props.message.message}
82
                </li>
83
      }
84
});
85
86
var ItemMessageCreator = React.createClass({
87
    propTypes: {
88
        itemnumber: React.PropTypes.number.isRequired,
89
        onAdd: React.PropTypes.func.isRequired,
90
    },
91
    getInitialState: function () {
92
        return {
93
            message: "",
94
            type: authorised_values[0].authorised_value,
95
        };
96
    },
97
    addMessage: function() {
98
        var self = this;
99
        var item_message = {
100
            type: this.state.type,
101
            message: this.state.message,
102
        };
103
        $.ajax({
104
            type: 'POST',
105
            url: '/api/v1/items/' + this.props.itemnumber + '/messages',
106
            data: JSON.stringify(item_message),
107
            success: function(data) {
108
                self.cancelMessage();
109
                self.props.onAdd(data);
110
            },
111
            error: function (xhr, ajaxOptions, thrownError) {
112
                console.log(xhr.responseText);
113
                console.log(thrownError);
114
            },
115
        });
116
    },
117
    cancelMessage: function() {
118
        this.setState( this.getInitialState );
119
        return false;
120
    },
121
    handleTypeChange: function(e) {
122
        this.setState({ type: e.target.value });
123
    },
124
    handleContentChange: function(e) {
125
        this.setState({ message: e.target.value });
126
    },
127
    render: function () {
128
        var options = [];
129
        for (var i = 0; i < authorised_values.length; i++) {
130
            var av = authorised_values[i];
131
            options.push(
132
                <option key={i} value={av.authorised_value}>{av.lib}</option>
133
            );
134
        }
135
136
        return  <li>
137
                    <span className="label">
138
                        <select value={this.state.type} onChange={this.handleTypeChange}>
139
                            {options}
140
                        </select>
141
                    </span>
142
                    <input className="input-xlarge" type="text" value={this.state.message} onChange={this.handleContentChange} />
143
                    <button className="submit" onClick={this.addMessage}>
144
                        <i className="fa fa-plus-circle"></i>&nbsp;
145
                        {ADD_MESSAGE}
146
                    </button>
147
                    <a href="javascript:void(0);" onClick={this.cancelMessage}>{CANCEL}</a>
148
                </li>
149
      }
150
});

Return to bug 17297