Bug 33483: Make KohaTable accept customizable actions button
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / KohaTable.vue
1 <template>
2     <DataTable
3         :columns="tableColumns"
4         :options="{ ...dataTablesDefaults, ...allOptions }"
5         :data="data"
6         ref="table"
7     >
8         <slot></slot>
9     </DataTable>
10 </template>
11
12 <script>
13 import DataTable from "datatables.net-vue3"
14 import DataTablesLib from "datatables.net"
15 import "datatables.net-buttons"
16 import "datatables.net-buttons/js/buttons.html5"
17 import "datatables.net-buttons/js/buttons.print"
18 import "datatables.net-buttons/js/buttons.colVis"
19 DataTable.use(DataTablesLib)
20
21 export default {
22     name: "KohaTable",
23     data() {
24         let hidden_ids, included_ids
25         ;[hidden_ids, included_ids] = _dt_visibility(
26             this.table_settings,
27             this.options
28         )
29         let buttons = _dt_buttons({
30             included_ids,
31             table_settings: this.table_settings,
32         })
33         return {
34             data: [],
35             tableColumns: this.columns,
36             allOptions: {
37                 deferRender: true,
38                 paging: true,
39                 serverSide: true,
40                 searching: true,
41                 pagingType: "full_numbers",
42                 processing: true,
43                 autoWidth: false,
44                 ajax: {
45                     url: typeof this.url === "function" ? this.url() : this.url,
46                     ..._dt_default_ajax({
47                         options: this.options,
48                         default_filters: this.default_filters,
49                     }),
50                 },
51                 buttons,
52                 search: { search: this.$route.query.q },
53                 columnDefs: [
54                     {
55                         targets: "_all",
56                         render: function (data, type, row, meta) {
57                             if (type == "display") {
58                                 return escape_str(data)
59                             }
60                             return data
61                         },
62                     },
63                 ],
64                 ...this.options,
65             },
66             hidden_ids,
67             included_ids,
68         }
69     },
70     setup() {
71         return { dataTablesDefaults }
72     },
73     methods: {
74         redraw: function (url) {
75             this.$refs.table.dt().ajax.url(url).draw()
76         },
77     },
78     beforeMount() {
79         if (this.actions.hasOwnProperty("-1")) {
80             this.tableColumns = [
81                 ...this.tableColumns,
82                 {
83                     name: "actions",
84                     title: this.$__("Actions"),
85                     searchable: false,
86                     render: (data, type, row) => {
87                         let content = []
88                         this.actions["-1"].forEach(action => {
89                             if (typeof action === "object") {
90                                 let action_name = Object.keys(action)[0]
91                                 content.push(
92                                     `<a class="${action_name} btn btn-default btn-xs" role="button"><i class="${action[action_name].icon}"></i>${action[action_name].text}</a>`
93                                 )
94                             } else if (action == "edit") {
95                                 content.push(
96                                     '<a class="edit btn btn-default btn-xs" role="button"><i class="fa fa-pencil"></i>' +
97                                         this.$__("Edit") +
98                                         "</a>"
99                                 )
100                             } else if (action == "delete") {
101                                 content.push(
102                                     '<a class="delete btn btn-default btn-xs" role="button"><i class="fa fa-trash"></i>' +
103                                         this.$__("Delete") +
104                                         "</a>"
105                                 )
106                             }
107                         })
108                         return content.join(" ")
109                     },
110                 },
111             ]
112         }
113
114         $(
115             ".dt_button_clear_filter, .columns_controls, .export_controls, .dt_button_configure_table"
116         ).tooltip()
117
118         if (this.add_filters) {
119             this.options.orderCellsTop = true
120         }
121
122         if (this.table_settings) {
123             if (
124                 this.table_settings.hasOwnProperty("default_display_length") &&
125                 this.table_settings.default_display_length != null
126             ) {
127                 this.options.pageLength =
128                     this.table_settings.default_display_length
129             }
130             if (
131                 this.table_settings.hasOwnProperty("default_sort_order") &&
132                 this.table_settings.default_sort_order != null
133             ) {
134                 this.options.order = [
135                     [this.table_settings.default_sort_order, "asc"],
136                 ]
137             }
138         }
139     },
140     mounted() {
141         let dt = this.$refs.table.dt()
142         let table_node = dt.table().node()
143         let add_filters = this.add_filters
144         if (add_filters) {
145             _dt_add_filters(table_node, dt, this.filters_options)
146         }
147
148         dt.on("column-visibility.dt", function () {
149             _dt_on_visibility(add_filters, table_node, dt)
150         })
151             .columns(this.hidden_ids)
152             .visible(false)
153
154         if (Object.keys(this.actions).length) {
155             const self = this
156             dt.on("draw", () => {
157                 const dataSet = dt.rows().data()
158                 Object.entries(this.actions).forEach(([col_id, actions]) => {
159                     dt.column(col_id)
160                         .nodes()
161                         .to$()
162                         .each(function (idx) {
163                             const data = dataSet[idx]
164                             actions.forEach(action => {
165                                 let action_name =
166                                     typeof action === "object"
167                                         ? Object.keys(action)[0]
168                                         : action
169                                 $("." + action_name, this).on("click", e => {
170                                     self.$emit(action_name, data, dt, e)
171                                 })
172                             })
173                         })
174                 })
175             })
176         }
177     },
178     beforeUnmount() {
179         const dt = this.$refs.table.dt()
180         dt.destroy()
181     },
182     components: {
183         DataTable,
184     },
185     props: {
186         url: {
187             type: [String, Function],
188             default: "",
189         },
190         columns: {
191             type: Array,
192             default: [],
193         },
194         actions: {
195             type: Object,
196             default: {},
197         },
198         options: {
199             type: Object,
200             default: {},
201         },
202         default_filters: {
203             type: Object,
204             required: false,
205         },
206         table_settings: {
207             type: Object,
208             required: false,
209         },
210         add_filters: {
211             type: Boolean,
212             required: false,
213         },
214         filters_options: {
215             type: Object,
216             required: false,
217         },
218     },
219 }
220 </script>