Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ gemspec

gem 'rails', '~> 7.0.1'

# Lock minitest to 5.x until Rails 7.1+ adds Minitest 6.0 support
# Minitest 6.0.0 was released Dec 2024 with breaking API changes
gem 'minitest', '~> 5.0'

# This fix is temporary until the next release of the gem
# See https://stackoverflow.com/questions/79360526/uninitialized-constant-activesupportloggerthreadsafelevellogger-nameerror
gem 'concurrent-ruby', '1.3.4'
Expand Down
7 changes: 5 additions & 2 deletions app/assets/javascripts/kaui/kaui_override.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ function setObjectIdPopover(){
// Custom tooltip function for object IDs
// attributes:
// data-id = content of the tooltip, object id; required
// title = title of the tooltip; not required
// data-title = title of the tooltip; not required
function setObjectIdTooltip() {
// Remove any existing tooltips
$(".custom-tooltip").remove();
Expand Down Expand Up @@ -476,6 +476,9 @@ function showCustomTooltip(element, objectId) {
var position = $element.offset();
var elementHeight = $element.outerHeight();
var elementWidth = $element.outerWidth();

// Get custom title from data-title attribute or default to "Subscription ID"
var tooltipTitle = $element.data("title") || "Subscription ID";

// Create tooltip content with header and custom SVG icon
var svgIcon =
Expand All @@ -485,7 +488,7 @@ function showCustomTooltip(element, objectId) {
"</svg>";

var tooltipContent =
'<div class="tooltip-header">Subscription ID</div>' +
'<div class="tooltip-header">' + tooltipTitle + '</div>' +
'<div class="tooltip-content">' +
'<span class="tooltip-id">' +
objectId +
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/kaui/admin_allowed_users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class AdminAllowedUsersController < Kaui::EngineController

def index
@allowed_users = retrieve_allowed_users_for_current_user
@roles_by_user = {}
@allowed_users.each do |user|
@roles_by_user[user.kb_username] = roles_for_user(user)
end
end

def new
Expand Down
1 change: 1 addition & 0 deletions app/controllers/kaui/payments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def download

if all_fields_checked
columns = KillBillClient::Model::PaymentAttributes.instance_variable_get('@json_attributes') - %w[transactions audit_logs]
columns += %w[payment_date status] # additional fields not part of the model
csv_headers = columns.dup
Kaui::Payment::REMAPPING_FIELDS.each do |k, v|
index = csv_headers.index(k)
Expand Down
14 changes: 14 additions & 0 deletions app/helpers/kaui/admin_allowed_users_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Kaui
module AdminAllowedUsersHelper
# Check if a user can be deleted
# Returns false if the user is an admin or the current logged-in user
def can_delete_user?(user, user_roles)
is_admin = user_roles.include?('admin') || user.kb_username == Kaui.root_username
is_current_user = user.kb_username == current_user.kb_username

!is_admin && !is_current_user
end
end
end
10 changes: 7 additions & 3 deletions app/views/kaui/admin_allowed_users/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@
<td><%= link_to u.kb_username, admin_allowed_user_path(u.id) %></td>
<td><%= u.description %></td>
<td class="text-end">
<%= form_tag kaui_engine.admin_allowed_user_path(u.id), method: :delete, class: 'd-inline', onsubmit: "return confirm('Are you sure?');" do %>
<%= button_tag type: 'submit', class: 'btn btn-outline-secondary d-inline-flex align-items-center gap-1 kaui-button delete-button custom-hover' do %>
Delete
<% user_roles = @roles_by_user[u.kb_username] || [] %>
<% if can_delete_user?(u, user_roles) %>
<%= form_tag kaui_engine.admin_allowed_user_path(u.id), method: :delete, class: 'd-inline', onsubmit: "return confirm('Are you sure?');" do %>
<%= button_tag type: 'submit', class: 'btn btn-outline-secondary d-inline-flex align-items-center gap-1 kaui-button delete-button custom-hover' do %>
Delete
<% end %>
<% end %>
<% end %>

<%= link_to kaui_engine.edit_admin_allowed_user_path(u.id), class: 'text-decoration-none' do %>
<%= render "kaui/components/button/button", {
label: "Edit",
Expand Down
32 changes: 17 additions & 15 deletions app/views/kaui/admin_allowed_users/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
<h2>User details</h2>
</div>
<span>
<%= render "kaui/components/button/button", {
label: 'Delete',
variant: "outline-secondary d-inline-flex align-items-center gap-1",
type: "button",
html_class: "kaui-button delete-button custom-hover",
html_options: {
data: {
confirm: "Are you sure?",
method: "delete",
turbo: false, # Optional: disable Turbo if using Rails Turbo
"url": kaui_engine.admin_allowed_user_path(@allowed_user.id)
},
onclick: "if (confirm(this.dataset.confirm)) { Rails.ajax({ url: this.dataset.url, type: this.dataset.method }); }"
}
} %>
<% if can_delete_user?(@allowed_user, @roles) %>
<%= render "kaui/components/button/button", {
label: 'Delete',
variant: "outline-secondary d-inline-flex align-items-center gap-1",
type: "button",
html_class: "kaui-button delete-button custom-hover",
html_options: {
data: {
confirm: "Are you sure?",
method: "delete",
turbo: false, # Optional: disable Turbo if using Rails Turbo
"url": kaui_engine.admin_allowed_user_path(@allowed_user.id)
},
onclick: "if (confirm(this.dataset.confirm)) { Rails.ajax({ url: this.dataset.url, type: this.dataset.method }); }"
}
} %>
<% end %>

<%= link_to kaui_engine.edit_admin_allowed_user_path(@allowed_user.id),
:class => '' do %>
Expand Down
99 changes: 51 additions & 48 deletions app/views/kaui/admin_tenants/new_catalog.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -264,55 +264,58 @@ $(document).ready(function() {
recompute_available_base_products_for_ao();
});

// Custom validation since HTML5 validation is not working
// (possibly due to jQuery autocomplete or other JavaScript interference)
$('#catalog_simple form').on('submit', function(e) {
var isValid = true;
var pattern = /^[a-zA-Z_][\w\.-]*$/;

// Validate Product Name
var productName = $('#simple_plan_product_name').val().trim();
var productNameField = $('#simple_plan_product_name');

if (productName === '') {
showError(productNameField, 'Product Name is required');
isValid = false;
} else if (!pattern.test(productName)) {
showError(productNameField, 'Product Name must start with a letter or underscore, and can only contain letters, digits, underscores, hyphens, and periods');
isValid = false;
} else {
clearError(productNameField);
}

// Validate Plan Name
var planName = $('#simple_plan_plan_id').val().trim();
var planNameField = $('#simple_plan_plan_id');

if (planName === '') {
showError(planNameField, 'Plan Name is required');
isValid = false;
} else if (!pattern.test(planName)) {
showError(planNameField, 'Plan Name must start with a letter or underscore, and can only contain letters, digits, underscores, hyphens, and periods');
isValid = false;
} else {
clearError(planNameField);
}

if (!isValid) {
e.preventDefault();
e.stopPropagation();
// Scroll to first error
$('.error-message:first').get(0)?.scrollIntoView({ behavior: 'smooth', block: 'center' });
return false;
}

return true;
});
// Realtime validation function
function validateField(field) {
var pattern = /^[a-zA-Z_][\w\.-]*$/;
var value = field.val().trim();
var fieldName = field.attr('id') === 'simple_plan_product_name' ? 'Product Name' : 'Plan Name';

if (value === '') {
showError(field, fieldName + ' is required');
return false;
} else if (!pattern.test(value)) {
showError(field, fieldName + ' must start with a letter or underscore, and can only contain letters, digits, underscores, hyphens, and periods');
return false;
} else {
clearError(field);
return true;
}
}

// Realtime validation on input
$('#simple_plan_product_name, #simple_plan_plan_id').on('input', function() {
validateField($(this));
});

// Validation on blur (when user leaves the field)
$('#simple_plan_product_name, #simple_plan_plan_id').on('blur', function() {
validateField($(this));
});

// Custom validation on form submit
$('#catalog_simple form').on('submit', function(e) {
var isValid = true;

// Validate Product Name
if (!validateField($('#simple_plan_product_name'))) {
isValid = false;
}

// Clear errors on input
$('#simple_plan_product_name, #simple_plan_plan_id').on('input', function() {
clearError($(this));
});
// Validate Plan Name
if (!validateField($('#simple_plan_plan_id'))) {
isValid = false;
}

if (!isValid) {
e.preventDefault();
e.stopPropagation();
// Scroll to first error
$('.error-message:first').get(0)?.scrollIntoView({ behavior: 'smooth', block: 'center' });
return false;
}

return true;
});
});

function showError(field, message) {
Expand Down
13 changes: 12 additions & 1 deletion app/views/kaui/invoices/_invoice_table.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@

</td>
<% end %>
<td onClick="hightlightLinkedItems('<%= item.invoice_item_id %>', '<%= item.linked_invoice_item_id %>'); return false;"><%= item.pretty_plan_name.blank? || !item.item_type.in?(%w{USAGE RECURRING}) ? item.description : item.pretty_plan_name %></td>
<td onClick="hightlightLinkedItems('<%= item.invoice_item_id %>', '<%= item.linked_invoice_item_id %>'); return false;">
<span id="<%= item.invoice_item_id %>-popover" class="object-id-popover" data-id="<%= item.invoice_item_id %>" data-title="Invoice Item ID">
<%= item.pretty_plan_name.blank? || !item.item_type.in?(%w{USAGE RECURRING}) ? item.description : item.pretty_plan_name %>
</span>
</td>
<td onClick="hightlightLinkedItems('<%= item.invoice_item_id %>', '<%= item.linked_invoice_item_id %>'); return false;"><%= item.start_date.html_safe if item.start_date %></td>
<td onClick="hightlightLinkedItems('<%= item.invoice_item_id %>', '<%= item.linked_invoice_item_id %>'); return false;"><%= item.end_date.html_safe if item.end_date %></td>
<td onClick="hightlightLinkedItems('<%= item.invoice_item_id %>', '<%= item.linked_invoice_item_id %>'); return false;"><%= item.subscription_id %></td>
Expand Down Expand Up @@ -149,4 +153,11 @@
}
});
}

$(document).ready(function() {
// Initialize tooltips for invoice item IDs
if (typeof setObjectIdTooltip === 'function') {
setObjectIdTooltip();
}
});
</script>
Loading