Bug 30708: Do not allow adding new items to a closed train
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / Preservation / TrainsList.vue
1 <template>
2     <div v-if="!initialized">{{ $__("Loading") }}</div>
3     <div v-else id="trains_list">
4         <Toolbar />
5         <fieldset v-if="count_trains > 0" class="filters">
6             <label>{{ $__("Filter by") }}:</label>
7             <input
8                 type="radio"
9                 id="all_status_filter"
10                 v-model="filters.status"
11                 value=""
12             /><label for="all_status_filter">{{ $__("All") }}</label>
13             <input
14                 type="radio"
15                 id="closed_status_filter"
16                 v-model="filters.status"
17                 value="closed"
18             /><label for="closed_status_filter">{{ $__("Closed") }}</label>
19             <input
20                 type="radio"
21                 id="sent_status_filter"
22                 v-model="filters.status"
23                 value="sent"
24             /><label for="sent_status_filter">{{ $__("Sent") }}</label>
25             <input
26                 type="radio"
27                 id="received_status_filter"
28                 v-model="filters.status"
29                 value="received"
30             /><label for="received_status_filter">{{ $__("Received") }}</label>
31             <input
32                 @click="filter_table"
33                 id="filter_table"
34                 type="button"
35                 :value="$__('Filter')"
36             />
37         </fieldset>
38         <div v-if="count_trains > 0" class="page-section">
39             <KohaTable
40                 ref="table"
41                 v-bind="tableOptions"
42                 @show="doShow"
43                 @edit="doEdit"
44                 @delete="doDelete"
45                 @addItems="doAddItems"
46             ></KohaTable>
47         </div>
48
49         <div v-else class="dialog message">
50             {{ $__("There are no trains defined") }}
51         </div>
52     </div>
53 </template>
54
55 <script>
56 import flatPickr from "vue-flatpickr-component"
57 import Toolbar from "./TrainsToolbar.vue"
58 import { inject, ref, reactive } from "vue"
59 import { APIClient } from "../../fetch/api-client"
60 import { build_url } from "../../composables/datatables"
61 import KohaTable from "../KohaTable.vue"
62
63 export default {
64     setup() {
65         const AVStore = inject("AVStore")
66         const { get_lib_from_av, map_av_dt_filter } = AVStore
67         const { setConfirmationDialog, setMessage, setWarning } =
68             inject("mainStore")
69         const table = ref()
70         const filters = reactive({ status: "" })
71         return {
72             get_lib_from_av,
73             map_av_dt_filter,
74             setConfirmationDialog,
75             setMessage,
76             setWarning,
77             table,
78             filters,
79         }
80     },
81     data: function () {
82         this.filters.status = this.$route.query.status || ""
83         return {
84             fp_config: flatpickr_defaults,
85             count_trains: 0,
86             initialized: false,
87             tableOptions: {
88                 columns: this.getTableColumns(),
89                 url: this.table_url,
90                 add_filters: true,
91                 actions: {
92                     0: ["show"],
93                     "-1": [
94                         "edit",
95                         "delete",
96                         {
97                             addItems: {
98                                 text: this.$__("Add items"),
99                                 icon: "fa fa-plus",
100                             },
101                         },
102                     ],
103                 },
104             },
105         }
106     },
107     beforeRouteEnter(to, from, next) {
108         next(vm => {
109             vm.getCountTrains()
110         })
111     },
112     computed: {},
113     methods: {
114         async getCountTrains() {
115             const client = APIClient.preservation
116             client.trains.count().then(
117                 count => {
118                     this.count_trains = count
119                     this.initialized = true
120                 },
121                 error => {}
122             )
123         },
124         doShow: function (train, dt, event) {
125             event.preventDefault()
126             this.$router.push(
127                 "/cgi-bin/koha/preservation/trains/" + train.train_id
128             )
129         },
130         doEdit: function (train, dt, event) {
131             this.$router.push(
132                 "/cgi-bin/koha/preservation/trains/edit/" + train.train_id
133             )
134         },
135         doDelete: function (train, dt, event) {
136             this.setConfirmationDialog(
137                 {
138                     title: this.$__(
139                         "Are you sure you want to remove this train?"
140                     ),
141                     message: train.name,
142                     accept_label: this.$__("Yes, delete"),
143                     cancel_label: this.$__("No, do not delete"),
144                 },
145                 () => {
146                     const client = APIClient.preservation
147                     client.trains.delete(train.train_id).then(
148                         success => {
149                             this.setMessage(
150                                 this.$__("Train %s deleted").format(train.name),
151                                 true
152                             )
153                             dt.draw()
154                         },
155                         error => {}
156                     )
157                 }
158             )
159         },
160         doAddItems: function (train, dt, event) {
161             if (train.closed_on != null) {
162                 this.setWarning(this.$__("Cannot add items to a closed train"))
163             } else {
164                 this.$router.push(
165                     "/cgi-bin/koha/preservation/trains/" +
166                         train.train_id +
167                         "/items/add"
168                 )
169             }
170         },
171         table_url() {
172             let url = "/api/v1/preservation/trains"
173             let q
174             if (this.filters.status == "closed") {
175                 q = {
176                     "me.closed_on": { "!=": null },
177                     "me.sent_on": null,
178                     "me.received_on": null,
179                 }
180             } else if (this.filters.status == "sent") {
181                 q = {
182                     "me.closed_on": { "!=": null },
183                     "me.sent_on": { "!=": null },
184                     "me.received_on": null,
185                 }
186             } else if (this.filters.status == "received") {
187                 q = {
188                     "me.closed_on": { "!=": null },
189                     "me.sent_on": { "!=": null },
190                     "me.received_on": { "!=": null },
191                 }
192             }
193             if (q) {
194                 url += "?" + new URLSearchParams({ q: JSON.stringify(q) })
195             }
196
197             return url
198         },
199         filter_table: async function () {
200             let new_route = build_url(
201                 "/cgi-bin/koha/preservation/trains",
202                 this.filters
203             )
204             this.$router.push(new_route)
205             if (this.$refs.table) {
206                 this.$refs.table.redraw(this.table_url())
207             }
208         },
209         getTableColumns: function () {
210             let escape_str = this.escape_str
211             return [
212                 {
213                     title: __("Name"),
214                     data: "me.train_id:me.name",
215                     searchable: true,
216                     orderable: true,
217                     render: function (data, type, row, meta) {
218                         return `<a href="/cgi-bin/koha/preservation/trains/${row.train_id}" class="show">${row.name} (#${row.train_id})</a>`
219                     },
220                 },
221                 {
222                     title: __("Created on"),
223                     data: "created_on",
224                     searchable: true,
225                     orderable: true,
226                     render: function (data, type, row, meta) {
227                         return $date(row.created_on)
228                     },
229                 },
230                 {
231                     title: __("Closed on"),
232                     data: "closed_on",
233                     searchable: true,
234                     orderable: true,
235                     render: function (data, type, row, meta) {
236                         return $date(row.closed_on)
237                     },
238                 },
239                 {
240                     title: __("Sent on"),
241                     data: "sent_on",
242                     searchable: true,
243                     orderable: true,
244                     render: function (data, type, row, meta) {
245                         return $date(row.sent_on)
246                     },
247                 },
248                 {
249                     title: __("Received on"),
250                     data: "received_on",
251                     searchable: true,
252                     orderable: true,
253                     render: function (data, type, row, meta) {
254                         return $date(row.received_on)
255                     },
256                 },
257             ]
258         },
259     },
260     components: { flatPickr, Toolbar, KohaTable },
261     name: "trainsList",
262     emits: ["select-train", "close"],
263 }
264 </script>
265
266 <style scoped>
267 #train_list {
268     display: table;
269 }
270 .filters > input[type="radio"] {
271     min-width: 0 !important;
272 }
273 .filters > input[type="button"] {
274     margin-left: 1rem;
275 }
276 </style>