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

(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersFormAdd.vue (+520 lines)
Line 0 Link Here
1
<template>
2
    <router-link :to="{ name: 'CirculationTriggersList' }" class="close_modal">
3
        <i class="fa fa-fw fa-close"></i>
4
    </router-link>
5
    <div v-if="initialized" class="modal-content">
6
        <form @submit="addCircRule($event)">
7
            <div class="modal-header">
8
                <h1 v-if="!editMode">{{ $__("Add circulation trigger") }}</h1>
9
                <h1 v-else>{{ $__("Edit circulation trigger") }}</h1>
10
            </div>
11
            <div class="modal-body">
12
                <div class="page-section bg-info" v-if="circRules.length">
13
                    <h2>{{ $__("Trigger context") }}</h2>
14
                    <TriggerContext :ruleInfo="ruleInfo" />
15
                    <h2>{{ $__("Existing rules") }}</h2>
16
                    <p>{{ $__("Notice") }} {{ " " + newTriggerNumber - 1 }}</p>
17
                    <TriggersTable
18
                        :circRules="circRules"
19
                        :triggerNumber="newTriggerNumber - 1"
20
                        :modal="true"
21
                        :ruleBeingEdited="ruleBeingEdited"
22
                    />
23
                </div>
24
                <fieldset class="rows">
25
                    <ol>
26
                        <li>
27
                            <label for="library_id" class="required"
28
                                >{{ $__("Library") }}:</label
29
                            >
30
                            <v-select
31
                                id="library_id"
32
                                v-model="circRuleTrigger.library_id"
33
                                label="name"
34
                                :reduce="lib => lib.library_id"
35
                                :options="libraries"
36
                                @update:modelValue="handleContextChange($event)"
37
                                :disabled="editMode ? true : false"
38
                            >
39
                                <template #search="{ attributes, events }">
40
                                    <input
41
                                        :required="!circRuleTrigger.library_id"
42
                                        class="vs__search"
43
                                        v-bind="attributes"
44
                                        v-on="events"
45
                                    />
46
                                </template>
47
                            </v-select>
48
                            <span class="required">{{ $__("Required") }}</span>
49
                        </li>
50
                        <li>
51
                            <label for="patron_category_id" class="required"
52
                                >{{ $__("Patron category") }}:</label
53
                            >
54
                            <v-select
55
                                id="patron_category_id"
56
                                v-model="circRuleTrigger.patron_category_id"
57
                                label="name"
58
                                :reduce="cat => cat.patron_category_id"
59
                                :options="categories"
60
                                @update:modelValue="handleContextChange($event)"
61
                                :disabled="editMode ? true : false"
62
                            >
63
                                <template #search="{ attributes, events }">
64
                                    <input
65
                                        :required="
66
                                            !circRuleTrigger.patron_category_id
67
                                        "
68
                                        class="vs__search"
69
                                        v-bind="attributes"
70
                                        v-on="events"
71
                                    />
72
                                </template>
73
                            </v-select>
74
                            <span class="required">{{ $__("Required") }}</span>
75
                        </li>
76
                        <li>
77
                            <label for="item_type_id" class="required"
78
                                >{{ $__("Item type") }}:</label
79
                            >
80
                            <v-select
81
                                id="item_type_id"
82
                                v-model="circRuleTrigger.item_type_id"
83
                                label="description"
84
                                :reduce="type => type.item_type_id"
85
                                :options="itemTypes"
86
                                @update:modelValue="handleContextChange($event)"
87
                                :disabled="editMode ? true : false"
88
                            >
89
                                <template #search="{ attributes, events }">
90
                                    <input
91
                                        :required="
92
                                            !circRuleTrigger.item_type_id
93
                                        "
94
                                        class="vs__search"
95
                                        v-bind="attributes"
96
                                        v-on="events"
97
                                    />
98
                                </template>
99
                            </v-select>
100
                            <span class="required">{{ $__("Required") }}</span>
101
                        </li>
102
                        <li>
103
                            <label for="overdue_delay"
104
                                >{{ $__("Delay") }}:
105
                            </label>
106
                            <input
107
                                id="overdue_delay"
108
                                v-model="circRuleTrigger.delay"
109
                                type="number"
110
                            />
111
                        </li>
112
                        <li>
113
                            <label for="letter_code"
114
                                >{{ $__("Letter") }}:</label
115
                            >
116
                            <v-select
117
                                id="letter_code"
118
                                v-model="circRuleTrigger.notice"
119
                                label="name"
120
                                :reduce="type => type.code"
121
                                :options="letters"
122
                            >
123
                                <template #search="{ attributes, events }">
124
                                    <input
125
                                        class="vs__search"
126
                                        v-bind="attributes"
127
                                        v-on="events"
128
                                    />
129
                                </template>
130
                            </v-select>
131
                        </li>
132
                        <li>
133
                            <label for="mtt"
134
                                >{{ $__("Transport type(s)") }}:</label
135
                            >
136
                            <v-select
137
                                id="mtt"
138
                                v-model="circRuleTrigger.mtt"
139
                                label="name"
140
                                :reduce="type => type.code"
141
                                :options="mtts"
142
                                multiple
143
                            >
144
                                <template #search="{ attributes, events }">
145
                                    <input
146
                                        class="vs__search"
147
                                        v-bind="attributes"
148
                                        v-on="events"
149
                                    />
150
                                </template>
151
                            </v-select>
152
                        </li>
153
                        <li>
154
                            <label for="restricts"
155
                                >{{ $__("Restricts checkouts") }}:</label
156
                            >
157
                            <input
158
                                type="checkbox"
159
                                id="restricts"
160
                                :checked="false"
161
                                true-value="1"
162
                                false-value="0"
163
                                v-model="circRuleTrigger.restrict"
164
                            />
165
                        </li>
166
                    </ol>
167
                </fieldset>
168
            </div>
169
            <div class="modal-footer">
170
                <ButtonSubmit />
171
                <router-link
172
                    :to="{
173
                        name: 'CirculationTriggersList',
174
                    }"
