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

(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (+7 lines)
Lines 80-85 Link Here
80
                        </div> <!-- / .dropdown-menu -->
80
                        </div> <!-- / .dropdown-menu -->
81
                    </li> <!-- / .nav-item.dropdown -->
81
                    </li> <!-- / .nav-item.dropdown -->
82
                [% END # / IF virtualshelves %]
82
                [% END # / IF virtualshelves %]
83
                [% IF ( Koha.Preference( 'OpacTrustedCheckout' ) && loggedinusername ) %]
84
                    <li class="nav-item">
85
                        <a href="#" class="nav-link" title="Self check out" id="comenulink" role="button" data-toggle="modal" data-target="#checkoutModal">
86
                            <i id="checkout-icon" class="fa fa-barcode fa-icon-black" aria-hidden="true"></i> <span class="checkout-label">Self checkout</span>
87
                        </a>
88
                    </li>
89
                [% END %]
83
            </ul> <!-- / .navbar-nav -->
90
            </ul> <!-- / .navbar-nav -->
84
91
85
            [% IF Koha.Preference( 'opacuserlogin' ) == 1 ||  Koha.Preference( 'EnableOpacSearchHistory') || Koha.Preference( 'opaclanguagesdisplay' ) %]
92
            [% IF Koha.Preference( 'opacuserlogin' ) == 1 ||  Koha.Preference( 'EnableOpacSearchHistory') || Koha.Preference( 'opaclanguagesdisplay' ) %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/modals/checkout.inc (+25 lines)
Line 0 Link Here
1
<!-- Checkout form hidden by default, used for modal window -->
2
<div class="modal" id="checkoutModal" tabindex="-1" role="dialog" aria-labelledby="checkoutModalLabel" aria-hidden="true">
3
    <div class="modal-dialog">
4
        <div class="modal-content">
5
            <div class="modal-header">
6
                <h3 class="modal-title" id="checkoutModalLabel">Self checkout</h3>
7
                <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close">
8
                    <span aria-hidden="true">&times;</span>
9
                </button>
10
            </div>
11
            <div class="modal-body">
12
                <div id="checkoutResults"></div>
13
                <div id="availabilityResult"></div>
14
                <div class="form-group">
15
                    <label for="checkout_barcode">Enter item barcode: </label>
16
                    <input type="text" name="checkout_barcode" id="checkout_barcode" required="required"></input>
17
                </div>
18
            </div>
19
            <div class="modal-footer">
20
                <button type="submit" id="checkoutSubmit" class="btn btn-primary">Submit</button>
21
                <button type="button" id="checkoutClose" class="btn btn-default" data-dismiss="modal">Close</button>
22
            </div>
23
        </div>
24
    </div>
25
</div>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc (+10 lines)
Lines 117-122 Link Here
117
    [% END # /IF OpacLangSelectorMode == 'both' || OpacLangSelectorMode == 'footer' %]
117
    [% END # /IF OpacLangSelectorMode == 'both' || OpacLangSelectorMode == 'footer' %]
118
[% END # / UNLESS is_popup %]
118
[% END # / UNLESS is_popup %]
119
119
120
[% IF ( Koha.Preference( 'OpacTrustedCheckout' ) && loggedinusername ) %]
121
    [% INCLUDE 'modals/checkout.inc' %]
122
[% END %]
123
120
<!-- JavaScript includes -->
124
<!-- JavaScript includes -->
121
[% Asset.js("lib/jquery/jquery-3.6.0.min.js") | $raw %]
125
[% Asset.js("lib/jquery/jquery-3.6.0.min.js") | $raw %]
122
[% Asset.js("lib/jquery/jquery-migrate-3.3.2.min.js") | $raw %]
126
[% Asset.js("lib/jquery/jquery-migrate-3.3.2.min.js") | $raw %]
Lines 124-129 Link Here
124
[% Asset.js("lib/bootstrap/js/bootstrap.bundle.min.js") | $raw %]
128
[% Asset.js("lib/bootstrap/js/bootstrap.bundle.min.js") | $raw %]
125
[% Asset.js("lib/fontfaceobserver.min.js") | $raw %]
129
[% Asset.js("lib/fontfaceobserver.min.js") | $raw %]
126
[% Asset.js("lib/enquire.min.js") | $raw %]
130
[% Asset.js("lib/enquire.min.js") | $raw %]
131
<script>
132
    let logged_in_user_id = "[% logged_in_user.borrowernumber | html %]";
133
</script>
127
[% Asset.js("js/global.js") | $raw %]
134
[% Asset.js("js/global.js") | $raw %]
128
[% IF ( OPACAmazonCoverImages || SyndeticsCoverImages ) %]
135
[% IF ( OPACAmazonCoverImages || SyndeticsCoverImages ) %]
129
    <script>
136
    <script>
Lines 304-309 $(document).ready(function() { Link Here
304
        </script>
311
        </script>
305
    [% END %]
312
    [% END %]
306
[% END %]
313
[% END %]
314
[% IF ( Koha.Preference( 'OpacTrustedCheckout' ) && loggedinusername ) %]
315
    [% Asset.js("js/modals/checkout.js") | $raw %]
316
[% END %]
307
[% KohaPlugins.get_plugins_opac_js | $raw %]
317
[% KohaPlugins.get_plugins_opac_js | $raw %]
308
</body>
318
</body>
309
</html>
319
</html>
(-)a/koha-tmpl/opac-tmpl/bootstrap/js/modals/checkout.js (-1 / +214 lines)
Line 0 Link Here
0
- 
1
$(document).ready(function() {
2
3
    function resetResults(){
4
        $('#checkoutResults').replaceWith('<div id="checkoutResults"></div>');
5
        $('#availabilityResult').replaceWith('<div id="availabilityResult"></div>');
6
    };
7
8
    function addResult(type, code, data){
9
        let result = '';
10
        if ( type == 'danger' ) {
11
            result += '<div class="alert alert-danger">';
12
        } else if ( type == 'warning' ) {
13
            result += '<div class="alert alert-warning">';
14
        } else if ( type == 'info' ) {
15
            result += '<div class="alert alert-info">';
16
        } else {
17
            result += '<div class="alert alert-success">';
18
        }
19
20
        if ( code == 'NOT_FOUND' ) {
21
            result += _("Item '%s' not found").format(data);
22
        }
23
        else if ( code == 'RENEW_ISSUE' ) {
24
            result += _("Item will be renewed").format(data);
25
        }
26
        else if ( code == 'OTHER_CHARGES' ) {
27
            result += _("Your account current has outstanding charges of '%s'").format(data);
28
        }
29
        else {
30
            result += _("Message code '%s' with data '%s'").format(code,data);
31
        }
32
33
        result += '</div>';
34
        $('#availabilityResult').append(result);
35
    };
36
37
    // On modal show, clear any prior results and set focus
38
    $('#checkoutModal').on('shown.bs.modal', function(e) {
39
        $('#checkoutResults').replaceWith('<div id="checkoutResults"></div>');
40
        $('#availabilityResult').replaceWith('<div id="availabilityResult"></div>');
41
        $('#external_id').focus();
42
    });
43
44
    // On modal submit
45
    $('#checkoutModal').on('click', '#checkoutSubmit', function(e) {
46
47
        // Get item from barcode
48
        let external_id = $('#checkout_barcode').val();
49
        let item_id;
50
        let items = $.ajax({
51
            url: '/api/v1/public/items?external_id=' + external_id,
52
            dataType: 'json',
53
            type: 'GET'
54
        });
55
56
        $('#availabilityResult').replaceWith('<div id="availabilityResult"></div>');
57
58
        // Get availability of the item
59
        let availability = items.then(
60
            function(data, textStatus, jqXHR) {
61
                if (data.length == 1) {
62
                    item_id = data[0].item_id;
63
                    console.log('Found one item with id: ' + item_id);
64
                    return $.ajax({
65
                        url: '/api/v1/public/checkouts/availability?item_id=' + item_id + '&patron_id=' + logged_in_user_id,
66
                        type: 'GET',
67
                        contentType: "json"
68
                    });
69
                } else {
70
                    addResult('danger', 'NOT_FOUND', external_id);
71
                }
72
            },
73
            function(data, textStatus, jqXHR) {
74
                console.log('Items request failed with: ' + textStatus);
75
                console.log(data);
76
            }
77
        );
78
79
        let checkout = availability.then(
80
            function(data, textStatus, jqXHR) {
81
                let result;
82
                console.log(data);
83
                // blocked
84
                if (Object.keys(data.blockers).length >= 1) {
85
                    for (const key in data.blockers) {
86
                        if (data.blockers.hasOwnProperty(key)) {
87
                            addResult('danger', `${key}`, `${data.blockers[key]}`);
88
                            console.log(`${key}: ${data.blockers[key]}`);
89
                        }
90
                    }
91
                    console.log("Request succeeded but blockers were reported");
92
                }
93
                // requires confirmation
94
                else if (Object.keys(data.confirms).length >= 1) {
95
                    for (const key in data.confirms) {
96
                        if (data.confirms.hasOwnProperty(key)) {
97
                            addResult('warning', `${key}`, `${data.confirms[key]}`);
98
                            console.log(`${key}: ${data.confirms[key]}`);
99
                        }
100
                    }
101
                    $('#checkoutSubmit').replaceWith('<input type="hidden" id="item_id" value="' + item_id + '"><input type="hidden" id="confirm_token" value="' + data.confirmation_token + '"><button type="submit" id="checkoutConfirm" class="btn btn-warning">Confirm</button>');
102
                    console.log("Request succeeded confirmation is required");
103
                }
104
                // straight checkout
105
                else {
106
                    let params = {
107
                        "checkout_id": undefined,
108
                        "patron_id": logged_in_user_id,
109
                        "item_id": item_id,
110
                        "due_date": undefined,
111
                        "library_id": undefined,
112
                        "issuer_id": undefined,
113
                        "checkin_date": undefined,
114
                        "last_renewed_date": undefined,
115
                        "renewals_count": undefined,
116
                        "unseen_renewals": undefined,
117
                        "auto_renew": undefined,
118
                        "auto_renew_error": undefined,
119
                        "timestamp": undefined,
120
                        "checkout_date": undefined,
121
                        "onsite_checkout": false,
122
                        "note": undefined,
123
                        "note_date": undefined,
124
                        "note_seen": undefined,
125
                    };
126
                    result = $.ajax({
127
                        url: '/api/v1/public/checkouts',
128
                        type: 'POST',
129
                        data: JSON.stringify(params),
130
                        contentType: "json"
131
                    });
132
                }
133
134
                // warnings to display
135
                if (Object.keys(data.warnings).length >= 1) {
136
                    for (const key in data.warnings) {
137
                        if (data.warnings.hasOwnProperty(key)) {
138
                            addResult('info', `${key}`, `${data.warnings[key]}`);
139
                            console.log(`${key}: ${data.warnings[key]}`);
140
                        }
141
                    }
142
                    console.log("Request succeeded but there were warnings");
143
                }
144
145
                // return a rejected promise if we've reached here
146
                return result ? result : $.Deferred().reject('Checkout halted');
147
            },
148
            function(data, textStatus, jqXHR) {
149
                console.log('Items request failed with: ' + textStatus);
150
                console.log(data);
151
            }
152
        );
153
154
        checkout.then(
155
            function(data, textStatus, jqXHR) {
156
                console.log("checkout.then succeeded");
157
                $('#checkoutResults').replaceWith('<div id="checkoutResults" class="alert alert-success">' + _("Item '%s' was checked out").format(external_id) + '</div>');
158
                $('#checkout_barcode').val("").focus();
159
                console.log(data);
160
                // data retrieved from url2 as provided by the first request
161
            },
162
            function(data, textStatus, jqXHR) {
163
                console.log("checkout.then failed");
164
            }
165
        );
166
167
    });
168
169
    $('#checkoutModal').on('click', '#checkoutConfirm', function(e) {
170
        let item_id = $('#item_id').val();
171
        let token = $('#confirm_token').val();
172
        let params = {
173
            "checkout_id": undefined,
174
            "patron_id": logged_in_user_id,
175
            "item_id": item_id,
176
            "due_date": undefined,
177
            "library_id": undefined,
178
            "issuer_id": undefined,
179
            "checkin_date": undefined,
180
            "last_renewed_date": undefined,
181
            "renewals_count": undefined,
182
            "unseen_renewals": undefined,
183
            "auto_renew": undefined,
184
            "auto_renew_error": undefined,
185
            "timestamp": undefined,
186
            "checkout_date": undefined,
187
            "onsite_checkout": false,
188
            "note": undefined,
189
            "note_date": undefined,
190
            "note_seen": undefined,
191
        };
192
        let checkout = $.ajax({
193
            url: '/api/v1/public/checkouts?confirmation=' + token,
194
            type: 'POST',
195
            data: JSON.stringify(params),
196
            contentType: "json"
197
        });
198
199
        checkout.then(
200
            function(data, textStatus, jqXHR) {
201
                console.log("checkout.then succeeded");
202
                $('#item_id').remove;
203
                $('#confirm_token').remove;
204
                $('#checkoutResults').replaceWith('<div id="checkoutResults" class="alert alert-success">' + _("Item '%s' was checked out").format(external_id) + '</div>');
205
                $('#checkoutConfirm').replaceWith('<button type="submit" id="checkoutSubmit" class="btn btn-primary">Submit</button>');
206
                $('#checkout_barcode').val("").focus();
207
                // data retrieved from url2 as provided by the first request
208
            },
209
            function(data, textStatus, jqXHR) {
210
                console.log("checkout.then failed");
211
            }
212
        );
213
    });
214
});

Return to bug 30979