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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt (-1 / +20 lines)
Lines 347-354 Link Here
347
</div>
347
</div>
348
<!-- /.row -->
348
<!-- /.row -->
349
349
350
<div class="row w-25 m-auto p-4 border border-4 border-warning br-5 rounded text-center mt-4">
351
    <dialog-island id="surprise"></dialog-island>
352
    <button id="surprise-button" class="btn btn-primary">Click me for a surprise!</button>
353
</div>
354
350
[% MACRO jsinclude BLOCK %]
355
[% MACRO jsinclude BLOCK %]
351
    [% Asset.js("js/vue/dist/islands.js", "type" => "module") | $raw %]
356
    [% INCLUDE 'calendar.inc' %]
357
    [% Asset.js("js/vue/dist/islands.js", "init" => "1") | $raw %]
358
    <!--
359
    [% SET islands = Asset.js("js/vue/dist/islands.esm.js").match('(src="([^"]+)")').1 %]
360
    <script src="[% islands %]" type="module">
361
</script>
362
    <script type="module">
363
        import { hydrate } from "[% islands %]";
364
        hydrate();
365
    </script>
366
    -->
352
    <script>
367
    <script>
353
        var MSG_CONFIRM_DELETE = _("Are you sure you want to delete this news item? This cannot be undone.");
368
        var MSG_CONFIRM_DELETE = _("Are you sure you want to delete this news item? This cannot be undone.");
354
        $(document).ready(function () {
369
        $(document).ready(function () {
Lines 360-365 Link Here
360
                const [firstHelloIslandsElement] = document.getElementsByTagName("hello-islands");
375
                const [firstHelloIslandsElement] = document.getElementsByTagName("hello-islands");
361
                firstHelloIslandsElement.message = "This is a delayed update to the message attribute of the web commponent.";
376
                firstHelloIslandsElement.message = "This is a delayed update to the message attribute of the web commponent.";
362
            }, 2000);
377
            }, 2000);
378
379
            $("#surprise-button").on("click", () => {
380
                $("#surprise").attr("warning", `<span>Yes, this is <span class="font-monospace">Dialog.vue</span> (in a wrapper component)!</span><span class="d-none">${Math.random()}</span>`);
381
            });
363
        });
382
        });
364
    </script>
383
    </script>
365
[% END %]
384
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Islands/DialogIsland.vue (+107 lines)
Line 0 Link Here
1
<template>
2
    <Dialog />
3
</template>
4
5
<script>
6
import { inject, watch } from "vue";
7
import Dialog from "../Dialog.vue";
8
9
export default {
10
    props: {
11
        message: {
12
            type: String,
13
            default: null,
14
        },
15
        error: {
16
            type: String,
17
            default: null,
18
        },
19
        warning: {
20
            type: String,
21
            default: null,
22
        },
23
        confirmation: {
24
            type: Object,
25
            default: () => null,
26
        },
27
        isSubmitting: {
28
            type: Boolean,
29
            default: false,
30
        },
31
        isLoading: {
32
            type: Boolean,
33
            default: false,
34
        },
35
        acceptCallback: {
36
            type: Function,
37
            default: null,
38
        },
39
    },
40
    setup(props) {
41
        const mainStore = inject("mainStore");
42
        const {
43
            setMessage,
44
            setError,
45
            setWarning,
46
            setConfirmation,
47
            setSubmitting,
48
            setLoading,
49
            setAcceptCallback,
50
        } = mainStore;
51
52
        watch(
53
            () => props.message,
54
            newVal => {
55
                setMessage(newVal);
56
            }
57
        );
58
59
        watch(
60
            () => props.error,
61
            newVal => {
62
                setError(newVal);
63
            }
64
        );
65
66
        watch(
67
            () => props.warning,
68
            newVal => {
69
                setWarning(newVal);
70
            }
71
        );
72
73
        watch(
74
            () => props.confirmation,
75
            newVal => {
76
                setConfirmation(newVal);
77
            }
78
        );
79
80
        watch(
81
            () => props.isSubmitting,
82
            newVal => {
83
                setSubmitting(newVal);
84
            }
85
        );
86
87
        watch(
88
            () => props.isLoading,
89
            newVal => {
90
                setLoading(newVal);
91
            }
92
        );
93
94
        watch(
95
            () => props.acceptCallback,
96
            newVal => {
97
                setAcceptCallback(newVal);
98
            }
99
        );
100
101
        return {};
102
    },
103
    components: {
104
        Dialog,
105
    },
106
};
107
</script>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts (-3 / +22 lines)
Lines 1-5 Link Here
1
import { Component, defineCustomElement } from "vue";
1
import { Component, defineCustomElement } from "vue";
2
import { createPinia } from "pinia";
2
import { createPinia } from "pinia";
3
import { $__ } from "../i18n";
3
import { useMainStore } from "../stores/main";
4
import { useMainStore } from "../stores/main";
4
import { useNavigationStore } from "../stores/navigation";
5
import { useNavigationStore } from "../stores/navigation";
5
6
Lines 27-33 export const componentRegistry: Map<string, WebComponentDynamicImport> = Link Here
27
                importFn: async () => {
28
                importFn: async () => {
28
                    const module = await import(
29
                    const module = await import(
29
                        /* webpackChunkName: "hello-islands" */
30
                        /* webpackChunkName: "hello-islands" */
30
                        "../components/HelloIslands.vue"
31
                        "../components/Islands/HelloIslands.vue"
31
                    );
32
                    );
32
                    return module.default;
33
                    return module.default;
33
                },
34
                },