175
                    >Cancel</router-link
176
                >
177
            </div>
178
        </form>
179
    </div>
180
    <div v-else>
181
        <p>{{ $__("Loading...") }}</p>
182
    </div>
183
</template>
184
185
<script>
186
import { APIClient } from "../../../fetch/api-client.js"
187
import TriggersTable from "./TriggersTable.vue"
188
import { inject } from "vue"
189
import { storeToRefs } from "pinia"
190
import ButtonSubmit from "../../ButtonSubmit.vue"
191
import TriggerContext from "./TriggerContext.vue"
192
193
export default {
194
    setup() {
195
        const circRulesStore = inject("circRulesStore")
196
        const { splitCircRulesByTriggerNumber } = circRulesStore
197
        const { letters } = storeToRefs(circRulesStore)
198
199
        return {
200
            splitCircRulesByTriggerNumber,
201
            letters,
202
        }
203
    },
204
    data() {
205
        return {
206
            initialized: false,
207
            libraries: null,
208
            categories: null,
209
            itemTypes: null,
210
            circRules: [],
211
            circRuleTrigger: {
212
                item_type_id: "*",
213
                library_id: "*",
214
                patron_category_id: "*",
215
                delay: null,
216
                notice: null,
217
                mtt: null,
218
                restrict: "0",
219
            },
220
            effectiveRule: {
221
                item_type_id: "*",
222
                library_id: "*",
223
                patron_category_id: "*",
224
                delay: null,
225
                notice: null,
226
                mtt: null,
227
                restrict: "0",
228
            },
229
            newTriggerNumber: 1,
230
            mtts: [
231
                { code: "email", name: "Email" },
232
                { code: "sms", name: "SMS" },
233
                { code: "print", name: "Print" },
234
            ],
235
            ruleInfo: {
236
                issuelength: null,
237
                decreaseloanholds: null,
238
                fine: null,
239
                chargeperiod: null,
240
                lengthunit: null,
241
            },
242
            editMode: false,
243
            ruleBeingEdited: null,
244
        }
245
    },
246
    beforeRouteEnter(to, from, next) {
247
        next(vm => {
248
            vm.getLibraries().then(() =>
249
                vm.getCategories().then(() =>
250
                    vm.getItemTypes().then(() => {
251
                        const { query } = to
252
                        vm.checkForExistingRules(query).then(
253
                            () => (vm.initialized = true)
254
                        )
255
                    })
256
                )
257
            )
258
        })
259
    },
260
    methods: {
261
        async addCircRule(e) {
262
            e.preventDefault()
263
264
            const context = {
265
                library_id: this.circRuleTrigger.library_id || "*",
266
                item_type_id: this.circRuleTrigger.item_type_id || "*",
267
                patron_category_id:
268
                    this.circRuleTrigger.patron_category_id || "*",
269
            }
270
271
            const delay =
272
                this.circRuleTrigger.delay === this.effectiveRule.delay
273
                    ? null
274
                    : this.circRuleTrigger.delay
275
            const notice =
276
                this.circRuleTrigger.notice === this.effectiveRule.notice
277
                    ? null
278
                    : this.circRuleTrigger.notice
279
            const restrict =
280
                this.circRuleTrigger.restrict === this.effectiveRule.restrict
281
                    ? null
282
                    : this.circRuleTrigger.restrict
283
            const mtt =
284
                this.circRuleTrigger.mtt.join(",") ===
285
                this.effectiveRule.mtt.join(",")
286
                    ? null
287
                    : this.circRuleTrigger.mtt.join(",")
288
289
            const circRule = {
290
                context,
291
            }
292
            circRule[`overdue_${this.newTriggerNumber}_delay`] = delay
293
            circRule[`overdue_${this.newTriggerNumber}_notice`] = notice
294
            circRule[`overdue_${this.newTriggerNumber}_restrict`] = restrict
295
            circRule[`overdue_${this.newTriggerNumber}_mtt`] = mtt
296
297
            if (this.editMode) {
298
                Object.keys(circRule).forEach(key => {
299
                    if (key === "context") return
300
                    if (!circRule[key]) delete circRule[key]
301
                })
302
            }
303
304
            const client = APIClient.circRule
305
            await client.circRules.update(circRule).then(
306
                () => {
307
                    this.$router
308
                        .push({ name: "CirculationTriggersList" })
309
                        .then(() => this.$router.go(0))
310
                },
311
                error => {}
312
            )
313
        },
314
        async getLibraries() {
315
            const client = APIClient.library
316
            await client.libraries.getAll().then(
317
                libraries => {
318
                    libraries.unshift({
319
                        library_id: "*",
320
                        name: "All libraries",
321
                    })
322
                    this.libraries = libraries
323
                },
324
                error => {}
325
            )
326
        },
327
        async getCategories() {
328
            const client = APIClient.patron
329
            await client.patronCategories.getAll().then(
330
                categories => {
331
                    categories.unshift({
332
                        patron_category_id: "*",
333
                        name: "All categories",
334
                    })
335
                    this.categories = categories
336
                },
337
                error => {}
338
            )
339
        },
340
        async getItemTypes() {
341
            const client = APIClient.item
342
            await client.itemTypes.getAll().then(
343
                types => {
344
                    types.unshift({
345
                        item_type_id: "*",
346
                        description: "All item types",
347
                    })
348
                    this.itemTypes = types
349
                },
350
                error => {}
351
            )
352
        },
353
        async handleContextChange() {
354
            await this.checkForExistingRules()
355
        },
356
        async checkForExistingRules(routeParams) {
357
            // We always pass library_id so we need to check for the existence of either item type or patron category
358
            const editMode = routeParams && routeParams.triggerNumber
359
            if (editMode) {
360
                this.editMode = editMode
361
                this.ruleBeingEdited = routeParams.triggerNumber
362
            }
363
            const library_id =
364
                routeParams && routeParams.library_id
365
                    ? routeParams.library_id
366
                    : this.circRuleTrigger.library_id || "*"
367
            const item_type_id =
368
                routeParams && routeParams.item_type_id
369
                    ? routeParams.item_type_id
370
                    : this.circRuleTrigger.item_type_id || "*"
371
            const patron_category_id =
372
                routeParams && routeParams.patron_category_id
373
                    ? routeParams.patron_category_id
374
                    : this.circRuleTrigger.patron_category_id || "*"
375
            const params = {
376
                library_id,
377
                item_type_id,
378
                patron_category_id,
379
            }
380
381
            const client = APIClient.circRule
382
            await client.circRules.getAll({}, params).then(
383
                rules => {
384
                    if (rules.length === 0) {
385
                        this.newTriggerNumber = 1
386
                    } else {
387
                        const { rulesPerTrigger } =
388
                            this.splitCircRulesByTriggerNumber(rules)
389
                        this.circRules = rulesPerTrigger
390
                        this.ruleInfo = {
391
                            issuelength: rules[0].issuelength,
392
                            decreaseloanholds: rules[0].decreaseloanholds,
393
                            fine: rules[0].fine,
394
                            chargeperiod: rules[0].chargeperiod,
395
                            lengthunit: rules[0].lengthunit,
396
                        }
397
                    }
398
                },
399
                error => {}
400
            )
401
402
            params.effective = false
403
            await client.circRules.getAll({}, params).then(
404
                rules => {
405
                    if (rules.length === 0) {
406
                        this.newTriggerNumber = 1
407
408
                        this.assignTriggerValues(
409
                            "circRuleTrigger",
410
                            this.circRules,
411
                            this.newTriggerNumber,
412
                            params
413
                        )
414
                        this.assignTriggerValues(
415
                            "effectiveRule",
416
                            this.circRules,
417
                            this.newTriggerNumber,
418
                            params
419
                        )
420
                    } else {
421
                        const regex = /overdue_(\d+)_delay/g
422
                        const numberOfTriggers = Object.keys(rules[0]).filter(
423
                            key => regex.test(key) && rules[0][key] !== null
424
                        ).length
425
                        this.newTriggerNumber = editMode
426
                            ? routeParams.triggerNumber
427
                            : numberOfTriggers + 1
428
                        const { rulesPerTrigger } =
429
                            this.splitCircRulesByTriggerNumber(rules)
430
                        const triggerToDisplay = editMode
431
                            ? routeParams.triggerNumber
432
                            : numberOfTriggers
433
                        this.assignTriggerValues(
434
                            "circRuleTrigger",
435
                            rulesPerTrigger,
436
                            triggerToDisplay
437
                        )
438
                        this.assignTriggerValues(
439
                            "effectiveRule",
440
                            rulesPerTrigger,
441
                            triggerToDisplay
442
                        )
443
                    }
444
                },
445
                error => {}
446
            )
447
        },
448
        assignTriggerValues(prop, rules, triggerNumber, context = null) {
449
            this[prop] = {
450
                item_type_id: context
451
                    ? context.item_type_id
452
                    : rules[triggerNumber - 1].context.item_type_id || "*",
453
                library_id: context
454
                    ? context.library_id
455
                    : rules[triggerNumber - 1].context.library_id || "*",
456
                patron_category_id: context
457
                    ? context.patron_category_id
458
                    : rules[triggerNumber - 1].context.patron_category_id ||
459
                      "*",
460
                delay: rules[triggerNumber - 1][
461
                    `overdue_${triggerNumber}_delay`
462
                ],
463
                notice: rules[triggerNumber - 1][
464
                    `overdue_${triggerNumber}_notice`
465
                ],
466
                mtt: rules[triggerNumber - 1][`overdue_${triggerNumber}_mtt`]
467
                    ? rules[triggerNumber - 1][
468
                          `overdue_${triggerNumber}_mtt`
469
                      ].split(",")
470
                    : [],
471
                restrict:
472
                    rules[triggerNumber - 1][
473
                        `overdue_${triggerNumber}_restrict`
474
                    ],
475
            }
476
        },
477
    },
478
    watch: {
479
        $route: {
480
            immediate: true,
481
            handler: function (newVal, oldVal) {
482
                if (
483
                    oldVal &&
484
                    oldVal.query.triggerNumber &&
485
                    newVal.query.triggerNumber !== oldVal.query.triggerNumber
486
                ) {
487
                    this.$router.go(0)
488
                }
489
            },
490
        },
491
    },
492
    components: { TriggersTable, ButtonSubmit, TriggerContext },
493
}
494
</script>
495
496
<style scoped>
497
.close_modal {
498
    position: absolute;
499
    top: 0.5rem;
500
    right: 0.5rem;
501
    font-size: 2rem;
502
}
503
504
form li {
505
    display: flex;
506
    align-items: center;
507
}
508
509
.dialog.alert
510
    fieldset:not(.bg-danger):not(.bg-warning):not(.bg-info):not(.bg-success):not(.bg-primary):not(.action),
