kaui 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +5 -29
- data/app/assets/javascripts/kaui/kaui.js +1 -1
- data/app/assets/stylesheets/kaui/account.less +9 -1
- data/app/assets/stylesheets/kaui/common.less +46 -3
- data/app/controllers/kaui/accounts_controller.rb +11 -15
- data/app/controllers/kaui/admin_tenants_controller.rb +77 -106
- data/app/controllers/kaui/audit_logs_controller.rb +3 -3
- data/app/controllers/kaui/bundles_controller.rb +4 -0
- data/app/controllers/kaui/engine_controller_util.rb +25 -17
- data/app/controllers/kaui/invoice_tags_controller.rb +28 -0
- data/app/controllers/kaui/invoices_controller.rb +65 -14
- data/app/controllers/kaui/payment_methods_controller.rb +14 -3
- data/app/controllers/kaui/sessions_controller.rb +6 -0
- data/app/controllers/kaui/subscriptions_controller.rb +13 -4
- data/app/helpers/kaui/account_helper.rb +10 -2
- data/app/helpers/kaui/payment_method_helper.rb +5 -3
- data/app/helpers/kaui/plugin_helper.rb +10 -49
- data/app/helpers/kaui/subscription_helper.rb +26 -9
- data/app/helpers/kaui/uuid_helper.rb +1 -0
- data/app/models/kaui/admin_tenant.rb +8 -84
- data/app/models/kaui/catalog.rb +28 -2
- data/app/models/kaui/tag.rb +1 -1
- data/app/views/kaui/account_emails/_form.html.erb +1 -1
- data/app/views/kaui/accounts/_billing_info.html.erb +4 -0
- data/app/views/kaui/accounts/_form.html.erb +1 -1
- data/app/views/kaui/accounts/_payment_methods.html.erb +3 -0
- data/app/views/kaui/accounts/index.html.erb +7 -4
- data/app/views/kaui/admin_tenants/_form_plugin_config.erb +59 -241
- data/app/views/kaui/admin_tenants/_show_catalog_simple.erb +2 -2
- data/app/views/kaui/admin_tenants/new_catalog.html.erb +16 -15
- data/app/views/kaui/bundles/_bundle_details.html.erb +12 -0
- data/app/views/kaui/bundles/index.html.erb +3 -14
- data/app/views/kaui/chargebacks/_form.html.erb +1 -1
- data/app/views/kaui/charges/_form.html.erb +1 -1
- data/app/views/kaui/invoice_tags/_form.html.erb +33 -0
- data/app/views/kaui/invoice_tags/_form_bar.html.erb +21 -0
- data/app/views/kaui/invoice_tags/edit.html.erb +10 -0
- data/app/views/kaui/invoices/_invoice_table.html.erb +30 -9
- data/app/views/kaui/invoices/index.html.erb +6 -4
- data/app/views/kaui/invoices/show.html.erb +11 -2
- data/app/views/kaui/layouts/kaui_flash.html.erb +8 -1
- data/app/views/kaui/payments/_form.html.erb +1 -1
- data/app/views/kaui/payments/_payment_table.html.erb +2 -2
- data/app/views/kaui/payments/index.html.erb +3 -1
- data/app/views/kaui/subscriptions/_edit_form.html.erb +1 -1
- data/app/views/kaui/subscriptions/_form.html.erb +1 -1
- data/app/views/kaui/subscriptions/_subscriptions_table.html.erb +3 -3
- data/config/routes.rb +6 -1
- data/lib/kaui.rb +55 -0
- data/lib/kaui/version.rb +1 -1
- data/test/dummy/config/database.yml +2 -2
- data/test/dummy/config/initializers/cookies_serializer.rb +1 -1
- data/test/dummy/config/initializers/money.rb +2 -0
- data/test/functional/kaui/account_emails_controller_test.rb +2 -2
- data/test/functional/kaui/account_tags_controller_test.rb +1 -1
- data/test/functional/kaui/accounts_controller_test.rb +4 -4
- data/test/functional/kaui/admin_tenants_controller_test.rb +3 -23
- data/test/functional/kaui/bundle_tags_controller_test.rb +1 -1
- data/test/functional/kaui/bundles_controller_test.rb +3 -3
- data/test/functional/kaui/chargebacks_controller_test.rb +2 -2
- data/test/functional/kaui/charges_controller_test.rb +2 -2
- data/test/functional/kaui/credits_controller_test.rb +5 -5
- data/test/functional/kaui/home_controller_test.rb +5 -5
- data/test/functional/kaui/invoice_items_controller_test.rb +3 -3
- data/test/functional/kaui/invoices_controller_test.rb +2 -2
- data/test/functional/kaui/refunds_controller_test.rb +2 -2
- data/test/functional/kaui/subscriptions_controller_test.rb +6 -6
- data/test/killbill_test_helper.rb +8 -6
- data/test/unit/helpers/kaui/payment_method_helper_test.rb +17 -0
- data/test/unit/kaui/account_test.rb +2 -2
- data/test/unit/kaui/admin_tenant_test.rb +10 -47
- data/test/unit/kaui/invoice_item_test.rb +1 -1
- data/test/unit/kaui/invoice_payment_test.rb +7 -7
- data/test/unit/kaui/invoice_test.rb +4 -4
- data/test/unit/kaui/payment_test.rb +7 -7
- metadata +110 -86
@@ -10,25 +10,39 @@ module Kaui
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def humanized_product_category(product_category)
|
13
|
-
if product_category == 'BASE'
|
13
|
+
if product_category.to_s == 'BASE'
|
14
14
|
'Base'
|
15
|
-
elsif product_category == 'ADD_ON'
|
15
|
+
elsif product_category.to_s == 'ADD_ON'
|
16
16
|
'Add-on'
|
17
17
|
else
|
18
|
-
product_category.downcase.capitalize
|
18
|
+
product_category.to_s.downcase.capitalize
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def humanized_subscription_product_name(sub)
|
23
|
-
if !sub.present?
|
22
|
+
def humanized_subscription_product_name(sub, catalog = nil)
|
23
|
+
if !sub.present? || !sub.product_name.present?
|
24
24
|
nil
|
25
25
|
else
|
26
|
-
|
26
|
+
product = catalog.nil? ? nil : catalog.products.find { |p| p.name == sub.product_name }
|
27
|
+
humanized_product_name(!product.nil? && !product.pretty_name.blank? ? product.pretty_name : sub.product_name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def humanized_subscription_pretty_plan_name(sub, catalog = nil)
|
32
|
+
if !sub.present? || !sub.product_name.present?
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
product = catalog.nil? ? nil : catalog.products.find { |p| p.name == sub.product_name }
|
36
|
+
return nil if product.nil?
|
37
|
+
|
38
|
+
plan = product.plans.find { |p| p.name == sub.plan_name }
|
39
|
+
plan.nil? || plan.pretty_name.blank? ? nil : plan.pretty_name
|
27
40
|
end
|
28
41
|
end
|
29
42
|
|
30
43
|
def humanized_product_name(product_name)
|
31
|
-
|
44
|
+
# Don't change the casing to avoid confusions (could lead to different products with different casing)
|
45
|
+
product_name
|
32
46
|
end
|
33
47
|
|
34
48
|
def humanized_subscription_billing_period(sub)
|
@@ -55,8 +69,11 @@ module Kaui
|
|
55
69
|
end
|
56
70
|
end
|
57
71
|
|
58
|
-
def
|
59
|
-
|
72
|
+
def humanized_subscription_plan_or_product_name(sub, catalog = nil)
|
73
|
+
pretty_plan_name = humanized_subscription_pretty_plan_name(sub, catalog)
|
74
|
+
return pretty_plan_name unless pretty_plan_name.nil?
|
75
|
+
|
76
|
+
humanized_product_name = humanized_subscription_product_name(sub, catalog)
|
60
77
|
humanized_billing_period = humanized_subscription_billing_period(sub)
|
61
78
|
humanized_price_list = humanized_subscription_price_list(sub, false)
|
62
79
|
|
@@ -26,81 +26,21 @@ class Kaui::AdminTenant < KillBillClient::Model::Tenant
|
|
26
26
|
KillBillClient::Model::Tenant.upload_tenant_plugin_config(plugin_name, plugin_config, user, reason, comment, options)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
require 'yaml'
|
32
|
-
|
33
|
-
source = URI.parse('https://raw.githubusercontent.com/killbill/killbill-cloud/master/kpm/lib/kpm/plugins_directory.yml').read
|
34
|
-
YAML.load(source)
|
35
|
-
rescue
|
36
|
-
# Ignore gracefully
|
37
|
-
{}
|
38
|
-
end
|
39
|
-
|
40
|
-
def get_oss_plugin_info(plugin_directory)
|
41
|
-
# Serialize the plugin state for the view:
|
42
|
-
# plugin_name#plugin_type:prop1,prop2,prop3;plugin_name#plugin_type:prop1,prop2,prop3;...
|
43
|
-
#
|
44
|
-
plugin_config = plugin_directory.inject({}) do |hsh, (k,v)|
|
45
|
-
hsh["#{k}##{v[:type]}"] = v[:require] || []
|
46
|
-
hsh
|
47
|
-
end
|
48
|
-
plugin_config.map { |e,v| "#{e}:#{v.join(",")}" }.join(";")
|
49
|
-
end
|
50
|
-
|
51
|
-
def get_tenant_plugin_config(plugin_directory, options)
|
52
|
-
require 'yaml'
|
53
|
-
|
29
|
+
# Return a map of plugin_name => config
|
30
|
+
def get_tenant_plugin_config(options)
|
54
31
|
raw_tenant_config = KillBillClient::Model::Tenant::search_tenant_config("PLUGIN_CONFIG_", options)
|
55
32
|
|
56
33
|
tenant_config = raw_tenant_config.inject({}) do |hsh, e|
|
57
34
|
# Strip prefix '/PLUGIN_CONFIG_'
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
# hack:: rewrite key, to allow the ui to find the right configuration inputs
|
64
|
-
plugin_key = rewrite_plugin_key(plugin_key) unless plugin_key.nil?
|
65
|
-
# If such key exists, lookup in plugin directory to see if is an official plugin
|
66
|
-
is_an_official_plugin = !plugin_key.nil? && !plugin_directory[plugin_key.to_sym].blank?
|
67
|
-
# Deserialize config based on string possible format, if exist in the official repository
|
68
|
-
if is_an_official_plugin && is_yaml?(e.values[0])
|
69
|
-
yml = YAML.load(e.values[0])
|
70
|
-
# Hash of properties
|
71
|
-
# is plugin key part of the yaml?
|
72
|
-
if yml[plugin_key.to_sym].blank?
|
73
|
-
# if not set it as raw
|
74
|
-
hsh[plugin_key] = {:raw_config => e.values[0]}
|
75
|
-
else
|
76
|
-
hsh[plugin_key] = yml[plugin_key.to_sym]
|
77
|
-
end
|
78
|
-
hsh[plugin_key][:_raw] = e.values[0]
|
79
|
-
elsif is_an_official_plugin && is_kv?(e.values[0])
|
80
|
-
# Construct hash of properties based on java properties (k1=v1\nk2=v2\n...)
|
81
|
-
hsh[plugin_key] = e.values[0].split("\n").inject({}) do |h, p0|
|
82
|
-
k, v = p0.split('=');
|
83
|
-
h[k] = v;
|
84
|
-
h
|
85
|
-
end
|
86
|
-
hsh[plugin_key][:_raw] = e.values[0]
|
87
|
-
else
|
88
|
-
# Construct simple hash with one property :raw_config
|
89
|
-
hsh[killbill_key] = {:raw_config => e.values[0], :_raw => e.values[0]}
|
90
|
-
end
|
35
|
+
plugin_name = e.key.gsub!(/PLUGIN_CONFIG_/, '')
|
36
|
+
|
37
|
+
# Construct simple hash with one property (first value)
|
38
|
+
hsh[plugin_name] = e.values[0]
|
39
|
+
|
91
40
|
hsh
|
92
41
|
end
|
93
42
|
|
94
|
-
|
95
|
-
# plugin_key1::key1=value1|key2=value2|..;plugin_key2::...
|
96
|
-
tenant_config.map do |plugin_key, props|
|
97
|
-
serialized_props = props.inject("") do |s, (k, v)|
|
98
|
-
e="#{k.to_s}=#{v.to_s}";
|
99
|
-
s == "" ? s="#{e}" : s="#{s}|#{e}";
|
100
|
-
s
|
101
|
-
end
|
102
|
-
"#{plugin_key}::#{serialized_props}"
|
103
|
-
end.join(";")
|
43
|
+
tenant_config
|
104
44
|
end
|
105
45
|
|
106
46
|
def format_plugin_config(plugin_key, plugin_type, props)
|
@@ -142,22 +82,6 @@ class Kaui::AdminTenant < KillBillClient::Model::Tenant
|
|
142
82
|
props
|
143
83
|
end
|
144
84
|
|
145
|
-
# hack when the plugin name after killbill is not the same as the plugin key, this mainly affects ruby plugin configuration,
|
146
|
-
# as it use the key to retrieve the configuration.
|
147
|
-
def rewrite_plugin_key(plugin_key)
|
148
|
-
if plugin_key.start_with?('paypal')
|
149
|
-
'paypal_express'
|
150
|
-
elsif plugin_key.start_with?('firstdata')
|
151
|
-
'firstdata_e4'
|
152
|
-
elsif plugin_key.start_with?('bridge')
|
153
|
-
'payment_bridge'
|
154
|
-
elsif plugin_key.start_with?('payu-latam')
|
155
|
-
'payu_latam'
|
156
|
-
else
|
157
|
-
"#{plugin_key}"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
85
|
# checks if string could be parse as yaml
|
162
86
|
def is_yaml?(candidate_string)
|
163
87
|
is_yaml = false
|
data/app/models/kaui/catalog.rb
CHANGED
@@ -4,9 +4,35 @@ class Kaui::Catalog < KillBillClient::Model::Catalog
|
|
4
4
|
|
5
5
|
class << self
|
6
6
|
|
7
|
-
def
|
7
|
+
def get_account_catalog_json(account_id, requested_date = nil, options = {})
|
8
|
+
params = {}
|
9
|
+
params[:accountId] = account_id
|
10
|
+
params[:requestedDate] = requested_date if requested_date
|
11
|
+
|
12
|
+
get KillBillClient::Model::Catalog::KILLBILL_API_CATALOG_PREFIX,
|
13
|
+
params,
|
14
|
+
{
|
15
|
+
:head => {'Accept' => "application/json"},
|
16
|
+
:content_type => "application/json",
|
17
|
+
|
18
|
+
}.merge(options)
|
19
|
+
end
|
8
20
|
|
9
|
-
|
21
|
+
def get_tenant_catalog_json(requested_date = nil, options = {})
|
22
|
+
super
|
23
|
+
rescue ::KillBillClient::API::InternalServerError => e
|
24
|
+
if !e.response.nil? && !e.response.body.nil?
|
25
|
+
error_message = JSON.parse(e.response.body) rescue nil
|
26
|
+
raise e if error_message.nil? || error_message['message'].nil?
|
27
|
+
|
28
|
+
# Hack for lack of proper Kill Bill messaging (see https://github.com/killbill/killbill-admin-ui/issues/265)
|
29
|
+
return [] if error_message['message'].starts_with?('No existing versions')
|
30
|
+
end
|
31
|
+
raise e
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_catalog_json(latest, requested_date, options)
|
35
|
+
catalogs = get_tenant_catalog_json(requested_date, options)
|
10
36
|
return catalogs.length > 0 ? catalogs[catalogs.length - 1] : nil if latest
|
11
37
|
|
12
38
|
# Order by latest
|
data/app/models/kaui/tag.rb
CHANGED
@@ -9,7 +9,7 @@ class Kaui::Tag < KillBillClient::Model::Tag
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class << self
|
12
|
-
[:account, :bundle, :subscription].each do |model|
|
12
|
+
[:account, :bundle, :subscription, :invoice].each do |model|
|
13
13
|
define_method "all_for_#{model.to_s}" do |model_id, included_deleted, audit, options|
|
14
14
|
instance = Kaui.const_get(model.to_s.camelize).new("#{model.to_s}_id".to_sym => model_id)
|
15
15
|
instance.tags(included_deleted, audit, options)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class='form-group'>
|
3
3
|
<%= f.label :email, 'Email', :class => 'col-sm-2 control-label' %>
|
4
4
|
<div class="col-sm-10">
|
5
|
-
<%= f.
|
5
|
+
<%= f.email_field :email, :class => 'form-control', :required => true %>
|
6
6
|
</div>
|
7
7
|
</div>
|
8
8
|
<div class="form-group">
|
@@ -25,6 +25,10 @@
|
|
25
25
|
<%= link_to '<i class="fa fa-plus-square"></i> Create charge'.html_safe,
|
26
26
|
kaui_engine.new_account_charge_path(@account.account_id, :currency => @account.currency) %>
|
27
27
|
<% end %>
|
28
|
+
<% if deposit_plugin_available? %>
|
29
|
+
<%= link_to '<i class="fa fa-plus-square"></i> Create deposit'.html_safe,
|
30
|
+
deposit_engine.collection_index_path(:account_id => @account.account_id, :currency => @account.currency) %>
|
31
|
+
<% end %>
|
28
32
|
</div>
|
29
33
|
</div>
|
30
34
|
</div>
|
@@ -38,7 +38,7 @@
|
|
38
38
|
<div class="form-group">
|
39
39
|
<%= f.label :email, 'Email', :class => 'col-sm-3 control-label' %>
|
40
40
|
<div class="col-sm-9">
|
41
|
-
<%= f.
|
41
|
+
<%= f.email_field :email, :class => 'form-control' %>
|
42
42
|
</div>
|
43
43
|
</div>
|
44
44
|
<% unless @account.persisted? %>
|
@@ -7,6 +7,9 @@
|
|
7
7
|
<%= link_to '<i class="fa fa-plus-square"></i>'.html_safe,
|
8
8
|
kaui_engine.new_payment_method_path(:account_id => @account.account_id),
|
9
9
|
:class => 'btn btn-xs' %>
|
10
|
+
<%= form_tag kaui_engine.refresh_payment_methods_path(params.to_h), :method => :post, :class => 'form-force-inline form-right' do %>
|
11
|
+
<%= button_tag '<i class="fa fa-refresh"></i>'.html_safe, :class => 'btn btn-xs' %>
|
12
|
+
<% end %>
|
10
13
|
<% end %>
|
11
14
|
</h1>
|
12
15
|
|
@@ -13,8 +13,9 @@
|
|
13
13
|
<tr>
|
14
14
|
<th></th>
|
15
15
|
<th>ID</th>
|
16
|
-
|
17
|
-
|
16
|
+
<% Kaui.account_search_columns.call()[0].each do |title| %>
|
17
|
+
<th><%= title %></th>
|
18
|
+
<% end %>
|
18
19
|
</tr>
|
19
20
|
</thead>
|
20
21
|
<tbody>
|
@@ -39,8 +40,10 @@ $(document).ready(function() {
|
|
39
40
|
},
|
40
41
|
"pageLength": <%= @limit %>,
|
41
42
|
"displayStart": <%= @offset %>,
|
42
|
-
<%
|
43
|
-
|
43
|
+
<% if @search_query.blank? %>
|
44
|
+
"ordering": false,
|
45
|
+
<% elsif !@ordering.blank? %>
|
46
|
+
"order": [[ 1, "<%= @ordering %>" ]],
|
44
47
|
<% end %>
|
45
48
|
"processing": true,
|
46
49
|
"serverSide": true,
|
@@ -17,9 +17,10 @@
|
|
17
17
|
|
18
18
|
<div id="plugin" class="form-group">
|
19
19
|
<%= label_tag :entered_plugin_name, 'Plugin name', :class => 'col-sm-2 control-label' %>
|
20
|
+
|
20
21
|
<div class="col-sm-4">
|
21
22
|
<select class="form-control" id="select_plugin_name"></select>
|
22
|
-
<%= text_field_tag :entered_plugin_name, nil, :
|
23
|
+
<%= text_field_tag :entered_plugin_name, nil, :placeholder => 'as defined in the plugin Activator file', :class => 'form-control', :tenant_plugin_config => @tenant_plugin_config.to_json %>
|
23
24
|
<div class="text plugin-suggestion text-danger"></div>
|
24
25
|
</div>
|
25
26
|
<div class="col-sm-1 spinner"><i class="fa fa-cog fa-2x fa-spin"></i></div>
|
@@ -29,7 +30,7 @@
|
|
29
30
|
<span class="slider round"></span>
|
30
31
|
</label>
|
31
32
|
</label>
|
32
|
-
<label class="col-sm-3 control-label toggle-label text-muted">
|
33
|
+
<label class="col-sm-3 control-label toggle-label text-muted">manual entry</label>
|
33
34
|
</div>
|
34
35
|
|
35
36
|
<div id="plugin_config_properties_header" class="form-group">
|
@@ -41,8 +42,11 @@
|
|
41
42
|
</label>
|
42
43
|
</label>
|
43
44
|
</div>
|
44
|
-
|
45
|
-
|
45
|
+
<div class="form-group">
|
46
|
+
<%= label_tag :configuration, 'Configuration', :class => 'col-sm-2 control-label' %>
|
47
|
+
<div class="col-sm-6">
|
48
|
+
<textarea name="plugin_properties[raw_config]" id="raw_config" rows="20" class="form-control"></textarea>
|
49
|
+
</div>
|
46
50
|
</div>
|
47
51
|
|
48
52
|
<div class="form-group">
|
@@ -54,23 +58,6 @@
|
|
54
58
|
</div>
|
55
59
|
<% end %>
|
56
60
|
|
57
|
-
<script id="plugin_config_properties_template" type="text/template">
|
58
|
-
<input type="hidden" id="plugin_key_values" value="{{data_json}}" />
|
59
|
-
{{#plugin_props_with_values}}
|
60
|
-
<div class="form-group">
|
61
|
-
<label class="col-sm-offset-1 col-sm-2 control-label" for="{{property}}">{{property_label}}</label>
|
62
|
-
<div class="col-sm-6">
|
63
|
-
{{#is_raw_config}}
|
64
|
-
<textarea name="plugin_properties[raw_config]" id="raw_config" rows="10" class="form-control">{{value}}</textarea>
|
65
|
-
{{/is_raw_config}}
|
66
|
-
{{^is_raw_config}}
|
67
|
-
<input type="text" name="plugin_properties[{{property}}]" id="{{property}}" class="form-control" value="{{value}}" />
|
68
|
-
{{/is_raw_config}}
|
69
|
-
</div>
|
70
|
-
</div>
|
71
|
-
{{/plugin_props_with_values}}
|
72
|
-
</script>
|
73
|
-
|
74
61
|
<script id="plugin_name_options_template" type="text/template">
|
75
62
|
<option></option>
|
76
63
|
{{#plugin_repository}}
|
@@ -101,48 +88,54 @@
|
|
101
88
|
$('#plugin_config_properties').empty();
|
102
89
|
$('#plugin_config_properties_header').hide();
|
103
90
|
$(".plugin-suggestion").html('');
|
91
|
+
$("#raw_config").val('');
|
104
92
|
});
|
105
93
|
|
106
|
-
|
107
|
-
|
108
|
-
|
94
|
+
/* Intercept TAB and potentially display known properties */
|
95
|
+
$('#entered_plugin_name').keydown(function (e) {
|
96
|
+
if (e.keyCode === 9) {
|
97
|
+
$("#plugin_name").val($('#entered_plugin_name').val());
|
98
|
+
$("#plugin_key").val('');
|
99
|
+
render_plugin_key_values();
|
109
100
|
}
|
101
|
+
});
|
102
|
+
/* Intercept mouseleave and potentially display known properties */
|
103
|
+
$('#entered_plugin_name').on('mouseleave', function() {
|
104
|
+
$("#plugin_name").val($('#entered_plugin_name').val());
|
105
|
+
$("#plugin_key").val('');
|
106
|
+
render_plugin_key_values();
|
107
|
+
});
|
110
108
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
var plugin_name = $('#entered_plugin_name').val();
|
117
|
-
var plugin_key = $("#plugin_key").val();
|
118
|
-
var existing_props = get_tenant_plugin_properties(plugin_key, plugin_name);
|
119
|
-
raw[0].value = existing_props['_raw'];
|
120
|
-
|
121
|
-
render_plugin_key_values(raw, plugin_key_values);
|
122
|
-
} else {
|
123
|
-
render_plugin_key_values(plugin_key_values, plugin_key_values);
|
124
|
-
}
|
109
|
+
$("#toggle_raw").on('change', function(e) {
|
110
|
+
$("#plugin_name").val($('#entered_plugin_name').val());
|
111
|
+
$("#plugin_key").val('');
|
112
|
+
render_plugin_key_values();
|
125
113
|
});
|
126
114
|
|
127
115
|
$('#select_plugin_name').on('change', function(e) {
|
116
|
+
// User has selected a plugin from the dropdown
|
128
117
|
var selectedOption = e.target.selectedOptions;
|
129
118
|
|
130
119
|
if (selectedOption.length > 0) {
|
131
120
|
var plugin_name = selectedOption[0].value;
|
132
121
|
var plugin_key = selectedOption[0].text;
|
122
|
+
|
133
123
|
$("#plugin_name").val(plugin_name);
|
134
124
|
$("#plugin_key").val(plugin_key);
|
135
|
-
$("#plugin_type").val(selectedOption[0].dataset['pluginType']);
|
125
|
+
$("#plugin_type").val(selectedOption[0].dataset['pluginType']); // java or ruby
|
136
126
|
$('#plugin_config_properties').attr('plugin_name', '');
|
137
127
|
$('#plugin_config_properties_header').hide();
|
138
128
|
$("#toggle_raw").prop('checked', false);
|
139
|
-
|
129
|
+
|
130
|
+
render_plugin_key_values();
|
140
131
|
}
|
141
132
|
});
|
142
133
|
|
143
134
|
populate_plugin_name_options();
|
144
135
|
function populate_plugin_name_options(){
|
145
|
-
var
|
136
|
+
var all_plugins = JSON.parse($("#plugin_repository").val());
|
137
|
+
// We only list installed plugins as to not confuse the user
|
138
|
+
var plugin_repository = all_plugins.filter(plugin => plugin.installed);
|
146
139
|
for (var idx = 0, size = plugin_repository.length; idx < size; idx++) {
|
147
140
|
if (idx == 0 && plugin_repository[idx].installed) {
|
148
141
|
plugin_repository[idx]['start_installed'] = true;
|
@@ -163,225 +156,50 @@
|
|
163
156
|
}
|
164
157
|
|
165
158
|
var template = $("#plugin_name_options_template").html();
|
166
|
-
var options_html = Mustache.render( template , { plugin_repository: plugin_repository});
|
159
|
+
var options_html = Mustache.render( template , { plugin_repository: plugin_repository });
|
167
160
|
$("#select_plugin_name").html(options_html);
|
168
161
|
}
|
169
162
|
|
170
163
|
function get_existing_tenant_plugin_properties(entered_plugin_name) {
|
171
164
|
var tenant_plugin_properties = $('#entered_plugin_name').attr('tenant_plugin_config');
|
172
|
-
var res =
|
173
|
-
|
174
|
-
$.each(tenant_plugin_properties.split(';'), function(idx, el) {
|
175
|
-
var el_parts = el.split('::');
|
176
|
-
var el_plugin_name = el_parts[0];
|
177
|
-
var el_props = el_parts[1];
|
178
|
-
if (el_plugin_name === entered_plugin_name) {
|
179
|
-
if (el_props.split('=')[0] == 'raw_config') {
|
180
|
-
res['raw_config'] = el_props.replace("raw_config=", "");
|
181
|
-
} else {
|
182
|
-
$.map(el_props.split('|'), function(el) {
|
183
|
-
var parts = el.split('=');
|
184
|
-
res[parts[0]] = parts.slice(1).join('=');
|
185
|
-
});
|
186
|
-
}
|
187
|
-
return false;
|
188
|
-
}
|
189
|
-
});
|
190
|
-
}
|
191
|
-
return res;
|
192
|
-
}
|
193
|
-
|
194
|
-
function get_selected_plugin_info(plugin_key) {
|
195
|
-
var plugin_config_str = $('#entered_plugin_name').attr('plugin_config');
|
196
|
-
var res = {}
|
197
|
-
/* Deserialize plugin/properties (see AdminTenant model)*/
|
198
|
-
$.each(plugin_config_str.split(';'), function(idx, el) {
|
199
|
-
var el_parts = el.split(':');
|
200
|
-
var el_parts_key = el_parts[0].split('#');
|
201
|
-
var el_plugin_name = el_parts_key[0];
|
202
|
-
var el_plugin_type = el_parts_key[1];
|
203
|
-
var el_plugin_props = el_parts[1];
|
204
|
-
if (el_plugin_name == plugin_key) {
|
205
|
-
res['type'] = el_plugin_type;
|
206
|
-
res['props'] = el_plugin_props == "" ? [] : (el_plugin_type == "" ? ['raw_config'] : el_plugin_props.split(','));
|
207
|
-
return false;
|
208
|
-
}
|
209
|
-
});
|
210
|
-
|
211
|
-
if (isBlank(res['props'])) {
|
212
|
-
res['type'] = '';
|
213
|
-
res['props'] = ['raw_config'];
|
214
|
-
}
|
215
|
-
|
216
|
-
return res;
|
165
|
+
var res = JSON.parse(tenant_plugin_properties);
|
166
|
+
return res[entered_plugin_name];
|
217
167
|
}
|
218
168
|
|
219
169
|
function get_tenant_plugin_properties(plugin_key, plugin_name) {
|
220
170
|
/* Retrieve existing plugin properties for this tenant */
|
221
171
|
var existing_props = get_existing_tenant_plugin_properties(plugin_key);
|
222
172
|
|
223
|
-
//
|
224
|
-
if (isBlank(existing_props)) {
|
173
|
+
// Try by plugin name for proprietary plugins
|
174
|
+
if (isBlank(existing_props) && !isBlank(plugin_name)) {
|
225
175
|
existing_props = get_existing_tenant_plugin_properties(plugin_name);
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
if (isBlank(plugin_name)) {
|
235
|
-
$('#plugin_config_properties').empty();
|
236
|
-
$('#plugin_config_properties').attr('plugin_name', '');
|
237
|
-
return;
|
238
|
-
}
|
239
|
-
|
240
|
-
if ($('#plugin_config_properties').attr('plugin_name') == plugin_name) {
|
241
|
-
/* Already set...*/
|
242
|
-
return;
|
243
|
-
}
|
244
|
-
|
245
|
-
var existing_props = get_tenant_plugin_properties(plugin_key, plugin_name);
|
246
|
-
|
247
|
-
var type = plugin_info['type'];
|
248
|
-
var props = plugin_info['props']
|
249
|
-
|
250
|
-
if (isBlank(type)) {
|
251
|
-
$(".switch-half-container").hide();
|
252
|
-
} else {
|
253
|
-
$(".switch-half-container").show();
|
254
|
-
}
|
255
|
-
|
256
|
-
$('#plugin_type').val(type);
|
257
|
-
/* Prune the tree to restart from scratch */
|
258
|
-
$('#plugin_config_properties_header').show();
|
259
|
-
$('#plugin_config_properties').empty();
|
260
|
-
$('#plugin_config_properties').append('<div id="plugin_config_properties_anchor" class="col-sm-12"></div>');
|
261
|
-
|
262
|
-
var merged_props_with_values = existing_props;
|
263
|
-
if (props != undefined) {
|
264
|
-
$.each(props, function(idx, p) {
|
265
|
-
if (merged_props_with_values[p] == undefined) {
|
266
|
-
merged_props_with_values[p] = '';
|
176
|
+
if (isBlank(existing_props)) {
|
177
|
+
// For proprietary plugins, the killbill- prefix likely doesn't exist (see Kaui::PluginHelper discussion)
|
178
|
+
plugin_name = plugin_name.replace('killbill-', '');
|
179
|
+
existing_props = get_existing_tenant_plugin_properties(plugin_name);
|
180
|
+
if (isBlank(existing_props)) {
|
181
|
+
// For proprietary plugins, our docs suggest acme:foo as the format for the plugin key, and often the plugin name becomes acme-foo
|
182
|
+
plugin_name = plugin_name.replace(':', '-');
|
183
|
+
existing_props = get_existing_tenant_plugin_properties(plugin_name);
|
267
184
|
}
|
268
|
-
});
|
269
|
-
}
|
270
|
-
|
271
|
-
add_property_form_entry(merged_props_with_values);
|
272
|
-
|
273
|
-
$('#plugin_config_properties').attr('plugin_name', plugin_name);
|
274
|
-
}
|
275
|
-
|
276
|
-
function format_label(input) {
|
277
|
-
/* Keep latest piece of a system property to keep it short */
|
278
|
-
var label_name = input.split('.').pop();
|
279
|
-
/* Replace underscore with comma */
|
280
|
-
label_name = label_name.replace(/_/g, ',');
|
281
|
-
/* Replace uppercase with comma + uppercase */
|
282
|
-
label_name = label_name.replace(/([A-Z]+)/g, ",$1");
|
283
|
-
/* Split name make sure each word starts with Uppercase */
|
284
|
-
var tmp1 = label_name.split(',');
|
285
|
-
var label_name_array = [];
|
286
|
-
$.map(tmp1, function(el) { label_name_array.push(el.charAt(0).toUpperCase() + el.slice(1)) });
|
287
|
-
label_name = label_name_array.join(' ');
|
288
|
-
return label_name;
|
289
|
-
}
|
290
|
-
|
291
|
-
function add_property_form_entry(merged_props_with_values) {
|
292
|
-
var plugin_props_with_values = [];
|
293
|
-
|
294
|
-
$.each(merged_props_with_values, function(p, v) {
|
295
|
-
if (p != '_raw') {
|
296
|
-
plugin_props_with_values.push({ property_label: format_label(p), property: p, value: v, is_raw_config: p == 'raw_config'});
|
297
|
-
}
|
298
|
-
});
|
299
|
-
|
300
|
-
render_plugin_key_values(plugin_props_with_values, plugin_props_with_values);
|
301
|
-
}
|
302
|
-
|
303
|
-
function render_plugin_key_values(plugin_props_with_values, original) {
|
304
|
-
var template = $("#plugin_config_properties_template").html();
|
305
|
-
var plugin_props_with_values_html = Mustache.render( template ,{ plugin_props_with_values: plugin_props_with_values,
|
306
|
-
data_json: JSON.stringify(original)});
|
307
|
-
$("#plugin_config_properties_anchor").html(plugin_props_with_values_html);
|
308
|
-
}
|
309
|
-
|
310
|
-
// Free text related functions and handlers
|
311
|
-
init_plugin_name_handlers();
|
312
|
-
function init_plugin_name_handlers() {
|
313
|
-
/* Intercept ENTER and potentially display property form if plugin is know */
|
314
|
-
$('#entered_plugin_name').keyup(function (e) {
|
315
|
-
e.preventDefault();
|
316
|
-
if (e.keyCode === 13) {
|
317
|
-
suggest_plugin_name();
|
318
185
|
}
|
319
|
-
});
|
320
|
-
|
321
|
-
/* Intercept mouseleave and potentially display property form if plugin is know */
|
322
|
-
$('#entered_plugin_name').on('mouseleave', function() {
|
323
|
-
suggest_plugin_name();
|
324
|
-
});
|
325
|
-
}
|
326
|
-
|
327
|
-
function suggested_response(response) {
|
328
|
-
$(".spinner").hide();
|
329
|
-
if (!isBlank(response.suggestion)) {
|
330
|
-
$(".plugin-suggestion").html(response.suggestion);
|
331
|
-
|
332
|
-
$("#suggested").click(function(e) {
|
333
|
-
var plugin_name = e.currentTarget.dataset['pluginName'];
|
334
|
-
var plugin_key = e.currentTarget.dataset['pluginKey'];
|
335
|
-
|
336
|
-
$("#entered_plugin_name").val(plugin_name);
|
337
|
-
$("#plugin_key").val(plugin_key);
|
338
|
-
$("#plugin_type").val(e.currentTarget.dataset['pluginType']);
|
339
|
-
$("#entered_plugin_name").data("last", plugin_name);
|
340
|
-
|
341
|
-
$(".plugin-suggestion").html('');
|
342
|
-
add_properties_for_plugin(isBlank(plugin_key) ? plugin_name : plugin_key, plugin_name);
|
343
|
-
});
|
344
|
-
|
345
|
-
} else {
|
346
|
-
$(".plugin-suggestion").html('');
|
347
186
|
}
|
348
187
|
|
349
|
-
|
350
|
-
var plugin_key = $("#plugin_key").val();
|
351
|
-
$("#plugin_name").val(plugin_name);
|
352
|
-
|
353
|
-
add_properties_for_plugin(isBlank(plugin_key) ? plugin_name : plugin_key, plugin_name);
|
188
|
+
return existing_props;
|
354
189
|
}
|
355
190
|
|
356
|
-
function
|
357
|
-
var plugin_name =
|
358
|
-
var
|
359
|
-
$(
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
// no change
|
366
|
-
if ( plugin_name == last_plugin_name) {
|
367
|
-
return;
|
191
|
+
function render_plugin_key_values() {
|
192
|
+
var plugin_name = "";
|
193
|
+
var plugin_key = "";
|
194
|
+
if (isBlank($('#entered_plugin_name').val())) {
|
195
|
+
plugin_name = $("#plugin_name").val();
|
196
|
+
plugin_key = $("#plugin_key").val();
|
197
|
+
} else {
|
198
|
+
plugin_name = $("#entered_plugin_name").val();
|
368
199
|
}
|
369
200
|
|
370
|
-
|
371
|
-
$(
|
372
|
-
$(".plugin-suggestion").html('');
|
373
|
-
$("#entered_plugin_name").data("last", plugin_name);
|
374
|
-
$(".spinner").show();
|
375
|
-
$.ajax({
|
376
|
-
url: '<%= suggest_plugin_name_path() %>',
|
377
|
-
type: "GET",
|
378
|
-
dataType: "json",
|
379
|
-
data: {
|
380
|
-
"plugin_name": plugin_name,
|
381
|
-
},
|
382
|
-
success: suggested_response
|
383
|
-
});
|
201
|
+
var existing_props = get_tenant_plugin_properties(plugin_key, plugin_name);
|
202
|
+
$("#raw_config").val(existing_props);
|
384
203
|
}
|
385
|
-
|
386
204
|
});
|
387
|
-
<% end %>
|
205
|
+
<% end %>
|