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 / +182 lines)
Line 0 Link Here
0
- 
1
$(document).ready(function() {
2
3
    $("#checkoutModal").on("shown.bs.modal", function(e) {
4
        $("#checkoutResults").replaceWith('<div id="checkoutResults"></div>');
5
        $("#availabilityResult").replaceWith('<div id="availabilityResult"></div>');
6
        $("#external_id").focus();
7
    });
8
9
    $('#checkoutModal').on('click', '#checkoutSubmit', function(e) {
10
        let external_id = $('#checkout_barcode').val();
11
        let item_id;
12
        let items = $.ajax({
13
            url: '/api/v1/public/items?external_id=' + external_id,
14
            dataType: 'json',
15
            type: 'GET',
16
            success: function(data) {
17
                console.log(data);
18
            }
19
        });
20
21
        $('#availabilityResult').replaceWith('<div id="availabilityResult"></div>');
22
23
        let availability = items.then(
24
            function(data, textStatus, jqXHR) {
25
                if (data.length == 1) {
26
                    item_id = data[0].item_id;
27
                    console.log("Found one item with id: "+item_id);
28
                    return $.ajax({
29
                        url: '/api/v1/public/checkouts/availability?item_id='+item_id+'&patron_id='+logged_in_user_id,
30
                        type: 'GET',
31
                        contentType: "json"
32
                    });
33
                } else {
34
                    $('#availabilityResult').append('<div class="alert alert-danger">'+_("Failure: Item '%s' not found").format(external_id)+'</div>');
35
                }
36
            },
37
            function(data, textStatus, jqXHR) {
38
                console.log('Items request failed with: ' + textStatus);
39
                console.log(data);
40
            }
41
        );
42
43
        let checkout = availability.then(
44
            function(data, textStatus, jqXHR) {
45
                let result;
46
                console.log(data);
47
                // blocked
48
                if (Object.keys(data.blockers).length >= 1) {
49
                    let report = $('<div class="alert alert-danger">'+_("Item '%s' cannot be checked out for the following reasons: ").format(external_id)+'</div>');
50
                    for (const blocker in data.blockers) {
51
                        if (data.blockers.hasOwnProperty(blocker)) {
52
                            report.append(`${blocker}`);
53
                            console.log(`${blocker}: ${data.blockers[blocker]}`);
54
                        }
55
                    }
56
                    $('#availabilityResult').append(report);
57
                    console.log("Request succeeded but blockers were reported");
58
                }
59
                // requires confirmation
60
                else if (Object.keys(data.confirms).length >= 1) {
61
                        let report = $('<div class="alert alert-warning">'+_("Item '%s' needs confirmation for the following: ").format(external_id)+'</div>');
62
                        for (const key in data.confirms) {
63
                            if (data.confirms.hasOwnProperty(key)) {
64
                                report.append(`${key}`);
65
                                console.log(`${key}: ${data.confirms[key]}`);
66
                            }
67
                        }
68
                        $('#availabilityResult').append(report);
69
                        $('#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>');
70
                        console.log("Request succeeded confirmation is required");
71
                }
72
                // straight checkout
73
                else {
74
                    let params = {
75
                        "checkout_id": undefined,
76
                        "patron_id": logged_in_user_id,
77
                        "item_id": item_id,
78
                        "due_date": undefined,
79
                        "library_id": undefined,
80
                        "issuer_id": undefined,
81
                        "checkin_date": undefined,
82
                        "last_renewed_date": undefined,
83
                        "renewals_count": undefined,
84
                        "unseen_renewals": undefined,
85
                        "auto_renew": undefined,
86
                        "auto_renew_error": undefined,
87
                        "timestamp": undefined,
88
                        "checkout_date": undefined,
89
                        "onsite_checkout": false,
90
                        "note": undefined,
91
                        "note_date": undefined,
92
                        "note_seen": undefined,
93
                    };
94
                    result = $.ajax({
95
                        url: '/api/v1/public/checkouts',
96
                        type: 'POST',
97
                        data: JSON.stringify(params),
98
                        contentType: "json"
99
                    });
100
                }
101
                // warnings to display
102
                if (Object.keys(data.warnings).length >= 1) {
103
                    let report = $('<div class="alert alert-warning">'+_("The following warnings were reported:</br>")+'</div>');
104
                    for (const key in data.warnings) {
105
                        if (data.warnings.hasOwnProperty(key)) {
106
                            report.append(`${key}`+"</hr>");
107
                            console.log(`${key}: ${data.confirms[key]}`);
108
                        }
109
                    }
110
                    $('#availabilityResult').append(report);
111
                    console.log("Request succeeded but there were warnings");
112
                }
113
114
                // return a rejected promise if we've reached here
115
                return result ? result : $.Deferred().reject('Checkout halted');
116
            },
117
            function(data, textStatus, jqXHR) {
118
                console.log('Items request failed with: ' + textStatus);
119
                console.log(data);
120
            }
121
        );
122
123
        checkout.then(
124
            function(data, textStatus, jqXHR) {
125
                console.log("checkout.then succeeded");
126
                $("#checkoutResults").replaceWith('<div id="checkoutResults" class="alert alert-success">'+_("Item '%s' was checked out").format(external_id)+'</div>');
127
                $('#checkout_barcode').val("").focus();
128
                console.log(data);
129
                // data retrieved from url2 as provided by the first request
130
            },
131
            function(data, textStatus, jqXHR) {
132
                console.log("checkout.then failed");
133
            }
134
        );
135
136
    });
137
138
    $('#checkoutModal').on('click', '#checkoutConfirm', function(e) {
139
        let item_id = $('#item_id').val();
140
        let token = $('#confirmation_token').val();
141
        let params = {
142
            "checkout_id": undefined,
143
            "patron_id": logged_in_user_id,
144
            "item_id": item_id,
145
            "due_date": undefined,
146
            "library_id": undefined,
147
            "issuer_id": undefined,
148
            "checkin_date": undefined,
149
            "last_renewed_date": undefined,
150
            "renewals_count": undefined,
151
            "unseen_renewals": undefined,
152
            "auto_renew": undefined,
153
            "auto_renew_error": undefined,
154
            "timestamp": undefined,
155
            "checkout_date": undefined,
156
            "onsite_checkout": false,
157
            "note": undefined,
158
            "note_date": undefined,
159
            "note_seen": undefined,
160
        };
161
        let checkout = $.ajax({
162
            url: '/api/v1/public/checkouts?confirmation='+token,
163
            type: 'POST',
164
            data: JSON.stringify(params),
165
            contentType: "json"
166
        });
167
168
        checkout.then(
169
            function(data, textStatus, jqXHR) {
170
                console.log("checkout.then succeeded");
171
                $('#item_id').remove;
172
                $('#confirm_token').remove;
173
                $('#checkout_barcode').val("").focus();
174
                $('#checkoutConfirm').replaceWith('<button type="submit" id="checkoutSubmit" class="btn btn-primary">Submit</button>');
175
                // data retrieved from url2 as provided by the first request
176
            },
177
            function(data, textStatus, jqXHR) {
178
                console.log("checkout.then failed");
179
            }
180
        );
181
    });
182
});

Return to bug 30979