511
.dialog.error
512
    fieldset:not(.bg-danger):not(.bg-warning):not(.bg-info):not(.bg-success):not(.bg-primary):not(.action) {
513
    margin: 0;
514
    background-color: rgba(255, 255, 255, 1);
515
}
516
517
.router-link-active {
518
    margin-left: 10px;
519
}
520
</style>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersList.vue (+258 lines)
Line 0 Link Here
1
<template>
2
    <Toolbar>
3
        <ToolbarButton
4
            :to="{
5
                name: 'CirculationTriggersFormAdd',
6
                query: { library_id: selectedLibrary },
7
            }"
8
            icon="plus"
9
            :title="$__('Add new trigger')"
10
        />
11
    </Toolbar>
12
    <div v-if="initialized">
13
        <h1>Circulation triggers</h1>
14
        <div class="page-section bg-info">
15
            <p>
16
                Rules are applied from most specific to less specific, using the
17
                first found in this order:
18
            </p>
19
            <ul>
20
                <li>same library, same patron category, same item type</li>
21
                <li>same library, same patron category, all item types</li>
22
                <li>same library, all patron categories, same item type</li>
23
                <li>same library, all patron categories, all item types</li>
24
                <li>
25
                    default (all libraries), same patron category, same item
26
                    type
27
                </li>
