kaui 4.0.14 → 4.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,226 +1,15 @@
1
- <div class="modal fade" id="advanceSearchModal" tabindex="-1" role="dialog" aria-labelledby="advanceSearchModalLabel" aria-hidden="true">
2
- <div class="modal-dialog" role="document">
3
- <div class="modal-content">
4
- <div class="modal-header">
5
- <h5 class="modal-title d-flex align-items-center gap-3" id="advanceSearchModalLabel">
6
- <span class="icon-container">
7
- <%= image_tag("kaui/modal/search.svg", width: 20, height: 20) %>
8
- </span>
9
- Advanced Search
10
- </h5>
11
- <button type="button" class="close close-button custom-hover" data-bs-dismiss="modal" aria-label="Close">
12
- <span aria-hidden="true">
13
- <%= image_tag("kaui/modal/close.svg", width: 20, height: 20) %>
14
- </span>
15
- </button>
16
- </div>
17
- <div class="modal-body">
18
- <form id="advanceSearchForm">
19
- <div class="form-group d-flex align-items-center">
20
- <label for="searchFieldSelect" class="mr-2 field-label" style="width: 30%;">Search Field</label>
21
- <select id="searchFieldSelect" class="form-control mr-2">
22
- <% if @account.account_id.present? %>
23
- <% @search_fields.reject { |value, _| value == 'balance' || value == 'account_id' }.each do |value, title| %>
24
- <option value="<%= value %>"><%= title %></option>
25
- <% end %>
26
- <% else %>
27
- <% @search_fields.each do |value, title| %>
28
- <option value="<%= value %>"><%= title %></option>
29
- <% end %>
30
- <% end %>
31
- </select>
32
- <button type="button" class="border-button custom-hover" id="addSearchField">
33
- <%= image_tag("kaui/modal/plus.svg", width: 16, height: 16) %>
34
- </button>
35
- </div>
36
- <div id="search-fields-container">
37
- </div>
38
- <div id="save-search-container" style="display: none;">
39
- <hr class="mt-4 mb-3">
40
- <div class="form-group d-flex align-items-center mb-0">
41
- <label for="savedSearchName" class="mr-2 field-label" style="width: 30%;">Save As Name</label>
42
- <input type="text" id="savedSearchName" class="form-control flex-grow-1" placeholder="Enter a name for this search...">
43
- </div>
44
- </div>
45
- </form>
46
- <% unless @account.account_id.present? %>
47
- <div class="alert alert-info" role="alert">
48
- * The Balance option won't work alongside other filters. If you search using Balance, all other filters will be ignored.
49
- </div>
50
- <% end %>
51
- </div>
52
- <div class="modal-footer">
53
- <%= render "kaui/components/button/button", {
54
- label: 'Save Search As...',
55
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
56
- type: "button",
57
- html_class: "kaui-button custom-hover",
58
- html_options: {
59
- id: "saveAdvanceSearch"
60
- }
61
- } %>
62
- <%= render "kaui/components/button/button", {
63
- label: 'Clear Search',
64
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
65
- type: "button",
66
- html_class: "kaui-button custom-hover",
67
- html_options: {
68
- id: "clearAdvanceSearch"
69
- }
70
- } %>
71
- <%= render "kaui/components/button/button", {
72
- label: 'Apply Search',
73
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
74
- type: "button",
75
- html_class: "kaui-dropdown custom-hover",
76
- html_options: {
77
- id: "applyAdvanceSearch"
78
- }
79
- } %>
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
-
85
- <template id="search-field-template">
86
- <div class="form-group row align-items-center justify-content-between search-field">
87
- <label class="col-sm-3 col-form-label search-field-label"></label>
88
- <div class="col-sm-4">
89
- <select class="form-control search-field-filter">
90
- <option value="eq">Equals</option>
91
- <option value="neq">Not Equals</option>
92
- <option value="gt">Greater Than</option>
93
- <option value="gte">Greater Than Or Equal</option>
94
- <option value="lt">Less Than</option>
95
- <option value="lte">Less Than Or Equal</option>
96
- <option value="like">Like</option>
97
- </select>
98
- </div>
99
- <div class="col-sm-4">
100
- <input type="text" class="form-control search-field-value">
101
- </div>
102
- <button type="button" class="button custom-hover" id="remove-search-field">
103
- <%= image_tag("kaui/modal/red-close.svg", width: 16, height: 16) %>
104
- </button>
105
- </div>
106
- </template>
107
-
108
-
109
- <%= javascript_tag do %>
110
- $(document).ready(function() {
111
-
112
- populateSearchLabelsFromUrl();
113
- var dateFields = ['Invoice date', 'Target date'];
114
- // Handle the "Add" button click to add new search fields
115
- $('#addSearchField').on('click', function() {
116
- var selectedField = $('#searchFieldSelect option:selected').text();
117
- var template = document.getElementById('search-field-template').content.cloneNode(true);
118
-
119
- // Set the label and input names based on the selected field
120
- template.querySelector('.search-field-label').textContent = selectedField.replace(/([A-Z])/g, ' $1').trim();
121
- template.querySelector('.search-field-filter').name = selectedField + 'Filter';
122
-
123
- // Check if the field should use a date input
124
- if (dateFields.includes(selectedField)) {
125
- template.querySelector('.search-field-value').type = 'date';
126
- } else if (selectedField === 'Balance') {
127
- template.querySelector('.search-field-value').type = 'number';
128
- } else {
129
- template.querySelector('.search-field-value').type = 'text';
130
- }
131
- template.querySelector('.search-field-value').name = selectedField;
132
-
133
- // Append the new search field to the container
134
- document.getElementById('search-fields-container').appendChild(template);
135
- });
136
-
137
- // Handle the "Apply Search" button click inside the modal
138
- $('#applyAdvanceSearch').on('click', function() {
139
- var searchFields = $('.search-field');
140
- var searchLabelsContainer = $('#search-labels-container');
141
- searchLabelsContainer.empty();
142
-
143
- // Validate that at least one search field has a value
144
- var hasValue = false;
145
- searchFields.each(function() {
146
- var value = $(this).find('.search-field-value').val().trim();
147
- if (value !== '') {
148
- hasValue = true;
149
- return false; // Break the loop
150
- }
151
- });
152
-
153
- // If no search field has a value, show an alert and prevent search
154
- if (!hasValue) {
155
- alert('Please enter a value for at least one search field.');
156
- return;
157
- }
158
-
159
- var table = $('#invoices-table').DataTable();
160
- table.off('preXhr.dt.filter');
161
- table.on('preXhr.dt.filter', function(e, settings, data) {
162
- data.search.value = searchQuery("<%= @search_query.to_s %>");
163
- });
164
-
165
- var searchParams = searchQuery("<%= @search_query.to_s %>");
166
- var ajaxUrl = "<%= invoices_pagination_path(:ordering => @ordering, :format => :json) %>";
167
- if (searchParams) {
168
- ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + searchParams;
169
- }
170
- table.ajax.url(ajaxUrl).load();
171
-
172
- // Update the URL with the search parameters
173
- if (searchParams) {
174
- searchParams = searchParams.replace(/account_id/g, 'ac_id');
175
- var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams;
176
- window.history.pushState({ path: newUrl }, '', newUrl);
177
- }
178
-
179
- searchFields.each(function() {
180
- var filter = $(this).find('.search-field-filter option:selected').text().trim();
181
- var value = $(this).find('.search-field-value').val().trim();
182
- var columnName = $(this).find('.search-field-filter').attr('name').replace('Filter', '').trim();
183
-
184
- // Create and append the search label
185
- if (value !== '') {
186
- var label = $('<span>', {
187
- class: 'label label-info d-inline-flex align-items-center gap-2',
188
- 'data-field': columnName,
189
- 'data-filter': filter,
190
- 'data-value': value
191
- });
192
- var labelText = $('<span>', { text: columnName + ' [' + filter + '] ' + value });
193
- var closeIcon = $('<span>', {
194
- class: 'filter-close-icon',
195
- style: 'cursor: pointer; margin-left: 5px; display: inline-flex; align-items: center;'
196
- }).html('<svg width="12" height="12" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.8337 4.1665L4.16699 15.8332M4.16699 4.1665L15.8337 15.8332" stroke="#A4A7AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>');
197
- label.append(labelText).append(closeIcon);
198
- searchLabelsContainer.append(label);
199
- }
200
- });
201
- $('#advanceSearchModal').modal('hide');
202
- });
203
-
204
- // Populate the modal with the current filters when it is shown
205
- $('#advanceSearchModal').on('show.bs.modal', function() {
206
- showAdvanceSearchModal();
207
- $('#search-fields-container .search-field').each(function() {
208
- var input = $(this).find('.search-field-value');
209
- if (dateFields.includes(input.attr('name'))) {
210
- input.attr('type', 'date');
211
- } else if (input.attr('name') === 'Balance') {
212
- input.attr('type', 'number');
213
- }
214
- });
215
- });
216
-
217
- $('#clearAdvanceSearch').on('click', function() {
218
- clearAdvanceSearch();
219
- });
220
-
221
- // Handle the remove icon click event to remove search fields
222
- $('#search-fields-container').on('click', '#remove-search-field', function() {
223
- $(this).closest('.search-field').remove();
224
- });
225
- });
226
- <% end %>
1
+ <% invoice_search_fields = if @account.account_id.present?
2
+ @search_fields.reject { |value, _| ['account_id', 'balance'].include?(value) }
3
+ else
4
+ @search_fields
5
+ end %>
6
+
7
+ <%= render "kaui/shared/advanced_search_filterbar", {
8
+ search_fields: invoice_search_fields,
9
+ date_fields: ['Invoice date', 'Target date'],
10
+ number_fields: ['Balance'],
11
+ table_selector: '#invoices-table',
12
+ pagination_path: invoices_pagination_path(:ordering => @ordering, :format => :json),
13
+ search_query: @search_query.to_s,
14
+ balance_notice: !@account.account_id.present?
15
+ } %>
@@ -50,7 +50,7 @@ $(document).ready(function() {
50
50
  }
51
51
  });