Lines 42-53 export const componentRegistry: Map<string, WebComponentDynamicImport> = Link Here
42
                importFn: async () => {
43
                importFn: async () => {
43
                    const module = await import(
44
                    const module = await import(
44
                        /* webpackChunkName: "hello-world" */
45
                        /* webpackChunkName: "hello-world" */
45
                        "../components/HelloWorld.vue"
46
                        "../components/Islands/HelloWorld.vue"
46
                    );
47
                    );
47
                    return module.default;
48
                    return module.default;
48
                },
49
                },
49
            },
50
            },
50
        ],
51
        ],
52
        [
53
            "dialog-island",
54
            {
55
                importFn: async () => {
56
                    const module = await import(
57
                        /* webpackChunkName: "vue-dialog" */
58
                        "../components/Islands/DialogIsland.vue"
59
                    );
60
                    return module.default;
61
                },
62
                config: {
63
                    stores: ["mainStore"],
64
                },
65
            },
66
        ],
51
    ]);
67
    ]);
52
68
53
/**
69
/**
Lines 88-93 export function hydrate(): void { Link Here
88
                                    app.provide(store, storesMatrix[store]);
104
                                    app.provide(store, storesMatrix[store]);
89
                                });
105
                                });
90
                            }
106
                            }
107
                            app.config.globalProperties.$__ = $__;
91
                            // Further config options can be added here as we expand this further
108
                            // Further config options can be added here as we expand this further
92
                        },
109
                        },
93
                    }),
110
                    }),
Lines 97-100 export function hydrate(): void { Link Here
97
    });
114
    });
98
}
115
}
99
116
100
hydrate();
117
if (parseInt(document?.currentScript?.getAttribute("init") ?? "0", 10)) {
118
    hydrate();
119
}
(-)a/rspack.config.js (-81 / +136 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
module.exports = [
7
    resolve: {
7
    {
8
        resolve: {
8
        alias: {
9
        alias: {
9
            "@fetch": path.resolve(
10
            "@fetch": path.resolve(
10
                __dirname,
11
                __dirname,
Lines 13-102 module.exports = { Link Here
13
        },
14
        },
14
    },
15
    },
15
    experiments: {
16
    experiments: {
16
        css: true,
17
            css: true,
17
    },
18
        },
18
    entry: {
19
        entry: {
19
        erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
20
            erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
20
        preservation:
21
            preservation:
21
            "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
22
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
22
        "admin/record_sources":
23
            "admin/record_sources":
23
            "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
24
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
24
        islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
25
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
25
    },
26
        },
26
    output: {
27
        output: {
27
        filename: "[name].js",
28
            filename: "[name].js",
28
        path: path.resolve(
29
            path: path.resolve(
29
            __dirname,
30
                __dirname,
30
            "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
31
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
31
        ),
32
            ),
32
        chunkFilename: "[name].[contenthash].js",
33
            chunkFilename: "[name].[contenthash].js",
33
        globalObject: "window",
34
            globalObject: "window",
34
    },
35
        },
35
    module: {
36
        module: {
36
        rules: [
37
            rules: [
37
            {
38
                {
38
                test: /\.vue$/,
39
                    test: /\.vue$/,
39
                loader: "vue-loader",
40
                    loader: "vue-loader",
40
                options: {
41
                    options: {
41
                    experimentalInlineMatchResource: true,
42
                        experimentalInlineMatchResource: true,
43
                    },
44
                    exclude: [path.resolve(__dirname, "t/cypress/")],
42
                },
45
                },
43
                exclude: [path.resolve(__dirname, "t/cypress/")],
46
                {
44
            },
47
                    test: /\.ts$/,
45
            {
48
                    loader: "builtin:swc-loader",
46
                test: /\.ts$/,
49
                    options: {
47
                loader: "builtin:swc-loader",
50
                        jsc: {
48
                options: {
51
                            parser: {
49
                    jsc: {
52
                                syntax: "typescript",
50
                        parser: {
53
                            },
51
                            syntax: "typescript",
52
                        },
54
                        },
55
                        appendTsSuffixTo: [/\.vue$/],
53
                    },
56
                    },
54
                    appendTsSuffixTo: [/\.vue$/],
57
                    exclude: [
58
                        /node_modules/,
59
                        path.resolve(__dirname, "t/cypress/"),
60
                    ],
61
                    type: "javascript/auto",
55
                },
62
                },
56
                exclude: [
63
                {
57
                    /node_modules/,
64
                    test: /\.css$/i,
58
                    path.resolve(__dirname, "t/cypress/"),
65
                    type: "javascript/auto",
59
                ],
66
                    use: ["style-loader", "css-loader"],
60
                type: "javascript/auto",
67
                },
61
            },
68
            ],
62
            {
69
        },
63
                test: /\.css$/i,
70
        plugins: [
64
                type: "javascript/auto",
71
            new VueLoaderPlugin(),
65
                use: ["style-loader", "css-loader"],
72
            new rspack.DefinePlugin({
66
            },
73
                __VUE_OPTIONS_API__: true,
74
                __VUE_PROD_DEVTOOLS__: false,
75
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
76
            }),
67
        ],
77
        ],
78
        externals: {
79
            jquery: "jQuery",
80
            "datatables.net": "DataTable",
81
            "datatables.net-buttons": "DataTable",
82
            "datatables.net-buttons/js/buttons.html5": "DataTable",
83
            "datatables.net-buttons/js/buttons.print": "DataTable",
84
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
85
        },
68
    },
86
    },
69
    /**
87
    {
70
    optimization: {
88
        experiments: {
71
        splitChunks: {
89
            css: true,
72
            chunks: "all",
90
            outputModule: true,
73
            cacheGroups: {
91
        },
74
                default: false, // Disable default cache groups to avoid affecting existing bundles
92
        entry: {
75
                vendors: false, // Disable vendor caching
93
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
76
                vue: {
94
        },
77
                    test: /[\\/]node_modules[\\/]vue[\\/]/,
95
        output: {
78
                    name: "vue",
96
            filename: "[name].esm.js",
79
                    chunks: "all",
97
            path: path.resolve(
80
                    enforce: true,
98
                __dirname,
81
                },
99
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
100
            ),
101
            chunkFilename: "[name].[contenthash].esm.js",
102
            globalObject: "window",
103
            library: {
104
                type: "module",
82
            },
105
            },
83
        },
106
        },
107
        module: {
108
            rules: [
109
                {
110
                    test: /\.vue$/,
111
                    loader: "vue-loader",
112
                    options: {
113
                        experimentalInlineMatchResource: true,
114
                    },
115
                    exclude: [path.resolve(__dirname, "t/cypress/")],
116
                },
117
                {
118
                    test: /\.ts$/,
119
                    loader: "builtin:swc-loader",
120
                    options: {
121
                        jsc: {
122
                            parser: {
123
                                syntax: "typescript",
124
                            },
125
                        },
126
                        appendTsSuffixTo: [/\.vue$/],
127
                    },
128
                    exclude: [
129
                        /node_modules/,
130
                        path.resolve(__dirname, "t/cypress/"),
131
                    ],
132
                    type: "javascript/auto",
133
                },
134
                {
135
                    test: /\.css$/i,
136
                    type: "javascript/auto",
137
                    use: ["style-loader", "css-loader"],
138
                },
139
            ],
140
        },
141
        plugins: [
142
            new VueLoaderPlugin(),
143
            new rspack.DefinePlugin({
144
                __VUE_OPTIONS_API__: true,
145
                __VUE_PROD_DEVTOOLS__: false,
146
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
147
            }),
148
        ],
149
        externals: {
150
            jquery: "jQuery",
151
            "datatables.net": "DataTable",
152
            "datatables.net-buttons": "DataTable",
153
            "datatables.net-buttons/js/buttons.html5": "DataTable",
154
            "datatables.net-buttons/js/buttons.print": "DataTable",
155
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
156
        },
84
    },
157
    },
85
    */
158
];
86
    plugins: [
87
        new VueLoaderPlugin(),
88
        new rspack.DefinePlugin({
89
            __VUE_OPTIONS_API__: true,
90
            __VUE_PROD_DEVTOOLS__: false,
91
            __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
92
        }),
93
    ],
94
    externals: {
95
        jquery: "jQuery",
96
        "datatables.net": "DataTable",
97
        "datatables.net-buttons": "DataTable",
98
        "datatables.net-buttons/js/buttons.html5": "DataTable",
99
        "datatables.net-buttons/js/buttons.print": "DataTable",
100
        "datatables.net-buttons/js/buttons.colVis": "DataTable",
101
    },
102
};
103
- 

Return to bug 37911