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

(-)a/.gitignore (+1 lines)
Lines 13-18 koha-tmpl/opac-tmpl/bootstrap/css/print.css Link Here
13
koha-tmpl/opac-tmpl/bootstrap/css/print-rtl.css
13
koha-tmpl/opac-tmpl/bootstrap/css/print-rtl.css
14
koha-tmpl/opac-tmpl/bootstrap/css/sco.css
14
koha-tmpl/opac-tmpl/bootstrap/css/sco.css
15
koha-tmpl/opac-tmpl/bootstrap/css/sco-rtl.css
15
koha-tmpl/opac-tmpl/bootstrap/css/sco-rtl.css
16
koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/
16
17
17
koha-tmpl/intranet-tmpl/prog/css/maps/
18
koha-tmpl/intranet-tmpl/prog/css/maps/
18
koha-tmpl/intranet-tmpl/prog/css/bookings.css
19
koha-tmpl/intranet-tmpl/prog/css/bookings.css
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Islands/PatronSelfRenewal/PatronSelfRenewal.vue (+171 lines)
Line 0 Link Here
1
<template>
2
    <div
3
        id="patronSelfRenewal"
4
        class="modal modal-full"
5
        tabindex="-1"
6
        role="dialog"
7
        aria-labelledby="patronSelfRenewal"
8
        aria-hidden="true"
9
    >
10
        <div class="modal-dialog modal-xl">
11
            <div v-if="initialized" class="modal-content">
12
                <div class="modal-header">
13
                    <h1 class="modal-title">
14
                        {{ $__("Patron self-renewal") }}
15
                    </h1>
16
                    <button
17
                        type="button"
18
                        class="btn-close"
19
                        data-bs-dismiss="modal"
20
                        aria-label="Close"
21
                    ></button>
22
                </div>
23
                <div class="modal-body">
24
                    <VerificationChecks
25
                        v-if="activeStep === 'verification'"
26
                        :verificationChecks="verificationChecks"
27
                        :renewalSettings="renewalSettings"
28
                        @verification-successful="onVerificationSuccess"
29
                    />
30
                    <VerificationChecks
31
                        v-if="activeStep === 'confirmation'"
32
                        :verificationChecks="[
33
                            {
34
                                description:
35
                                    'Are you sure you want to renew your account?',
36
                            },
37
                        ]"
38
                        :renewalSettings="renewalSettings"
39
                        :confirmation="true"
40
                        @verification-successful="submitRenewal"
41
                    />
42
                    <div v-if="activeStep === 'detailsCheck'">
43
                        <legend>
44
                            {{ $__("Confirm your account details") }}
45
                        </legend>
46
                        <div class="detail_confirmation">
47
                            <span>{{
48
                                $__(
49
                                    "You need to confirm your personal details to proceed with your account renewal."
50
                                )
51
                            }}</span>
52
                            <button
53
                                class="btn btn-default"
54
                                @click="proceedToDetailsVerification()"
55
                            >
56
                                {{ $__("Continue") }}
57
                            </button>
58
                        </div>
59
                    </div>
60
                </div>
61
                <div class="modal-footer">
62
                    <button
63
                        type="button"
64
                        class="btn btn-default cancel"
65
                        data-bs-dismiss="modal"
66
                    >
67
                        {{ $__("Close") }}
68
                    </button>
69
                </div>
70
            </div>
71
        </div>
72
    </div>