52
52
 
53
- var stateKey = 'DataTables_invoices-table_' + window.location.pathname.replace(/\//g, '_');
53
+ var stateKey = 'DataTables_invoices-table';
54
54
  var state = JSON.parse(localStorage.getItem(stateKey));
55
55
  if (state) {
56
56
  state.start = <%= @offset %>;
@@ -64,10 +64,10 @@ $(document).ready(function() {
64
64
  },
65
65
  "stateSave": true,
66
66
  "stateSaveCallback": function(settings, data) {
67
- localStorage.setItem('DataTables_invoices-table', JSON.stringify(data));
67
+ localStorage.setItem(stateKey, JSON.stringify(data));
68
68
  },
69
69
  "stateLoadCallback": function(settings) {
70
- return JSON.parse(localStorage.getItem('DataTables_invoices-table'));
70
+ return JSON.parse(localStorage.getItem(stateKey));
71
71
  },
72
72
  "scrollX": true,
73
73
  "dom": "<'row'r>t<'row'<'col-md-6'i><'col-md-6'p>>",
@@ -1,212 +1,15 @@
1
-
2
- <div class="modal fade" id="advanceSearchModal" tabindex="-1" role="dialog" aria-labelledby="advanceSearchModalLabel" aria-hidden="true">
3
- <div class="modal-dialog" role="document">
4
- <div class="modal-content">
5
- <div class="modal-header">
6
- <h5 class="modal-title d-flex align-items-center gap-3" id="advanceSearchModalLabel">
7
- <span class="icon-container">
8
- <%= image_tag("kaui/modal/search.svg", width: 20, height: 20) %>
9
- </span>
10
- Advanced Search
11
- </h5>
12
- <button type="button" class="close close-button custom-hover" data-bs-dismiss="modal" aria-label="Close">
13
- <span aria-hidden="true">
14
- <%= image_tag("kaui/modal/close.svg", width: 20, height: 20) %>
15
- </span>
16
- </button>
17
- </div>
18
- <div class="modal-body">
19
- <form id="advanceSearchForm">
20
- <div class="form-group d-flex align-items-center">
21
- <label for="searchFieldSelect" class="mr-2 field-label" style="width: 30%;">Search Field</label>
22
- <select id="searchFieldSelect" class="form-control mr-2">
23
- <% if @account.account_id.present? %>
24
- <% @search_fields.reject { |value, _| value == 'account_id' }.each do |value, title| %>
25
- <option value="<%= value %>"><%= title %></option>
26
- <% end %>
27
- <% else %>
28
- <% @search_fields.each do |value, title| %>
29
- <option value="<%= value %>"><%= title %></option>
30
- <% end %>
31
- <% end %>
32
- </select>
33
- <button type="button" class="border-button custom-hover" id="addSearchField">
34
- <%= image_tag("kaui/modal/plus.svg", width: 16, height: 16) %>
35
- </button>
36
- </div>
37
- <div id="search-fields-container">
38
- </div>
39
- <div id="save-search-container" style="display: none;">
40
- <hr class="mt-4 mb-3">
41
- <div class="form-group d-flex align-items-center mb-0">
42
- <label for="savedSearchName" class="mr-2 field-label" style="width: 30%;">Save As Name</label>
43
- <input type="text" id="savedSearchName" class="form-control flex-grow-1" placeholder="Enter a name for this search...">
44
- </div>
45
- </div>
46
- </form>
47
- </div>
48
- <div class="modal-footer">
49
- <%= render "kaui/components/button/button", {
50
- label: 'Save Search As...',
51
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
52
- type: "button",
53
- html_class: "kaui-button custom-hover",
54
- html_options: {
55
- id: "saveAdvanceSearch"
56
- }
57
- } %>
58
- <%= render "kaui/components/button/button", {
59
- label: 'Clear Search',
60
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
61
- type: "button",
62
- html_class: "kaui-button custom-hover",
63
- html_options: {
64
- id: "clearAdvanceSearch"
65
- }
66
- } %>
67
- <%= render "kaui/components/button/button", {
68
- label: 'Apply Search',
69
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
70
- type: "button",
71
- html_class: "kaui-dropdown custom-hover",
72
- html_options: {
73
- id: "applyAdvanceSearch"
74
- }
75
- } %>
76
- </div>
77
- </div>
78
- </div>
79
- </div>
80
-
81
- <template id="search-field-template">
82
- <div class="form-group row align-items-center justify-content-between search-field">
83
- <label class="col-sm-3 col-form-label search-field-label"></label>
84
- <div class="col-sm-4">
85
- <select class="form-control search-field-filter">
86
- <option value="eq">Equals</option>
87
- <option value="neq">Not Equals</option>
88
- <option value="gt">Greater Than</option>
89
- <option value="gte">Greater Than Or Equal</option>
90
- <option value="lt">Less Than</option>
91
- <option value="lte">Less Than Or Equal</option>
92
- <option value="like">Like</option>
93
- </select>
94
- </div>
95
- <div class="col-sm-4">
96
- <input type="text" class="form-control search-field-value">
97
- </div>
98
- <button type="button" class="button custom-hover" id="remove-search-field">
99
- <%= image_tag("kaui/modal/red-close.svg", width: 16, height: 16) %>
100
- </button>
101
- </div>
102
- </template>
103
-
104
- <%= javascript_tag do %>
105
- $(document).ready(function() {
106
-
107
- populateSearchLabelsFromUrl();
108
-
109
- // Handle the "Add" button click to add new search fields
110
- $('#addSearchField').on('click', function() {
111
- var selectedField = $('#searchFieldSelect option:selected').text();
112
- var template = document.getElementById('search-field-template').content.cloneNode(true);
113
-
114
- // Set the label and input names based on the selected field
115
- template.querySelector('.search-field-label').textContent = selectedField.replace(/([A-Z])/g, ' $1').trim();
116
- template.querySelector('.search-field-filter').name = selectedField + 'Filter';
117
-
118
- // Check if the field should use a date input
119
- var dateFields = ['Invoice date', 'Target date'];
120
- if (dateFields.includes(selectedField)) {
121
- template.querySelector('.search-field-value').type = 'date';
122
- } else {
123
- template.querySelector('.search-field-value').type = 'text';
124
- }
125
- template.querySelector('.search-field-value').name = selectedField;
126
-
127
- // Append the new search field to the container
128
- document.getElementById('search-fields-container').appendChild(template);
129
- });
130
-
131
- // Handle the "Apply Search" button click inside the modal
132
- $('#applyAdvanceSearch').on('click', function() {
133
- var searchFields = $('.search-field');
134
- var searchLabelsContainer = $('#search-labels-container');
135
- searchLabelsContainer.empty();
136
-
137
- // Validate that at least one search field has a value
138
- var hasValue = false;
139
- searchFields.each(function() {
140
- var value = $(this).find('.search-field-value').val().trim();
141
- if (value !== '') {
142
- hasValue = true;
143
- return false; // Break the loop
144
- }
145
- });
146
-
147
- // If no search field has a value, show an alert and prevent search
148
- if (!hasValue) {
149
- alert('Please enter a value for at least one search field.');
150
- return;
151
- }
152
-
153
- var table = $('#payments-table').DataTable();
154
- table.off('preXhr.dt.filter');
155
- table.on('preXhr.dt.filter', function(e, settings, data) {
156
- data.search.value = searchQuery("<%= @search_query.to_s %>");
157
- });
158
-
159
- var searchParams = searchQuery("<%= @search_query.to_s %>");
160
- var ajaxUrl = "<%= payments_pagination_path(:ordering => @ordering, :format => :json) %>";
161
- if (searchParams) {
162
- ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + searchParams;
163
- }
164
- table.ajax.url(ajaxUrl).load();
165
-
166
- // Update the URL with the search parameters
167
- if (searchParams) {
168
- searchParams = searchParams.replace(/account_id/g, 'ac_id');
169
- var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams;
170
- window.history.pushState({ path: newUrl }, '', newUrl);
171
- }
172
-
173
- searchFields.each(function() {
174
- var filter = $(this).find('.search-field-filter option:selected').text().trim();
175
- var value = $(this).find('.search-field-value').val().trim();
176
- var columnName = $(this).find('.search-field-filter').attr('name').replace('Filter', '').trim();
177
-
178
- // Create and append the search label
179
- if (value !== '') {
180
- var label = $('<span>', {
181
- class: 'label label-info d-inline-flex align-items-center gap-2',
182
- 'data-field': columnName,
183
- 'data-filter': filter,
184
- 'data-value': value
185
- });
186
- var labelText = $('<span>', { text: columnName + ' [' + filter + '] ' + value });
187
- var closeIcon = $('<span>', {
188
- class: 'filter-close-icon',
189
- style: 'cursor: pointer; margin-left: 5px; display: inline-flex; align-items: center;'
190
- }).html('<svg width="12" height="12" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.8337 4.1665L4.16699 15.8332M4.16699 4.1665L15.8337 15.8332" stroke="#A4A7AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>');
191
- label.append(labelText).append(closeIcon);
192
- searchLabelsContainer.append(label);
193
- }
194
- });
195
- $('#advanceSearchModal').modal('hide');
196
- });
197
-
198
- // Populate the modal with the current filters when it is shown
199
- $('#advanceSearchModal').on('show.bs.modal', function() {
200
- showAdvanceSearchModal();
201
- });
202
-
203
- $('#clearAdvanceSearch').on('click', function() {
204
- clearAdvanceSearch();
205
- });
206
-
207
- // Handle the remove icon click event to remove search fields
208
- $('#search-fields-container').on('click', '#remove-search-field', function() {
209
- $(this).closest('.search-field').remove();
210
- });
211
- });
212
- <% end %>
1
+ <% payment_search_fields = if @account.account_id.present?
2
+ @search_fields.reject { |value, _| value == 'account_id' }
3
+ else
4
+ @search_fields
5
+ end %>
6
+
7
+ <%= render "kaui/shared/advanced_search_filterbar", {
8
+ search_fields: payment_search_fields,
9
+ date_fields: [],
10
+ number_fields: [],
11
+ table_selector: '#payments-table',
12
+ pagination_path: payments_pagination_path(:ordering => @ordering, :format => :json),
13
+ search_query: @search_query.to_s,
14
+ balance_notice: false
15
+ } %>