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

(-)a/koha-tmpl/shared/js/cookieconsent.js (+199 lines)
Line 0 Link Here
1
(function () {
2
    // Has the user previously consented, establish our
3
    // initial state
4
    let selected = [];
5
    let existingConsent = "";
6
    // The presence of a 'cookieConsent' local storage item indicates
7
    // that previous consent has been set. If the value is empty, then
8
    // no consent to non-essential cookies was given
9
    const hasStoredConsent = localStorage.getItem("cookieConsent");
10
    getExistingConsent();
11
12
    // The consent bar may not be in the DOM if it is not being used
13
    const consentBar = $("#cookieConsentBar");
14
    if (!consentBar) {
15
        return;
16
    }
17
18
    // Initialize the consent modal and prevent the modal
19
    // from being closed with anything but the buttons
20
    const cookieConsentModal = new bootstrap.Modal(
21
        document.getElementById("cookieConsentModal"),
22
        {
23
            backdrop: "static",
24
            keyboard: false,
25
            focus: true,
26
            show: true,
27
        }
28
    );
29
30
    if (hasStoredConsent === null) {
31
        showConsentBar();
32
    }
33
    addButtonHandlers();
34
35
    // When the modal is opened, populate our state based on currently
36
    // selected values
37
    const cookieConsentModalEl = document.getElementById("cookieConsentModal");
38
    cookieConsentModalEl.addEventListener("shown.bs.modal", () => {
39
        initialiseSelected();
40
    });
41
42
    // Initialise existing consent based on local storage
43
    function getExistingConsent() {
44
        existingConsent = localStorage.getItem("cookieConsent")
45
            ? localStorage.getItem("cookieConsent")
46
            : [];
47
    }
48
49
    function showConsentBar() {
50
        const consentBar = $("#cookieConsentBar");
51
        const langmenu = $("#changelanguage");
52
        if (langmenu) {
53
            const height = langmenu.height();
54
            consentBar.css("bottom", height);
55
        }
56
        consentBar.attr("aria-hidden", "false");
57
        consentBar.css("display", "flex");
58
    }
59
60
    function hideConsentBar() {
61
        const consentBar = $("#cookieConsentBar");
62
        consentBar.attr("aria-hidden", "true");
63
        consentBar.hide();
64
    }
65
66
    // Hides the appropriate consent container, depending on what
67
    // is currently visible
68
    function hideContainer() {
69
        if ($(cookieConsentModalEl).is(":visible")) {
70
            cookieConsentModal.hide();
71
        } else {
72
            hideConsentBar();
73
        }
74
    }
75
76
    // Initialise our state of selected item and enable/disable
77
    // the "Accept selected" button appropriately
78
    function initialiseSelected() {
79
        selected = [];
80
        $(".consentCheckbox").each(function () {
81
            const val = $(this).val();
82
            if (existingConsent.indexOf(val) > -1) {
83
                $(this).prop("checked", true);
84
                selected.push(val);
85
            } else {
86
                $(this).prop("checked", false);
87
            }
88
        });
89
        enableDisableSelectedButton();
90
    }
91
92
    // Maintain our state of selected items and enable/disable
93
    // the "Accept selected" button appropriately
94
    function maintainSelected() {
95
        selected = [];
96
        $(".consentCheckbox:checked").each(function () {
97
            selected.push($(this).val());
98
        });
99
        enableDisableSelectedButton();
100
    }
101
102
    // Set the enabled / disabled state of the
103
    // "Accept selected button based on the checkbox
104
    // states
105
    function enableDisableSelectedButton() {
106
        $("#consentAcceptSelected").prop("disabled", selected.length === 0);
107
    }
108
109
    function runConsentedCode() {
110
        getExistingConsent();
111
        $(".consentCode").each(function () {
112
            // The user has explicitly consented to this code, or the
113
            // code doesn't require consent in the staff view
114
            if (
115
                existingConsent.indexOf($(this).data("consent-id")) > -1 ||
116
                !$(this).data("requires-consent")
117
            ) {
118
                const code = atob($(this).data("consent-code"));
119
                const func = Function(code);
120
                func();
121
            } else {
122
                // This code doesn't have consent to run, we may need to remove
123
                // any cookies it has previously set
124
                const matchPattern = $(this).data("consent-match-pattern");
125
                const cookieDomain = $(this).data("consent-cookie-domain");
126
                const cookiePath = $(this).data("consent-cookie-path");
127
                if (matchPattern.length > 0) {
128
                    const regex = new RegExp(matchPattern);
129
                    const allCookies = document.cookie.split("; ");
130
                    allCookies.forEach(function (cookie) {
131
                        const name = cookie.split("=")[0];
132
                        if (regex.test(name)) {
133
                            document.cookie =
134
                                name +
135
                                "=; expires=Thu, 01 Jan 1970 00:00:01 GMT; domain=" +
136
                                cookieDomain +
137
                                "; path=" +
138
                                cookiePath;
139
                        }
140
                    });
141
                }
142
            }
143
        });
144
    }
145
146
    function addButtonHandlers() {
147
        // "Accept all" handler
148
        $(".consentAcceptAll").on("click", function (e) {
149
            e.preventDefault();
150
            let toSave = [];
151
            $(".consentCheckbox").each(function () {
152
                const val = $(this).val();
153
                toSave.push(val);
154
            });
155
            localStorage.setItem("cookieConsent", toSave);
156
            hideContainer();
157
            runConsentedCode();
158
        });
159
160
        // "Accept essential" handler
161
        $(".consentAcceptEssential").on("click", function (e) {
162
            e.preventDefault();
163
            localStorage.setItem("cookieConsent", []);
164
            hideContainer();
165
            runConsentedCode();
166
        });
167
168
        // "Accept selected" handler
169
        $("#consentAcceptSelected").on("click", function (e) {
170
            e.preventDefault();
171
            const toSave = selected.length > 0 ? selected : [];
172
            localStorage.setItem("cookieConsent", toSave);
173
            hideContainer();
174
            runConsentedCode();
175
        });
176
177
        // "Cancel" handler
178
        $(".consentCloseModal").on("click", function (e) {
179
            e.preventDefault();
180
            hideContainer();
181
            showConsentBar();
182
        });
183
184
        // "More information" handler
185
        $("#consentMoreInfo, #viewCookieConsents").on("click", function (e) {
186
            e.preventDefault();
187
            hideConsentBar();
188
            // Ensure we're up to date with the existing consent
189
            getExistingConsent();
190
            cookieConsentModal.show();
191
        });
192
        $(".consentCheckbox").on("click", function () {
193
            maintainSelected();
194
        });
195
    }
196
197
    // On page load, run any code that has been given consent
198
    runConsentedCode();
199
})();
(-)a/rspack.config.js (-1 / +78 lines)
Lines 3-9 const { VueLoaderPlugin } = require("vue-loader"); Link Here
3
const path = require("path");
3
const path = require("path");
4
const rspack = require("@rspack/core");
4
const rspack = require("@rspack/core");
5
5
6
const sharedAssetsStaffConfig = {
7
    name: "shared-assets-staff",
8
    entry: {
9
        cookieconsent: "./koha-tmpl/shared/js/cookieconsent.js",
10
        // Future shared modules:
11
        // coce: "./koha-tmpl/shared/js/coce.js",
12
        // "ill-availability": "./koha-tmpl/shared/js/ill-availability.js",
13
        // and so on...
14
    },
15
    output: {
16
        filename: "[name].js",
17
        path: path.resolve(__dirname, "koha-tmpl/intranet-tmpl/prog/js/"),
18
    },
19
    module: {
20
        rules: [
21
            {
22
                test: /\.js$/,
23
                loader: "builtin:swc-loader",
24
                options: {
25
                    jsc: {
26
                        parser: {
27
                            syntax: "ecmascript",
28
                        },
29
                    },
30
                },
31
                exclude: [/node_modules/],
32
                type: "javascript/auto",
33
            },
34
        ],
35
    },
36
    externals: {
37
        jquery: "jQuery",
38
    },
39
    optimization: {
40
        minimize: process.env.NODE_ENV === "production",
41
    },
42
};
43
44
const sharedAssetsOpacConfig = {
45
    name: "shared-assets-opac",
46
    entry: {
47
        cookieconsent: "./koha-tmpl/shared/js/cookieconsent.js",
48
        // Future shared modules:
49
        // coce: "./koha-tmpl/shared/js/coce.js",
50
        // "ill-availability": "./koha-tmpl/shared/js/ill-availability.js",
51
        // and so on...
52
    },
53
    output: {
54
        filename: "[name].js",
55
        path: path.resolve(__dirname, "koha-tmpl/opac-tmpl/bootstrap/js/"),
56
    },
57
    module: {
58
        rules: [
59
            {
60
                test: /\.js$/,
61
                loader: "builtin:swc-loader",
62
                options: {
63
                    jsc: {
64
                        parser: {
65
                            syntax: "ecmascript",
66
                        },
67
                    },
68
                },
69
                exclude: [/node_modules/],
70
                type: "javascript/auto",
71
            },
72
        ],
73
    },
74
    externals: {
75
        jquery: "jQuery",
76
    },
77
    optimization: {
78
        minimize: process.env.NODE_ENV === "production",
79
    },
80
};
81
6
module.exports = [
82
module.exports = [
83
    sharedAssetsStaffConfig,
84
    sharedAssetsOpacConfig,
7
    {
85
    {
8
        resolve: {
86
        resolve: {
9
            alias: {
87
            alias: {
10
- 

Return to bug 35716