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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/kaui/multi_functions_bar_utils.js +55 -13
- data/app/assets/stylesheets/kaui/account.css +170 -2
- data/app/assets/stylesheets/kaui/common.css +243 -0
- data/app/assets/stylesheets/kaui/invoice.css +148 -2
- data/app/assets/stylesheets/kaui/payment.css +148 -2
- data/app/assets/stylesheets/kaui/queues.css +176 -88
- data/app/assets/stylesheets/kaui/tenants.css +2 -1
- data/app/controllers/kaui/admin_tenants_controller.rb +25 -0
- data/app/controllers/kaui/engine_controller.rb +2 -1
- data/app/controllers/kaui/engine_controller_util.rb +26 -2
- data/app/controllers/kaui/invoices_controller.rb +3 -3
- data/app/controllers/kaui/payments_controller.rb +3 -3
- data/app/views/kaui/accounts/_account_filterbar.html.erb +10 -212
- data/app/views/kaui/accounts/index.html.erb +9 -2
- data/app/views/kaui/admin_tenants/_show_overdue.erb +11 -0
- data/app/views/kaui/bundles/_bundle_filterbar.html.erb +56 -39
- data/app/views/kaui/invoices/_invoice_filterbar.html.erb +15 -226
- data/app/views/kaui/invoices/index.html.erb +3 -3
- data/app/views/kaui/payments/_payment_filterbar.html.erb +15 -212
- data/app/views/kaui/queues/index.html.erb +212 -191
- data/app/views/kaui/shared/_advanced_search_filterbar.html.erb +253 -0
- data/config/locales/en.yml +32 -0
- data/config/routes.rb +2 -1
- data/lib/kaui/error_handler.rb +2 -1
- data/lib/kaui/version.rb +1 -1
- metadata +3 -2
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<% modal_class ||= "" %>
|
|
2
|
+
<% search_fields ||= [] %>
|
|
3
|
+
<% date_fields ||= [] %>
|
|
4
|
+
<% number_fields ||= [] %>
|
|
5
|
+
<% search_query ||= "" %>
|
|
6
|
+
<% balance_notice ||= false %>
|
|
7
|
+
|
|
8
|
+
<div class="modal fade kaui-advanced-search-modal <%= modal_class %>" id="advanceSearchModal" tabindex="-1" role="dialog" aria-labelledby="advanceSearchModalLabel" aria-hidden="true"
|
|
9
|
+
data-save-search-label="<%= t('advanced_search.actions.save_search_as') %>"
|
|
10
|
+
data-save-label="<%= t('advanced_search.actions.save') %>"
|
|
11
|
+
data-empty-value-message="<%= t('advanced_search.validation.empty_value') %>"
|
|
12
|
+
data-missing-field-message="<%= t('advanced_search.validation.missing_field') %>">
|
|
13
|
+
<div class="modal-dialog" role="document">
|
|
14
|
+
<div class="modal-content">
|
|
15
|
+
<div class="modal-header">
|
|
16
|
+
<h5 class="modal-title d-flex align-items-center gap-3" id="advanceSearchModalLabel">
|
|
17
|
+
<span class="icon-container">
|
|
18
|
+
<%= image_tag("kaui/modal/search.svg", width: 20, height: 20) %>
|
|
19
|
+
</span>
|
|
20
|
+
<%= t('advanced_search.title') %>
|
|
21
|
+
</h5>
|
|
22
|
+
<button type="button" class="close close-button custom-hover" data-bs-dismiss="modal" aria-label="<%= t('advanced_search.actions.close') %>">
|
|
23
|
+
<span aria-hidden="true">
|
|
24
|
+
<%= image_tag("kaui/modal/close.svg", width: 20, height: 20) %>
|
|
25
|
+
</span>
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="modal-body">
|
|
29
|
+
<form id="advanceSearchForm">
|
|
30
|
+
<div class="advanced-search-builder">
|
|
31
|
+
<div class="advanced-search-group">
|
|
32
|
+
<div id="search-fields-container" class="advanced-search-rules">
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
<button type="button" class="advanced-search-add-rule custom-hover" id="addSearchField">
|
|
36
|
+
<%= image_tag("kaui/modal/plus.svg", width: 16, height: 16) %>
|
|
37
|
+
<span><%= t('advanced_search.actions.add_search') %></span>
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
40
|
+
<div id="save-search-container" style="display: none;">
|
|
41
|
+
<hr class="mt-4 mb-3">
|
|
42
|
+
<div class="form-group d-flex align-items-center mb-0">
|
|
43
|
+
<label for="savedSearchName" class="mr-2 field-label" style="width: 30%;"><%= t('advanced_search.save_as_name') %></label>
|
|
44
|
+
<input type="text" id="savedSearchName" class="form-control flex-grow-1" placeholder="<%= t('advanced_search.save_name_placeholder') %>">
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</form>
|
|
48
|
+
<% if balance_notice %>
|
|
49
|
+
<div class="alert alert-info advanced-search-alert" role="alert" style="margin-top: 30px;">
|
|
50
|
+
<%= t('advanced_search.balance_notice') %>
|
|
51
|
+
</div>
|
|
52
|
+
<% end %>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="modal-footer">
|
|
55
|
+
<div class="advanced-search-footer-left">
|
|
56
|
+
<%= render "kaui/components/button/button", {
|
|
57
|
+
label: t('advanced_search.actions.save_search_as'),
|
|
58
|
+
variant: "advanced-search-button advanced-search-button-secondary d-inline-flex align-items-center gap-1",
|
|
59
|
+
type: "button",
|
|
60
|
+
html_class: "custom-hover",
|
|
61
|
+
html_options: {
|
|
62
|
+
id: "saveAdvanceSearch"
|
|
63
|
+
}
|
|
64
|
+
} %>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="advanced-search-footer-right">
|
|
67
|
+
<%= render "kaui/components/button/button", {
|
|
68
|
+
label: t('advanced_search.actions.clear_search'),
|
|
69
|
+
variant: "advanced-search-button advanced-search-button-ghost d-inline-flex align-items-center gap-1",
|
|
70
|
+
type: "button",
|
|
71
|
+
html_class: "custom-hover",
|
|
72
|
+
html_options: {
|
|
73
|
+
id: "clearAdvanceSearch"
|
|
74
|
+
}
|
|
75
|
+
} %>
|
|
76
|
+
<%= render "kaui/components/button/button", {
|
|
77
|
+
label: t('advanced_search.actions.apply_search'),
|
|
78
|
+
variant: "advanced-search-button advanced-search-button-primary d-inline-flex align-items-center gap-1",
|
|
79
|
+
type: "button",
|
|
80
|
+
html_class: "custom-hover",
|
|
81
|
+
html_options: {
|
|
82
|
+
id: "applyAdvanceSearch"
|
|
83
|
+
}
|
|
84
|
+
} %>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<template id="search-field-template">
|
|
92
|
+
<div class="search-field">
|
|
93
|
+
<div class="advanced-search-rule-row">
|
|
94
|
+
<select class="form-control search-field-name" aria-label="<%= t('advanced_search.search_field') %>">
|
|
95
|
+
<option value="" selected><%= t('advanced_search.select_placeholder') %></option>
|
|
96
|
+
<% search_fields.each do |value, title| %>
|
|
97
|
+
<option value="<%= value %>"><%= title %></option>
|
|
98
|
+
<% end %>
|
|
99
|
+
</select>
|
|
100
|
+
<select class="form-control search-field-filter" aria-label="<%= t('advanced_search.compare_operation') %>">
|
|
101
|
+
<option value="eq"><%= t('advanced_search.operators.eq') %></option>
|
|
102
|
+
<option value="neq"><%= t('advanced_search.operators.neq') %></option>
|
|
103
|
+
<option value="gt"><%= t('advanced_search.operators.gt') %></option>
|
|
104
|
+
<option value="gte"><%= t('advanced_search.operators.gte') %></option>
|
|
105
|
+
<option value="lt"><%= t('advanced_search.operators.lt') %></option>
|
|
106
|
+
<option value="lte"><%= t('advanced_search.operators.lte') %></option>
|
|
107
|
+
<option value="like"><%= t('advanced_search.operators.like') %></option>
|
|
108
|
+
</select>
|
|
109
|
+
<input type="text" class="form-control search-field-value" aria-label="<%= t('advanced_search.search_value') %>">
|
|
110
|
+
<button type="button" class="button custom-hover remove-search-field" aria-label="<%= t('advanced_search.actions.remove_search') %>">
|
|
111
|
+
<%= image_tag("kaui/modal/red-close.svg", width: 16, height: 16) %>
|
|
112
|
+
</button>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</template>
|
|
116
|
+
|
|
117
|
+
<%= javascript_tag do %>
|
|
118
|
+
$(document).ready(function() {
|
|
119
|
+
|
|
120
|
+
populateSearchLabelsFromUrl();
|
|
121
|
+
var dateFields = <%= raw date_fields.to_json %>;
|
|
122
|
+
var numberFields = <%= raw number_fields.to_json %>;
|
|
123
|
+
var emptyValueMessage = $('#advanceSearchModal').data('empty-value-message');
|
|
124
|
+
var missingFieldMessage = $('#advanceSearchModal').data('missing-field-message');
|
|
125
|
+
|
|
126
|
+
function updateSearchFieldRow(searchField) {
|
|
127
|
+
var selectedField = searchField.find('.search-field-name option:selected').text().trim();
|
|
128
|
+
var selectedValue = searchField.find('.search-field-name').val();
|
|
129
|
+
var valueInput = searchField.find('.search-field-value');
|
|
130
|
+
|
|
131
|
+
if (!selectedValue) {
|
|
132
|
+
searchField.find('.search-field-filter').attr('name', '');
|
|
133
|
+
valueInput.attr('name', '').attr('type', 'text');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
searchField.find('.search-field-filter').attr('name', selectedField + 'Filter');
|
|
138
|
+
valueInput.attr('name', selectedField);
|
|
139
|
+
|
|
140
|
+
if (dateFields.includes(selectedField)) {
|
|
141
|
+
valueInput.attr('type', 'date');
|
|
142
|
+
} else if (numberFields.includes(selectedField)) {
|
|
143
|
+
valueInput.attr('type', 'number');
|
|
144
|
+
} else {
|
|
145
|
+
valueInput.attr('type', 'text');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function addSearchField() {
|
|
150
|
+
var template = document.getElementById('search-field-template').content.cloneNode(true);
|
|
151
|
+
document.getElementById('search-fields-container').appendChild(template);
|
|
152
|
+
updateSearchFieldRow($('#search-fields-container .search-field:last'));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
$('#addSearchField').on('click', function() {
|
|
156
|
+
addSearchField();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
$('#search-fields-container').on('change', '.search-field-name', function() {
|
|
160
|
+
updateSearchFieldRow($(this).closest('.search-field'));
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
$('#applyAdvanceSearch').on('click', function() {
|
|
164
|
+
var searchFields = $('.search-field');
|
|
165
|
+
var searchLabelsContainer = $('#search-labels-container');
|
|
166
|
+
|
|
167
|
+
var hasValue = false;
|
|
168
|
+
var hasMissingField = false;
|
|
169
|
+
searchFields.each(function() {
|
|
170
|
+
var value = $(this).find('.search-field-value').val().trim();
|
|
171
|
+
if (value !== '') {
|
|
172
|
+
hasValue = true;
|
|
173
|
+
if (!$(this).find('.search-field-name').val()) {
|
|
174
|
+
hasMissingField = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
if (!hasValue) {
|
|
180
|
+
alert(emptyValueMessage);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (hasMissingField) {
|
|
185
|
+
alert(missingFieldMessage);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
searchLabelsContainer.empty();
|
|
190
|
+
|
|
191
|
+
var table = $('<%= table_selector %>').DataTable();
|
|
192
|
+
table.off('preXhr.dt.filter');
|
|
193
|
+
table.on('preXhr.dt.filter', function(e, settings, data) {
|
|
194
|
+
data.search.value = searchQuery('<%= j search_query.to_s %>');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
var searchParams = searchQuery('<%= j search_query.to_s %>');
|
|
198
|
+
var ajaxUrl = "<%= pagination_path %>";
|
|
199
|
+
if (searchParams) {
|
|
200
|
+
ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + searchParams;
|
|
201
|
+
}
|
|
202
|
+
table.ajax.url(ajaxUrl).load();
|
|
203
|
+
|
|
204
|
+
if (searchParams) {
|
|
205
|
+
searchParams = searchParams.replace(/account_id/g, 'ac_id');
|
|
206
|
+
var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams;
|
|
207
|
+
window.history.pushState({ path: newUrl }, '', newUrl);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
searchFields.each(function() {
|
|
211
|
+
var filter = $(this).find('.search-field-filter option:selected').text().trim();
|
|
212
|
+
var value = $(this).find('.search-field-value').val().trim();
|
|
213
|
+
var columnName = $(this).find('.search-field-name option:selected').text().trim();
|
|
214
|
+
|
|
215
|
+
if (value !== '') {
|
|
216
|
+
var label = $('<span>', {
|
|
217
|
+
class: 'label label-info d-inline-flex align-items-center gap-2',
|
|
218
|
+
'data-field': columnName,
|
|
219
|
+
'data-filter': filter,
|
|
220
|
+
'data-value': value
|
|
221
|
+
});
|
|
222
|
+
var labelText = $('<span>', { text: columnName + ' [' + filter + '] ' + value });
|
|
223
|
+
var closeIcon = $('<span>', {
|
|
224
|
+
class: 'filter-close-icon',
|
|
225
|
+
style: 'cursor: pointer; margin-left: 5px; display: inline-flex; align-items: center;'
|
|
226
|
+
}).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>');
|
|
227
|
+
label.append(labelText).append(closeIcon);
|
|
228
|
+
searchLabelsContainer.append(label);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
$('#advanceSearchModal').modal('hide');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
$('#advanceSearchModal').on('show.bs.modal', function() {
|
|
236
|
+
showAdvanceSearchModal();
|
|
237
|
+
if ($('#search-fields-container .search-field').length === 0) {
|
|
238
|
+
addSearchField();
|
|
239
|
+
}
|
|
240
|
+
$('#search-fields-container .search-field').each(function() {
|
|
241
|
+
updateSearchFieldRow($(this));
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
$('#clearAdvanceSearch').on('click', function() {
|
|
246
|
+
clearAdvanceSearch();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
$('#search-fields-container').on('click', '.remove-search-field', function() {
|
|
250
|
+
$(this).closest('.search-field').remove();
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
<% end %>
|
data/config/locales/en.yml
CHANGED
|
@@ -44,6 +44,36 @@ en:
|
|
|
44
44
|
loading_data_from_server: "Loading data from server"
|
|
45
45
|
requested_amount_colon: "Requested amount: "
|
|
46
46
|
|
|
47
|
+
advanced_search:
|
|
48
|
+
title: "Advanced Search"
|
|
49
|
+
search_field: "Search field"
|
|
50
|
+
search_value: "Search value"
|
|
51
|
+
value_placeholder: "Enter search value..."
|
|
52
|
+
compare_operation: "Compare operation"
|
|
53
|
+
save_as_name: "Save As Name"
|
|
54
|
+
save_name_placeholder: "Enter a name for this search..."
|
|
55
|
+
select_placeholder: "-- Select --"
|
|
56
|
+
balance_notice: "* The Balance option won't work alongside other filters. If you search using Balance, all other filters will be ignored."
|
|
57
|
+
actions:
|
|
58
|
+
add_search: "Add Search"
|
|
59
|
+
apply_search: "Apply Search"
|
|
60
|
+
clear_search: "Clear Search"
|
|
61
|
+
close: "Close"
|
|
62
|
+
remove_search: "Remove search"
|
|
63
|
+
save: "Save"
|
|
64
|
+
save_search_as: "Save Search As..."
|
|
65
|
+
operators:
|
|
66
|
+
eq: "Equals"
|
|
67
|
+
neq: "Not Equals"
|
|
68
|
+
gt: "Greater Than"
|
|
69
|
+
gte: "Greater Than Or Equal"
|
|
70
|
+
lt: "Less Than"
|
|
71
|
+
lte: "Less Than Or Equal"
|
|
72
|
+
like: "Like"
|
|
73
|
+
validation:
|
|
74
|
+
empty_value: "Please enter a value for at least one search field."
|
|
75
|
+
missing_field: "Please select a search field for each rule with a value."
|
|
76
|
+
|
|
47
77
|
flashes:
|
|
48
78
|
notices:
|
|
49
79
|
clock_updated_successfully: "Clock was successfully updated to %{new_date}"
|
|
@@ -51,6 +81,7 @@ en:
|
|
|
51
81
|
overdue_uploaded_successfully: 'Overdue config was successfully uploaded'
|
|
52
82
|
overdue_added_successfully: 'Overdue config was successfully added'
|
|
53
83
|
overdue_updated_successfully: 'Overdue config was successfully updated'
|
|
84
|
+
overdue_deleted_successfully: 'Overdue config was successfully deleted'
|
|
54
85
|
invoice_template_uploaded_successfully: 'Invoice template was successfully uploaded'
|
|
55
86
|
invoice_translation_uploaded_successfully: 'Invoice translation was successfully uploaded'
|
|
56
87
|
catalog_translation_uploaded_successfully: 'Catalog translation was successfully uploaded'
|
|
@@ -85,3 +116,4 @@ en:
|
|
|
85
116
|
|
|
86
117
|
admin_tenants:
|
|
87
118
|
clock_warning: "This action will affect all tenants across the system. Proceed with caution."
|
|
119
|
+
delete_overdue_config_confirmation: "This action is irreversible and will permanently delete the overdue configuration for this tenant. Are you sure you want to continue?"
|
data/config/routes.rb
CHANGED
|
@@ -25,7 +25,7 @@ Kaui::Engine.routes.draw do
|
|
|
25
25
|
get '/500', to: 'errors#show', code: 500
|
|
26
26
|
|
|
27
27
|
scope '/accounts' do
|
|
28
|
-
|
|
28
|
+
post '/pagination' => 'accounts#pagination', :as => 'accounts_pagination'
|
|
29
29
|
get '/validate_external_key' => 'accounts#validate_external_key', :as => 'accounts_validate_external_key'
|
|
30
30
|
get '/download' => 'accounts#download', :as => 'download_accounts'
|
|
31
31
|
get '/export/:account_id', to: 'accounts#export_account', as: 'export_account'
|
|
@@ -189,6 +189,7 @@ Kaui::Engine.routes.draw do
|
|
|
189
189
|
delete '/:id/delete_catalog' => 'admin_tenants#delete_catalog', :as => 'admin_tenant_delete_catalog'
|
|
190
190
|
get '/:id/new_plan_currency' => 'admin_tenants#new_plan_currency', :as => 'admin_tenant_new_plan_currency'
|
|
191
191
|
get '/:id/new_overdue_config' => 'admin_tenants#new_overdue_config', :as => 'admin_tenant_new_overdue_config'
|
|
192
|
+
delete '/:id' => 'admin_tenants#delete_overdue_config', :as => 'admin_tenant_delete_overdue_config'
|
|
192
193
|
post '/upload_catalog' => 'admin_tenants#upload_catalog', :as => 'admin_tenant_upload_catalog'
|
|
193
194
|
post '/display_catalog_xml' => 'admin_tenants#display_catalog_xml', :as => 'admin_tenant_display_catalog_xml'
|
|
194
195
|
post '/display_overdue_xml' => 'admin_tenants#display_overdue_xml', :as => 'admin_tenant_display_overdue_xml'
|
data/lib/kaui/error_handler.rb
CHANGED
|
@@ -26,7 +26,8 @@ module Kaui
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def perform_redirect_after_error(error:, error_message:, redirect: true)
|
|
29
|
-
account_id = nested_hash_value(params.permit!.to_h, :account_id)
|
|
29
|
+
account_id = request.path_parameters[:account_id].presence || nested_hash_value(params.permit!.to_h, :account_id)
|
|
30
|
+
account_id = nil unless account_id.is_a?(String) || account_id.is_a?(Numeric)
|
|
30
31
|
home_path = kaui_engine.home_path
|
|
31
32
|
redirect_path = if redirect && account_id.present?
|
|
32
33
|
kaui_engine.account_path(account_id)
|
data/lib/kaui/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kaui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0.
|
|
4
|
+
version: 4.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kill Bill core team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionpack
|
|
@@ -644,6 +644,7 @@ files:
|
|
|
644
644
|
- app/views/kaui/role_definitions/new.html.erb
|
|
645
645
|
- app/views/kaui/sessions/_form.html.erb
|
|
646
646
|
- app/views/kaui/sessions/new.html.erb
|
|
647
|
+
- app/views/kaui/shared/_advanced_search_filterbar.html.erb
|
|
647
648
|
- app/views/kaui/subscriptions/_cancel_by_date_modal.html.erb
|
|
648
649
|
- app/views/kaui/subscriptions/_edit_form.html.erb
|
|
649
650
|
- app/views/kaui/subscriptions/_form.html.erb
|