28
                <li>
29
                    default (all libraries), same patron category, all item
30
                    types
31
                </li>
32
                <li>
33
                    default (all libraries), all patron categories, same item
34
                    type
35
                </li>
36
                <li>
37
                    default (all libraries), all patron categories, all item
38
                    types
39
                </li>
40
            </ul>
41
        </div>
42
        <div class="page-section" v-if="initialized">
43
            <label for="library_select">{{ $__("Select a library") }}:</label>
44
            <v-select
45
                id="library_select"
46
                v-model="selectedLibrary"
47
                label="name"
48
                :reduce="lib => lib.library_id"
49
                :options="libraries"
50
                @update:modelValue="handleLibrarySelection($event)"
51
            >
52
                <template #search="{ attributes, events }">
53
                    <input
54
                        :required="!selectedLibrary"
55
                        class="vs__search"
56
                        v-bind="attributes"
57
                        v-on="events"
58
                    />
59
                </template>
60
            </v-select>
61
        </div>
62
    </div>
63
    <div v-if="initialized">
64
        <div id="circ_triggers_tabs" class="toptabs numbered">
65
            <ul class="nav nav-tabs" role="tablist">
66
                <li
67
                    v-for="(number, i) in numberOfTabs"
68
                    role="presentation"
69
                    v-bind:class="
