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

(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementLicenses.vue (-14 / +8 lines)
Lines 19-40 Link Here
19
                    <label :for="`license_id_${counter}`" class="required"
19
                    <label :for="`license_id_${counter}`" class="required"
20
                        >{{ $__("License") }}:</label
20
                        >{{ $__("License") }}:</label
21
                    >
21
                    >
22
                    <v-select
22
                    <InfiniteScrollSelect
23
                        :id="`license_id_${counter}`"
23
                        :id="`license_id_${counter}`"
24
                        v-model="agreement_license.license_id"
24
                        v-model="agreement_license.license_id"
25
                        label="name"
25
                        dataType="licenses"
26
                        :reduce="l => l.license_id"
26
                        :required="true"
27
                        :options="licenses"
27
                    />
28
                    >
29
                        <template #search="{ attributes, events }">
30
                            <input
31
                                :required="!agreement_license.license_id"
32
                                class="vs__search"
33
                                v-bind="attributes"
34
                                v-on="events"
35
                            />
36
                        </template>
37
                    </v-select>
38
                    <span class="required">{{ $__("Required") }}</span>
28
                    <span class="required">{{ $__("Required") }}</span>
39
                </li>
29
                </li>
40
                <li>
30
                <li>
Lines 102-107 Link Here
102
92
103
<script>
93
<script>
104
import { APIClient } from "../../fetch/api-client.js"
94
import { APIClient } from "../../fetch/api-client.js"
95
import InfiniteScrollSelect from "../InfiniteScrollSelect.vue"
105
96
106
export default {
97
export default {
107
    name: "AgreementLicenses",
98
    name: "AgreementLicenses",
Lines 139-143 export default { Link Here
139
            this.agreement_licenses.splice(counter, 1)
130
            this.agreement_licenses.splice(counter, 1)
140
        },
131
        },
141
    },
132
    },
133
    components: {
134
        InfiniteScrollSelect,
135
    },
142
}
136
}
143
</script>
137
</script>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/InfiniteScrollSelect.vue (-1 / +167 lines)
Line 0 Link Here
0
- 
1
<template>
2
    <v-select
3
        v-bind:id="id"
4
        v-model="model"
5
        :label="queryProperty"
6
        :options="search ? data : paginated"
7
        :reduce="item => item[dataIdentifier]"
8
        @open="onOpen"
9
        @close="onClose"
10
        @search="searchFilter($event)"
11
    >
12
        <template #list-footer>
13
            <li v-show="hasNextPage && !this.search" ref="load">
14
                {{ $__("Loading more options...") }}
15
            </li>
16
        </template>
17
    </v-select>
18
</template>
19
20
<script>
21
import { APIClient } from "../fetch/api-client.js"
22
23
export default {
24
    created() {
25
        this.fetchInitialData(this.dataType)
26
        switch (this.dataType) {
27
            case "vendors":
28
                this.dataIdentifier = "id"
29
                this.queryProperty = "name"
30
                break
31
            case "agreements":
32
                this.dataIdentifier = "agreement_id"
33
                this.queryProperty = "name"
34
                break
35
            case "licenses":
36
                this.dataIdentifier = "license_id"
37
                this.queryProperty = "name"
38
                break
39
            case "localPackages":
40
                this.dataIdentifier = "package_id"
41
                this.queryProperty = "name"
42
                break
43
            default:
44
                break
45
        }
46
    },
47
    props: {
48
        id: String,
49
        dataType: String,
50
        modelValue: Number,
51
        required: Boolean,
52
    },
53
    emits: ["update:modelValue"],
54
    data() {
55
        return {
56
            observer: null,
57
            dataIdentifier: null,
58
            queryProperty: null,
59
            limit: null,
60
            search: "",
61
            scrollPage: null,
62
            data: [],
63
        }
64
    },
65
    computed: {
66
        model: {
67
            get() {
68
                return this.modelValue
69
            },
70
            set(value) {
71
                this.$emit("update:modelValue", value)
72
            },
73
        },
74
        filtered() {
75
            return this.data.filter(item =>
76
                item[this.queryProperty].includes(this.search)
77
            )
78
        },
79
        paginated() {
80
            return this.filtered.slice(0, this.limit)
81
        },
82
        hasNextPage() {
83
            return this.paginated.length < this.filtered.length
84
        },
85
    },
86
    mounted() {
87
        this.observer = new IntersectionObserver(this.infiniteScroll)
88
    },
89
    methods: {
90
        async fetchInitialData(dataType) {
91
            const client = APIClient.erm
92
            await client[dataType]
93
                .getAll("_page=1&_per_page=20&_match=contains")
94
                .then(
95
                    items => {
96
                        this.data = items
97
                        this.search = ""
98
                        this.limit = 19
99
                        this.scrollPage = 1
100
                    },
101
                    error => {}
102
                )
103
        },
104
        async searchFilter(e) {
105
            if (e) {
106
                this.observer.disconnect()
107
                this.data = []
108
                this.search = e
109
                const client = APIClient.erm
110
                await client[this.dataType]
111
                    .getAll(
112
                        `q={"me.${this.queryProperty}":{"like":"%${e}%"}}&_per_page=-1`
113
                    )
114
                    .then(
115
                        items => {
116
                            this.data = items
117
                        },
118
                        error => {}
119
                    )
120
            } else {
121
                await this.fetchInitialData(this.dataType)
122
                await this.resetSelect()
123
            }
124
        },
125
        async onOpen() {
126
            await this.fetchInitialData(this.dataType)
127
            if (this.hasNextPage) {
128
                await this.$nextTick()
129
                this.observer.observe(this.$refs.load)
130
            }
131
        },
132
        onClose() {
133
            this.observer.disconnect()
134
            this.search = ""
135
        },
136
        async infiniteScroll([{ isIntersecting, target }]) {
137
            if (isIntersecting) {
138
                const ul = target.offsetParent
139
                const scrollTop = target.offsetParent.scrollTop
140
                this.limit += 20
141
                this.scrollPage++
142
                await this.$nextTick()
143
                const client = APIClient.erm
144
                await client[this.dataType]
145
                    .getAll(
146
                        `_page=${this.scrollPage}&_per_page=20&_match=contains`
147
                    )
148
                    .then(
149
                        items => {
150
                            const existingData = [...this.data]
151
                            this.data = [...existingData, ...items]
152
                        },
153
                        error => {}
154
                    )
155
                ul.scrollTop = scrollTop
156
            }
157
        },
158
        async resetSelect() {
159
            if (this.hasNextPage) {
160
                await this.$nextTick()
161
                this.observer.observe(this.$refs.load)
162
            }
163
        },
164
    },
165
    name: "InfiniteScrollSelect",
166
}
167
</script>

Return to bug 32474