73
</template>
74
75
<script>
76
import { onBeforeMount, ref } from "vue";
77
import { APIClient } from "../../../fetch/api-client.js";
78
import VerificationChecks from "./VerificationChecks.vue";
79
import { $__ } from "@koha-vue/i18n";
80
81
export default {
82
    components: { VerificationChecks },
83
    setup(props) {
84
        const verificationChecks = ref([]);
85
        const initialized = ref(false);
86
        const activeStep = ref(null);
87
        const renewalSettings = ref({
88
            defaultErrorMessage: $__(
89
                "You are not able to self-renew with the provided information. Please visit your library to proceed with your renewal."
90
            ),
91
        });
92
93
        onBeforeMount(() => {
94
            const client = APIClient.patron;
95
            client.self_renewal.start().then(
96
                response => {
97
                    verificationChecks.value = response.verification_checks;
98
                    renewalSettings.value = {
99
                        ...renewalSettings.value,
100
                        ...response.self_renewal_settings,
101
                    };
102
                    activeStep.value = verificationChecks.value.length
103
                        ? "verification"
104
                        : response.self_renewal_settings.opac_patron_details ===
105
                            "1"
106
                          ? "detailsCheck"
107
                          : "confirmation";
108
                    initialized.value = true;
109
                },
110
                error => {}
111
            );
112
        });
113
114
        const proceedToDetailsVerification = () => {
115
            window.location.href =
116
                "/cgi-bin/koha/opac-memberentry.pl?self_renewal=1";
117
        };
118
119
        const onVerificationSuccess = () => {
120
            if (renewalSettings.value.opac_patron_details === "1") {
121
                activeStep.value = "detailsCheck";
122
            } else {
123
                activeStep.value = "confirmation";
124
            }
125
        };
126
127
        const submitRenewal = () => {
128
            const client = APIClient.patron;
129
            client.self_renewal.submit({}).then(
130
                response => {
131
                    let newLocation =
132
                        "/cgi-bin/koha/opac-user.pl?self_renewal_success=" +
133
                        response.expiry_date;
134
                    if (response.confirmation_sent) {
135
                        newLocation += "&confirmation_sent=1";
136
                    }
137
                    document.location = newLocation;
138
                },
139
                error => {
140
                    document.location =
141
                        "/cgi-bin/koha/opac-user.pl?self_renewal_success=0";
142
                }
143
            );
144
        };
145
146
        return {
147
            initialized,
148
            activeStep,
149
            verificationChecks,
150
            renewalSettings,
151
            onVerificationSuccess,
152
            proceedToDetailsVerification,
153
            submitRenewal,
154
        };
155
    },
156
};
157
</script>
158
159
<style scoped>
160
.detail_confirmation {
161
    display: flex;
162
    flex-direction: column;
163
    gap: 1em;
164
}
165
.detail_confirmation button {
166
    display: flex;
167
    flex-direction: column;
168
    gap: 1em;
169
    width: 7em;
170
}
171
</style>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Islands/PatronSelfRenewal/VerificationChecks.vue (+85 lines)
Line 0 Link Here
1
<template>
2
    <fieldset class="rows" v-if="!verificationFailure">
3
        <legend v-if="!confirmation">
4
            {{ $__("Verification step %s").format(completedCount + 1) }}
5
        </legend>
6
        <span class="verification_question">{{ activeCheck.description }}</span>
7
        <div class="verification_actions">
8
            <button class="btn btn-success" @click="verificationPassed()">
9
                {{ $__("Yes") }}
10
            </button>
11
            <button class="btn btn-default" @click="verificationFailed()">
12
                {{ $__("No") }}
13
            </button>
14
        </div>
15
    </fieldset>
16
    <span class="error" v-else>{{ errorMessage }}</span>
17
</template>
18
19
<script>
20
import { computed, ref } from "vue";
21
import { $__ } from "@koha-vue/i18n";
22
23
export default {
24
    props: {
25
        verificationChecks: Array,
26
        renewalSettings: Object,
27
        confirmation: Boolean,
28
    },
29
    emits: ["verification-successful"],
30
    setup(props, { emit }) {
31
        const checkCount = ref(props.verificationChecks.length);
32
        const completedCount = ref(0);
33
        const verificationFailure = ref(false);
34
35
        const activeCheck = ref(props.verificationChecks[0]);
36
37
        const verificationPassed = () => {
38
            if (completedCount.value === checkCount.value - 1) {
39
                emit("verification-successful");
40
            } else {
41
                completedCount.value++;
42
                activeCheck.value =
43
                    props.verificationChecks[completedCount.value];
44
            }
45
        };
46
        const verificationFailed = () => {
47
            verificationFailure.value = true;
48
        };
49
50
        const errorMessage = computed(() => {
51
            const { self_renewal_failure_message, defaultErrorMessage } =
52
                props.renewalSettings;
53
            return self_renewal_failure_message || defaultErrorMessage;
54
        });
55
56
        return {
57
            checkCount,
58
            activeCheck,
59
            verificationPassed,
60
            verificationFailed,
61
            verificationFailure,
62
            errorMessage,
63
            completedCount,
64
        };
65
    },
66
};
67
</script>
68
69
<style scoped>
70
.rows {
71
    display: flex;
72
    flex-direction: column;
73
}
74
.verification_actions {
75
    display: flex;
76
    gap: 1em;
77
}
78
.verification_actions button {
79
    width: 5em;
80
}
81
.verification_question {
82
    margin-bottom: 2em;
83
    font-size: 100%;
84
}
85
</style>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts (+13 lines)
Lines 72-77 export const componentRegistry: Map<string, WebComponentDynamicImport> = Link Here
72
                },
72
                },
73
            },
73
            },
74
        ],
74
        ],
75
        [
76
            "patron-self-renewal",
77
            {
78
                importFn: async () => {
79
                    const module = await import(
80
                        /* webpackChunkName: "patron-self-renewal" */
81
                        "../components/Islands/PatronSelfRenewal/PatronSelfRenewal.vue"
82
                    );
83
                    return module.default;
84
                },
85
                config: {},
86
            },
87
        ],
75
    ]);
88
    ]);