70
                        tabSelected === `Notice ${number}` ? 'active' : ''
71
                    "
72
                    :key="`noticeTab${i}`"
73
                >
74
                    <a
75
                        href="#"
76
                        role="tab"
77
                        @click="changeTabContent"
78
                        :data-content="`Notice ${number}`"
79
                        >{{ $__("Trigger") + " " + number }}</a
80
                    >
81
                </li>
82
            </ul>
83
        </div>
84
        <div class="tab_content">
85
            <template v-for="(number, i) in numberOfTabs">
86
                <div
87
                    v-if="tabSelected === `Notice ${number}`"
88
                    :key="`noticeTabContent${i}`"
89
                >
90
                    <TriggersTable
91
                        :circRules="circRules"
92
                        :triggerNumber="number"
93
                        :categories="categories"
94
                        :itemTypes="itemTypes"
95
                    />
96
                </div>
97
            </template>
98
        </div>
99
    </div>
100
    <div v-if="showModal" class="modal_centered">
101
        <div
102
            class="modal-dialog modal-dialog-centered modal-lg"
103
            role="document"
104
        >
105
            <router-view></router-view>
106
        </div>
107
    </div>
108
</template>
109
110
<script>
111
import Toolbar from "../../Toolbar.vue"
112
import ToolbarButton from "../../ToolbarButton.vue"
113
import { APIClient } from "../../../fetch/api-client.js"
114
import TriggersTable from "./TriggersTable.vue"
115
import { inject } from "vue"
116
117
export default {
118
    setup() {
119
        const { splitCircRulesByTriggerNumber } = inject("circRulesStore")
120
121
        return {
122
            splitCircRulesByTriggerNumber,
123
        }
124
    },
125
    data() {
126
        return {
127
            initialized: false,
128
            libraries: null,
129
            selectedLibrary: "*",
130
            circRules: null,
131
            numberOfTabs: [1],
132
            tabSelected: "Notice 1",
133
            showModal: false,
134
        }
135
    },
136
    beforeRouteEnter(to, from, next) {
137
        next(vm => {
138
            vm.getLibraries().then(() =>
139
                vm
140
                    .getCategories()
141
                    .then(() =>
142
                        vm
143
                            .getItemTypes()
144
                            .then(() =>
145
                                vm
146
                                    .getCircRules({}, true)
147
                                    .then(() => (vm.initialized = true))
148
                            )
149
                    )
150
            )
151
        })
152
    },
153
    methods: {
154
        async getLibraries() {
155
            const libClient = APIClient.library
156
            await libClient.libraries.getAll().then(
157
                libraries => {
158
                    libraries.unshift({
159
                        library_id: "*",
160
                        name: "All libraries",
161
                    })
162
                    this.libraries = libraries
163
                },
164
                error => {}
165
            )
166
        },
167
        async getCategories() {
168
            const client = APIClient.patron
169
            await client.patronCategories.getAll().then(
170
                categories => {
171
                    categories.unshift({
172
                        patron_category_id: "*",
173
                        name: "All",
174
                    })
175
                    this.categories = categories
176
                },
177
                error => {}
178
            )
179
        },
180
        async getItemTypes() {
181
            const client = APIClient.item
182
            await client.itemTypes.getAll().then(
183
                types => {
184
                    types.unshift({
185
                        item_type_id: "*",
186
                        description: "All",
187
                    })
188
                    this.itemTypes = types
189
                },
190
                error => {}
191
            )
192
        },
193
        async getCircRules(params = {}, pageLoad) {
194
            params.effective = false
195
            if (pageLoad) {
196
                params.library_id = "*"
197
            }
198
            const client = APIClient.circRule
199
            await client.circRules.getAll({}, params).then(
200
                rules => {
201
                    const { numberOfTabs, rulesPerTrigger: circRules } =
202
                        this.splitCircRulesByTriggerNumber(rules)
203
                    this.numberOfTabs = numberOfTabs
204
                    this.circRules = circRules
205
                },
206
                error => {}
207
            )
208
        },
209
        async handleLibrarySelection(e) {
210
            if (!e) e = ""
211
            await this.getCircRules({ library_id: e })
212
        },
213
        changeTabContent(e) {
214
            this.tabSelected = e.target.getAttribute("data-content")
215
        },
216
    },
217
    watch: {
218
        $route: {
219
            immediate: true,
220
            handler: function (newVal, oldVal) {
221
                this.showModal = newVal.meta && newVal.meta.showModal
222
            },
223
        },
224
    },
225
    components: { TriggersTable, Toolbar, ToolbarButton },
226
}
227
</script>
228
229
<style scoped>
230
.v-select {
231
    display: inline-block;
232
    background-color: white;
233
    width: 30%;
234
    margin-left: 10px;
235
}
236
.active {
237
    cursor: pointer;
238
}
239
.toptabs {
240
    margin-bottom: 0;
241
}
242
243
.modal_centered {
244
    position: fixed;
245
    z-index: 9998;
246
    display: table;
247
    transition: opacity 0.3s ease;
248
    left: 0px;
249
    top: 0px;
250
    width: 100%;
251
    height: 100%;
252
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
253
}
254
.modal-dialog {
255
    overflow: auto;
256
    height: 90%;
257
}
258
</style>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/TriggerContext.vue (+50 lines)
Line 0 Link Here
1
<template>
2
    <div class="page-section">
