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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt (-1 / +19 lines)
Lines 315-322 Link Here
315
            <!-- <hello-world></hello-world> -->
315
            <!-- <hello-world></hello-world> -->
316
        </div> <!-- /.row -->
316
        </div> <!-- /.row -->
317
317
318
        <div class="row w-25 m-auto p-4 border border-4 border-warning br-5 rounded text-center mt-4">
319
            <dialog-island id="surprise"></dialog-island>
320
            <button id="surprise-button" class="btn btn-primary">Click me for a surprise!</button>
321
        </div>
322
318
[% MACRO jsinclude BLOCK %]
323
[% MACRO jsinclude BLOCK %]
319
    [% Asset.js("js/vue/dist/islands.js", "type" => "module") | $raw %]
324
    [% INCLUDE 'calendar.inc' %]
325
    [% Asset.js("js/vue/dist/islands.js", "init" => "1") | $raw %]
326
    <!--
327
    [% SET islands = Asset.js("js/vue/dist/islands.esm.js").match('(src="([^"]+)")').1 %]
328
    <script src="[% islands %]" type="module"></script>
329
    <script type="module">
330
        import { hydrate } from "[% islands %]";
331
        hydrate();
332
    </script>
333
    -->
320
    <script>
334
    <script>
321
        var MSG_CONFIRM_DELETE = _("Are you sure you want to delete this news item? This cannot be undone.");
335
        var MSG_CONFIRM_DELETE = _("Are you sure you want to delete this news item? This cannot be undone.");
322
        $(document).ready(function(){
336
        $(document).ready(function(){
Lines 328-333 Link Here
328
                const [firstHelloIslandsElement] = document.getElementsByTagName("hello-islands");
342
                const [firstHelloIslandsElement] = document.getElementsByTagName("hello-islands");
329
                firstHelloIslandsElement.message = 'This is a delayed update to the message attribute of the web commponent.'
343
                firstHelloIslandsElement.message = 'This is a delayed update to the message attribute of the web commponent.'
330
            }, 2000);
344
            }, 2000);
345
346
            $("#surprise-button").on("click", () => {
347
                $("#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>`);
348
            });
331
        });
349
        });
332
    </script>
350
    </script>
