Files
sure/app/views/settings/hostings/_twelve_data_settings.html.erb
MkDev11 eeff4edbea Add warning for TwelveData plan-restricted tickers (#803)
* Add warning for TwelveData plan-restricted tickers

Fixes #800

- Add Security::PlanRestrictionTracker concern using Rails cache
- Detect plan upgrade errors during Security::Price::Importer sync
- Display amber warning on /settings/hosting with affected tickers
- Include unit tests for the new functionality

* Scope plan restriction cache by provider

Addresses review feedback:
- Cache key now includes provider name to support multiple data providers
- Methods now require provider parameter for proper scoping
- Added tests for provider-scoped restrictions
- Added documentation explaining instance-level API key architecture

* Fix RuboCop array bracket spacing

* Fix empty array bracket spacing

* Move plan upgrade detection to Provider::TwelveData

* Fix provider scoping tests to use direct cache writes

---------

Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com>
2026-01-27 15:45:50 +01:00

94 lines
4.3 KiB
Plaintext

<div class="space-y-4">
<div>
<h2 class="font-medium mb-1"><%= t(".title") %></h2>
<% if ENV["TWELVE_DATA_API_KEY"].present? %>
<p class="text-sm text-secondary"><%= t(".env_configured_message") %></p>
<% else %>
<div class="text-secondary text-sm mb-4">
<span><%= t(".description") %></span>
<details class="inline">
<summary class="cursor-pointer font-medium text-secondary underline inline"> (show details)</summary>
<ol class="text-sm text-secondary mt-2 list-decimal ml-6 space-y-2">
<li>
Visit <a href="https://twelvedata.com/register" target="_blank" rel="noopener noreferrer" class="underline">twelvedata.com</a> and create a free Twelve Data Developer account.
</li>
<li>
Go to the <a href="https://twelvedata.com/account/api-keys" target="_blank" rel="noopener noreferrer" class="underline">API Keys</a> page.
</li>
<li>
Reveal your <strong>Secret Key</strong> and paste it below.
</li>
</ol>
</details>
</div>
<% end %>
</div>
<%= styled_form_with model: Setting.new,
url: settings_hosting_path,
method: :patch,
data: {
controller: "auto-submit-form",
"auto-submit-form-trigger-event-value": "blur"
} do |form| %>
<%= form.text_field :twelve_data_api_key,
label: t(".label"),
type: "password",
placeholder: t(".placeholder"),
value: ENV.fetch("TWELVE_DATA_API_KEY", Setting.twelve_data_api_key),
disabled: ENV["TWELVE_DATA_API_KEY"].present?,
container_class: @twelve_data_usage.present? && !@twelve_data_usage.success? ? "border-red-500" : "",
data: { "auto-submit-form-target": "auto" } %>
<% end %>
<% if @twelve_data_usage.present? && @twelve_data_usage.success? %>
<div class="space-y-4">
<div class="space-y-2">
<p class="text-sm text-secondary">
<%= t(".api_calls_used",
used: number_with_delimiter(@twelve_data_usage.data.used),
limit: number_with_delimiter(@twelve_data_usage.data.limit),
percentage: number_to_percentage(@twelve_data_usage.data.utilization, precision: 1)) %>
</p>
<div class="w-52 h-1.5 bg-gray-100 rounded-2xl">
<div class="h-full bg-green-500 rounded-2xl"
style="width: <%= [@twelve_data_usage.data.utilization, 2].max %>%;"></div>
</div>
</div>
<div class="bg-gray-100 rounded-md px-1.5 py-0.5 w-fit">
<p class="text-xs font-medium text-secondary uppercase">
<%= t(".plan", plan: @twelve_data_usage.data.plan) %>
</p>
</div>
<% if @plan_restricted_securities.present? %>
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3 mt-4">
<div class="flex items-start gap-2">
<%= icon("alert-triangle", size: "sm", class: "text-amber-600 mt-0.5") %>
<div class="text-sm">
<p class="font-medium text-amber-800"><%= t(".plan_upgrade_warning_title") %></p>
<p class="text-amber-700 mt-1"><%= t(".plan_upgrade_warning_description") %></p>
<ul class="mt-2 space-y-1">
<% @plan_restricted_securities.each do |security| %>
<li class="text-amber-700">
<span class="font-medium"><%= security[:ticker] %></span>
<% if security[:name].present? %>
<span class="text-amber-600">(<%= security[:name] %>)</span>
<% end %>
<span class="text-amber-600">— <%= t(".requires_plan", plan: security[:required_plan]) %></span>
</li>
<% end %>
</ul>
<p class="mt-2">
<a href="https://twelvedata.com/pricing" target="_blank" rel="noopener noreferrer" class="text-amber-800 underline font-medium">
<%= t(".view_pricing") %>
</a>
</p>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>