3
        <table>
4
            <thead>
5
                <th>
6
                    {{ $__("Loan period") }}
7
                </th>
8
                <th>
9
                    {{ $__("Unit") }}
10
                </th>
11
                <th>
12
                    {{ $__("Decreased loan period for high holds") }}
13
                </th>
14
                <th>
15
                    {{ $__("Fine amount") }}
16
                </th>
17
                <th>
18
                    {{ $__("Fine charging interval") }}
19
                </th>
20
            </thead>
21
            <tbody>
22
                <tr>
23
                    <td>
24
                        {{ ruleInfo.issuelength }}
25
                    </td>
26
                    <td>
27
                        {{ ruleInfo.lengthunit }}
28
                    </td>
29
                    <td>
30
                        {{ ruleInfo.decreaseloanholds }}
31
                    </td>
32
                    <td>
33
                        {{ ruleInfo.fine }}
34
                    </td>
35
                    <td>
36
                        {{ ruleInfo.chargeperiod }}
37
                    </td>
38
                </tr>
39
            </tbody>
40
        </table>
41
    </div>
42
</template>
43
44
<script>
45
export default {
46
    props: ["ruleInfo"],
47
}
48
</script>
49
50
<style></style>
(-)a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/TriggersTable.vue (-1 / +266 lines)
Line 0 Link Here
0
- 
1
<template>
2
    <div class="page-section">