333
[% END %]
351
[% 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-94 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
    experiments: {
7
    {
8
        css: true,
8
        experiments: {
9
    },
9
            css: true,
10
    entry: {
10
        },
11
        erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
11
        entry: {
12
        preservation:
12
            erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts",
13
            "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
13
            preservation:
14
        "admin/record_sources":
14
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts",
15
            "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
15
            "admin/record_sources":
16
        islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
16
                "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts",
17
    },
17
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
18
    output: {
18
        },
19
        filename: "[name].js",
19
        output: {
20
        path: path.resolve(
20
            filename: "[name].js",
21
            __dirname,
21
            path: path.resolve(
22
            "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
22
                __dirname,
23
        ),
23
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
24
        chunkFilename: "[name].[contenthash].js",
24
            ),
25
        globalObject: "window",
25
            chunkFilename: "[name].[contenthash].js",
26
    },
26
            globalObject: "window",
27
    module: {
27
        },
28
        rules: [
28
        module: {
29
            {
29
            rules: [
30
                test: /\.vue$/,
30
                {
31
                loader: "vue-loader",
31
                    test: /\.vue$/,
32
                options: {
32
                    loader: "vue-loader",
33
                    experimentalInlineMatchResource: true,
33
                    options: {
34
                        experimentalInlineMatchResource: true,
35
                    },
36
                    exclude: [path.resolve(__dirname, "t/cypress/")],
34
                },
37
                },
35
                exclude: [path.resolve(__dirname, "t/cypress/")],
38
                {
36
            },
39
                    test: /\.ts$/,
37
            {
40
                    loader: "builtin:swc-loader",
38
                test: /\.ts$/,
41
                    options: {
39
                loader: "builtin:swc-loader",
42
                        jsc: {
40
                options: {
43
                            parser: {
41
                    jsc: {
44
                                syntax: "typescript",
42
                        parser: {
45
                            },
43
                            syntax: "typescript",
44
                        },
46
                        },
47
                        appendTsSuffixTo: [/\.vue$/],
45
                    },
48
                    },
46
                    appendTsSuffixTo: [/\.vue$/],
49
                    exclude: [
50
                        /node_modules/,
51
                        path.resolve(__dirname, "t/cypress/"),
52
                    ],
53
                    type: "javascript/auto",
47
                },
54
                },
48
                exclude: [
55
                {
49
                    /node_modules/,
56
                    test: /\.css$/i,
50
                    path.resolve(__dirname, "t/cypress/"),
57
                    type: "javascript/auto",
51
                ],
58
                    use: ["style-loader", "css-loader"],
52
                type: "javascript/auto",
59
                },
53
            },
60
            ],
54
            {
61
        },
55
                test: /\.css$/i,
62
        plugins: [
56
                type: "javascript/auto",
63
            new VueLoaderPlugin(),
57
                use: ["style-loader", "css-loader"],
64
            new rspack.DefinePlugin({
58
            },
65
                __VUE_OPTIONS_API__: true,
66
                __VUE_PROD_DEVTOOLS__: false,
67
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
68
            }),
59
        ],
69
        ],
70
        externals: {
71
            jquery: "jQuery",
72
            "datatables.net": "DataTable",
73
            "datatables.net-buttons": "DataTable",
74
            "datatables.net-buttons/js/buttons.html5": "DataTable",
75
            "datatables.net-buttons/js/buttons.print": "DataTable",
76
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
77
        },
60
    },
78
    },
61
    /**
79
    {
62
    optimization: {
80
        experiments: {
63
        splitChunks: {
81
            css: true,
64
            chunks: "all",
82
            outputModule: true,
65
            cacheGroups: {
83
        },
66
                default: false, // Disable default cache groups to avoid affecting existing bundles
84
        entry: {
67
                vendors: false, // Disable vendor caching
85
            islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts",
68
                vue: {
86
        },
69
                    test: /[\\/]node_modules[\\/]vue[\\/]/,
87
        output: {
70
                    name: "vue",
88
            filename: "[name].esm.js",
71
                    chunks: "all",
89
            path: path.resolve(
72
                    enforce: true,
90
                __dirname,
73
                },
91
                "koha-tmpl/intranet-tmpl/prog/js/vue/dist/"
92
            ),
93
            chunkFilename: "[name].[contenthash].esm.js",
94
            globalObject: "window",
95
            library: {
96
                type: "module",
74
            },
97
            },
75
        },
98
        },
99
        module: {
100
            rules: [
101
                {
102
                    test: /\.vue$/,
103
                    loader: "vue-loader",
104
                    options: {
105
                        experimentalInlineMatchResource: true,
106
                    },
107
                    exclude: [path.resolve(__dirname, "t/cypress/")],
108
                },
109
                {
110
                    test: /\.ts$/,
111
                    loader: "builtin:swc-loader",
112
                    options: {
113
                        jsc: {
114
                            parser: {
115
                                syntax: "typescript",
116
                            },
117
                        },
118
                        appendTsSuffixTo: [/\.vue$/],
119
                    },
120
                    exclude: [
121
                        /node_modules/,
122
                        path.resolve(__dirname, "t/cypress/"),
123
                    ],
124
                    type: "javascript/auto",
125
                },
126
                {
127
                    test: /\.css$/i,
128
                    type: "javascript/auto",
129
                    use: ["style-loader", "css-loader"],
130
                },
131
            ],
132
        },
133
        plugins: [
134
            new VueLoaderPlugin(),
135
            new rspack.DefinePlugin({
136
                __VUE_OPTIONS_API__: true,
137
                __VUE_PROD_DEVTOOLS__: false,
138
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
139
            }),
140
        ],
141
        externals: {
142
            jquery: "jQuery",
143
            "datatables.net": "DataTable",
144
            "datatables.net-buttons": "DataTable",
145
            "datatables.net-buttons/js/buttons.html5": "DataTable",
146
            "datatables.net-buttons/js/buttons.print": "DataTable",
147
            "datatables.net-buttons/js/buttons.colVis": "DataTable",
148
        },
76
    },
149
    },
77
    */
150
];
78
    plugins: [
79
        new VueLoaderPlugin(),
80
        new rspack.DefinePlugin({
81
            __VUE_OPTIONS_API__: true,
82
            __VUE_PROD_DEVTOOLS__: false,
83
            __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
84
        }),
85
    ],
86
    externals: {
87
        jquery: "jQuery",
88
        "datatables.net": "DataTable",
89
        "datatables.net-buttons": "DataTable",
90
        "datatables.net-buttons/js/buttons.html5": "DataTable",
91
        "datatables.net-buttons/js/buttons.print": "DataTable",
92
        "datatables.net-buttons/js/buttons.colVis": "DataTable",
93
    },
94
};
95
- 

Return to bug 37911