76
89
77
/**
90
/**
(-)a/rspack.config.js (-29 / +39 lines)
Lines 3-10 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
module.exports = [
6
const islandsExport = application => {
7
    {
7
    const vueDir =
8
        application === "intranet"
9
            ? "intranet-tmpl/prog"
10
            : "opac-tmpl/bootstrap";
11
12
    return {
8
        resolve: {
13
        resolve: {
9
            alias: {
14
            alias: {
10
                "@fetch": path.resolve(
15
                "@fetch": path.resolve(
Lines 15-42 module.exports = [ Link Here
15
                    __dirname,
20
                    __dirname,
16
                    "koha-tmpl/intranet-tmpl/prog/js/vue"
21
                    "koha-tmpl/intranet-tmpl/prog/js/vue"
17
                ),
22
                ),
18
                "@cypress": path.resolve(__dirname, "t/cypress"),
19
            },
23
            },
20
        },
24
        },
25
        experiments: {
26
            outputModule: true,
27
        },
21
        entry: {
28
        entry: {
22
            erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
23
            preservation:
24
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
25
            "admin/record_sources":
26
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
27
            acquisitions:
28
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/acquisitions.ts",
29
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
29
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
30
            sip2: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/sip2.ts",
31
        },
30
        },
32
        output: {
31
        output: {
33
            filename: "[name].js",
32
            filename: "[name].esm.js",
34
            path: path.resolve(
33
            path: path.resolve(__dirname, `koha-tmpl/${vueDir}/js/vue/dist/`),
35
                __dirname,
34
            chunkFilename: "[name].[contenthash].esm.js",
36
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
37
            ),
38
            chunkFilename: "[name].[contenthash].js",
39
            globalObject: "window",
35
            globalObject: "window",
36
            library: {
37
                type: "module",
38
            },
40
        },
39
        },
41
        module: {
40
        module: {
42
            rules: [
41
            rules: [
Lines 46-52 module.exports = [ Link Here
46
                    options: {
45
                    options: {
47
                        experimentalInlineMatchResource: true,
46
                        experimentalInlineMatchResource: true,
48
                    },
47
                    },
49
                    //exclude: [path.resolve(__dirname, "t/cypress/")],
48
                    exclude: [path.resolve(__dirname, "t/cypress/")],
50
                },
49
                },
51
                {
50
                {
52
                    test: /\.ts$/,
51
                    test: /\.ts$/,
Lines 88-94 module.exports = [ Link Here
88
            "datatables.net-buttons/js/buttons.print": "DataTable",
87
            "datatables.net-buttons/js/buttons.print": "DataTable",
89
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
88
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
90
        },
89
        },
91
    },
90
    };
91
};
92
93
module.exports = [
92
    {
94
    {
93
        resolve: {
95
        resolve: {
94
            alias: {
96
            alias: {
Lines 96-120 module.exports = [ Link Here
96
                    __dirname,
98
                    __dirname,
97
                    "koha-tmpl/intranet-tmpl/prog/js/fetch"
99
                    "koha-tmpl/intranet-tmpl/prog/js/fetch"
98
                ),
100
                ),
101
                "@koha-vue": path.resolve(
102
                    __dirname,
103
                    "koha-tmpl/intranet-tmpl/prog/js/vue"
104
                ),
105
                "@cypress": path.resolve(__dirname, "t/cypress"),
99
            },
106
            },
100
        },
107
        },
101
        experiments: {
102
            outputModule: true,
103
        },
104
        entry: {
108
        entry: {
109
            erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
110
            preservation:
111
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
112
            "admin/record_sources":
113
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
114
            acquisitions:
115
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/acquisitions.ts",
105
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
116
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
117
            sip2: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/sip2.ts",
106
        },
118
        },
107
        output: {
119
        output: {
108
            filename: "[name].esm.js",
120
            filename: "[name].js",
109
            path: path.resolve(
121
            path: path.resolve(
110
                __dirname,
122
                __dirname,
111
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
123
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
112
            ),
124
            ),
113
            chunkFilename: "[name].[contenthash].esm.js",
125
            chunkFilename: "[name].[contenthash].js",
114
            globalObject: "window",
126
            globalObject: "window",
115
            library: {
116
                type: "module",
117
            },
118
        },
127
        },
119
        module: {
128
        module: {
120
            rules: [
129
            rules: [
Lines 124-130 module.exports = [ Link Here
124
                    options: {
133
                    options: {
125
                        experimentalInlineMatchResource: true,
134
                        experimentalInlineMatchResource: true,
126
                    },
135
                    },
127
                    exclude: [path.resolve(__dirname, "t/cypress/")],
136
                    //exclude: [path.resolve(__dirname, "t/cypress/")],
128
                },
137
                },
129
                {
138
                {
130
                    test: /\.ts$/,
139
                    test: /\.ts$/,
Lines 167-172 module.exports = [ Link Here
167
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
176
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
168
        },
177
        },
169
    },
178
    },
179
    islandsExport("intranet"),
180
    islandsExport("opac"),
170
    {
181
    {
171
        entry: {
182
        entry: {
172
            "api-client.cjs":
183
            "api-client.cjs":
173
- 

Return to bug 26355