3
        <table>
4
            <thead>
5
                <th v-if="!modal">
6
                    {{ $__("Patron category") }}
7
                </th>
8
                <th v-if="!modal">
9
                    {{ $__("Item type") }}
10
                </th>
11
                <th v-if="modal">
12
                    {{ $__("Notice") }}
13
                </th>
14
                <th>
15
                    {{ $__("Delay") }}
16
                </th>
17
                <th>
18
                    {{ $__("Notice") }}
19
                </th>
20
                <th>
21
                    {{ $__("Email") }}
22
                </th>
23
                <th>
24
                    {{ $__("Print") }}
25
                </th>
26
                <th>
27
                    {{ $__("SMS") }}
28
                </th>
29
                <th>
30
                    {{ $__("Restricts checkouts") }}
31
                </th>
32
                <th v-if="!modal">
33
                    {{ $__("Actions") }}
34
                </th>
35
            </thead>
36
            <tbody>
37
                <tr
38
                    v-for="(rule, i) in filterCircRulesByTabNumber(
39
                        triggerNumber
40
                    )"
41
                    v-bind:key="'rule' + i"
42
                >
43
                    <td
44
                        v-if="!modal"
45
                        :class="
46
                            modal && i + 1 === parseInt(ruleBeingEdited)
47
                                ? 'selected_rule'
48
                                : ''
49
                        "
50
                    >
51
                        {{
52
                            handleContext(
53
                                rule.context.patron_category_id,
54
                                categories,
55
                                "patron_category_id"
56
                            )
57
                        }}
58
                    </td>
59
                    <td
60
                        v-if="!modal"
61
                        :class="
62
                            modal && i + 1 === parseInt(ruleBeingEdited)
63
                                ? 'selected_rule'
64
                                : ''
65
                        "
66
                    >
67
                        {{
68
                            handleContext(
69
                                rule.context.item_type_id,
70
                                itemTypes,
71
                                "item_type_id",
72
                                "description"
73
                            )
74
                        }}
75
                    </td>
76
                    <td
77
                        v-if="modal"
78
                        :class="
79
                            modal && i + 1 === parseInt(ruleBeingEdited)
80
                                ? 'selected_rule'
81
                                : ''
82
                        "
83
                    >
84
                        {{ i + 1 }}
85
                    </td>
86
                    <td
87
                        :class="
88
                            modal && i + 1 === parseInt(ruleBeingEdited)
89
                                ? 'selected_rule'
90
                                : ''
91
                        "
92
                    >
93
                        {{
94
                            rule[
95
                                "overdue_" +
96
                                    (modal ? i + 1 : triggerNumber) +
97
                                    "_delay"
98
                            ]
99
                                ? rule[
100
                                      "overdue_" +
101
                                          (modal ? i + 1 : triggerNumber) +
102
                                          "_delay"
103
                                  ] +
104
                                  " " +
105
                                  $__("days")
106
                                : 0 + " " + $__("days")
107
                        }}
108
                    </td>
109
                    <td
110
                        :class="
111
                            modal && i + 1 === parseInt(ruleBeingEdited)
112
                                ? 'selected_rule'
113
                                : ''
114
                        "
115
                    >
116
                        {{
117
                            rule[
118
                                "overdue_" +
119
                                    (modal ? i + 1 : triggerNumber) +
120
                                    "_notice"
121
                            ]
122
                        }}
123
                    </td>
124
                    <td
125
                        :class="
126
                            modal && i + 1 === parseInt(ruleBeingEdited)
127
                                ? 'selected_rule'
128
                                : ''
129
                        "
130
                    >
131
                        {{
132
                            handleTransport(
133
                                rule[
134
                                    "overdue_" +
135
                                        (modal ? i + 1 : triggerNumber) +
136
                                        "_mtt"
137
                                ],
138
                                "email"
139
                            )
140
                        }}
141
                    </td>
142
                    <td
143
                        :class="
144
                            modal && i + 1 === parseInt(ruleBeingEdited)
145
                                ? 'selected_rule'
146
                                : ''
147
                        "
148
                    >
149
                        {{
150
                            handleTransport(
151
                                rule[
152
                                    "overdue_" +
153
                                        (modal ? i + 1 : triggerNumber) +
154
                                        "_mtt"
155
                                ],
156
                                "print"
157
                            )
158
                        }}
159
                    </td>
160
                    <td
161
                        :class="
162
                            modal && i + 1 === parseInt(ruleBeingEdited)
163
                                ? 'selected_rule'
164
                                : ''
165
                        "
166
                    >
167
                        {{
168
                            handleTransport(
169
                                rule[
170
                                    "overdue_" +
171
                                        (modal ? i + 1 : triggerNumber) +
172
                                        "_mtt"
173
                                ],
174
                                "sms"
175
                            )
176
                        }}
177
                    </td>
178
                    <td
179
                        :class="
180
                            modal && i + 1 === parseInt(ruleBeingEdited)
181
                                ? 'selected_rule'
182
                                : ''
183
                        "
184
                    >
185
                        {{
186
                            handleRestrictions(
187
                                rule[
188
                                    "overdue_" +
189
                                        (modal ? i + 1 : triggerNumber) +
190
                                        "_restrict"
191
                                ]
192
                            )
193
                        }}
194
                    </td>
195
                    <td v-if="!modal" class="actions">
196
                        <router-link
197
                            :to="{
198
                                name: 'CirculationTriggersFormEdit',
199
                                query: {
200
                                    library_id: rule.context.library_id,
201
                                    item_type_id: rule.context.item_type_id,
202
                                    patron_category_id:
203
                                        rule.context.patron_category_id,
204
                                    triggerNumber,
205
                                },
206
                            }"
207
                            class="btn btn-default btn-xs"
208
                            ><i class="fa-solid fa-pencil"></i>
209
                            Edit</router-link
210
                        >
211
                    </td>
212
                </tr>
213
            </tbody>
214
        </table>
215
    </div>
216
</template>
217
218
<script>
219
export default {
220
    props: [
221
        "circRules",
222
        "triggerNumber",
223
        "modal",
224
        "ruleBeingEdited",
225
        "categories",
226
        "itemTypes",
227
    ],
228
    methods: {
229
        handleContext(value, data, type, displayProperty = "name") {
230
            const item = data.find(item => item[type] === value)
231
            return item[displayProperty]
232
        },
233
        handleTransport(value, type) {
234
            return value
235
                ? value.includes(type)
236
                    ? this.$__("Yes")
237
                    : this.$__("No")
238
                : this.$__("Default")
239
        },
240
        handleRestrictions(value) {
241
            return value === "1" ? this.$__("Yes") : this.$__("No")
242
        },
243
        filterCircRulesByTabNumber(number) {
244
            if (this.modal) return this.circRules
245
            return this.circRules.filter(
246
                rule =>
247
                    rule.triggerNumber === number &&
248
                    (rule[`overdue_${number}_delay`] ||
249
                        rule[`overdue_${number}_notice`] ||
250
                        rule[`overdue_${number}_mtt`] ||
251
                        rule[`overdue_${number}_restrict`])
252
            )
253
        },
254
    },
255
}
256
</script>
257
258
<style scoped>
259
.selected_rule {
260
    background-color: yellow !important;
261
}
262
263
.actions a {
264
    margin-right: 5px;
265
}
266
</style>

Return to bug 10190