mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-19 21:05:15 +00:00
UI tweak (#996)
This commit is contained in:
parent
64849e2656
commit
1a28bc744a
1 changed files with 306 additions and 330 deletions
|
|
@ -325,370 +325,346 @@
|
|||
</section>
|
||||
|
||||
{#if ui.show_imports_and_mirrors}
|
||||
<section
|
||||
id="imports_and_mirrors"
|
||||
class="rounded-md border border-surface-200 bg-darker p-4 sm:p-5"
|
||||
>
|
||||
<h2 class="text-xl font-semibold text-surface-content">
|
||||
Imports & Mirrors
|
||||
</h2>
|
||||
<p class="mt-1 text-sm text-muted">
|
||||
Connect WakaTime-compatible sources and destinations.
|
||||
</p>
|
||||
<div class="mt-4 space-y-7">
|
||||
<section id="wakatime_import_source">
|
||||
<h3 class="text-lg font-semibold text-surface-content">
|
||||
Import from WakaTime
|
||||
</h3>
|
||||
|
||||
<div class="mt-4 space-y-7">
|
||||
<section id="wakatime_import_source">
|
||||
<h3 class="text-lg font-semibold text-surface-content">
|
||||
Import from WakaTime
|
||||
</h3>
|
||||
{#if importSource}
|
||||
<div
|
||||
class="mt-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<p class="text-sm text-surface-content">
|
||||
Status: <span class="font-semibold">{importSource.status}</span>
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Last synced: {importSource.last_synced_ago || "Never"}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Imported: {importSource.imported_count.toLocaleString()}
|
||||
</p>
|
||||
{#if importSource.last_error_message}
|
||||
<p class="mt-1 text-xs text-red-300">
|
||||
Last error: {importSource.last_error_message}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_path}
|
||||
class="mt-3 space-y-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<input type="hidden" name="authenticity_token" value={csrfToken} />
|
||||
{#if importSource}
|
||||
<div
|
||||
class="mt-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<p class="text-sm text-surface-content">
|
||||
Status: <span class="font-semibold"
|
||||
>{importSource.status}</span
|
||||
>
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Last synced: {importSource.last_synced_ago || "Never"}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Imported: {importSource.imported_count.toLocaleString()}
|
||||
</p>
|
||||
{#if importSource.last_error_message}
|
||||
<p class="mt-1 text-xs text-red-300">
|
||||
Last error: {importSource.last_error_message}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
<input type="hidden" name="_method" value="patch" />
|
||||
{/if}
|
||||
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_path}
|
||||
class="mt-3 space-y-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
for="import_endpoint_url"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Endpoint URL
|
||||
</label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
id="import_endpoint_url"
|
||||
type="url"
|
||||
name="heartbeat_import_source[endpoint_url]"
|
||||
required
|
||||
value={importSource?.endpoint_url ||
|
||||
"https://wakatime.com/api/v1"}
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="import_api_key"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
API Key
|
||||
</label>
|
||||
<input
|
||||
id="import_api_key"
|
||||
type="password"
|
||||
name="heartbeat_import_source[encrypted_api_key]"
|
||||
required={!importSource}
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
{#if importSource}
|
||||
<input type="hidden" name="_method" value="patch" />
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="import_endpoint_url"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Endpoint URL
|
||||
</label>
|
||||
<input
|
||||
id="import_endpoint_url"
|
||||
type="url"
|
||||
name="heartbeat_import_source[endpoint_url]"
|
||||
required
|
||||
value={importSource?.endpoint_url ||
|
||||
"https://wakatime.com/api/v1"}
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="import_api_key"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
API Key
|
||||
</label>
|
||||
<input
|
||||
id="import_api_key"
|
||||
type="password"
|
||||
name="heartbeat_import_source[encrypted_api_key]"
|
||||
required={!importSource}
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
{#if importSource}
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Leave blank to keep the existing key.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="rounded-md border border-surface-200 bg-darker p-3">
|
||||
<p class="text-sm font-semibold text-surface-content">
|
||||
Backfill scope
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Leave blank to keep the existing key.
|
||||
</p>
|
||||
<div class="mt-2 flex flex-wrap items-center gap-4">
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="backfill_mode"
|
||||
value="all_time"
|
||||
checked={backfillMode === "all_time"}
|
||||
onchange={() => {
|
||||
backfillMode = "all_time";
|
||||
importStartDate = "";
|
||||
importEndDate = "";
|
||||
}}
|
||||
class="peer sr-only"
|
||||
/>
|
||||
<span
|
||||
class="h-4 w-4 rounded-full border border-surface-200 bg-surface ring-offset-2 ring-offset-surface transition peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40"
|
||||
></span>
|
||||
All time
|
||||
</label>
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="backfill_mode"
|
||||
value="date_range"
|
||||
checked={backfillMode === "date_range"}
|
||||
onchange={() => {
|
||||
backfillMode = "date_range";
|
||||
}}
|
||||
class="peer sr-only"
|
||||
/>
|
||||
<span
|
||||
class="h-4 w-4 rounded-full border border-surface-200 bg-surface ring-offset-2 ring-offset-surface transition peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40"
|
||||
></span>
|
||||
Specific date range
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if backfillMode === "all_time"}
|
||||
<div class="rounded-md border border-surface-200 bg-darker p-3">
|
||||
<p class="text-sm font-semibold text-surface-content">
|
||||
Backfill scope
|
||||
</p>
|
||||
<div class="mt-2 flex flex-wrap items-center gap-4">
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="heartbeat_import_source[initial_backfill_start_date]"
|
||||
value=""
|
||||
type="radio"
|
||||
name="backfill_mode"
|
||||
value="all_time"
|
||||
checked={backfillMode === "all_time"}
|
||||
onchange={() => {
|
||||
backfillMode = "all_time";
|
||||
importStartDate = "";
|
||||
importEndDate = "";
|
||||
}}
|
||||
class="peer sr-only"
|
||||
/>
|
||||
<span
|
||||
class="h-4 w-4 rounded-full border border-surface-200 bg-surface ring-offset-2 ring-offset-surface transition peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40"
|
||||
></span>
|
||||
All time
|
||||
</label>
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="heartbeat_import_source[initial_backfill_end_date]"
|
||||
value=""
|
||||
type="radio"
|
||||
name="backfill_mode"
|
||||
value="date_range"
|
||||
checked={backfillMode === "date_range"}
|
||||
onchange={() => {
|
||||
backfillMode = "date_range";
|
||||
}}
|
||||
class="peer sr-only"
|
||||
/>
|
||||
{:else}
|
||||
<div class="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
<div>
|
||||
<label
|
||||
for="import_start_date"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Start date
|
||||
</label>
|
||||
<input
|
||||
id="import_start_date"
|
||||
type="date"
|
||||
name="heartbeat_import_source[initial_backfill_start_date]"
|
||||
bind:value={importStartDate}
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-surface px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="import_end_date"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
End date
|
||||
</label>
|
||||
<input
|
||||
id="import_end_date"
|
||||
type="date"
|
||||
name="heartbeat_import_source[initial_backfill_end_date]"
|
||||
bind:value={importEndDate}
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-surface px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<span
|
||||
class="h-4 w-4 rounded-full border border-surface-200 bg-surface ring-offset-2 ring-offset-surface transition peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40"
|
||||
></span>
|
||||
Specific date range
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
{#if backfillMode === "all_time"}
|
||||
<input
|
||||
type="hidden"
|
||||
name="heartbeat_import_source[sync_enabled]"
|
||||
value="0"
|
||||
name="heartbeat_import_source[initial_backfill_start_date]"
|
||||
value=""
|
||||
/>
|
||||
<input
|
||||
type="hidden"
|
||||
name="heartbeat_import_source[initial_backfill_end_date]"
|
||||
value=""
|
||||
/>
|
||||
{:else}
|
||||
<div class="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
<div>
|
||||
<label
|
||||
for="import_start_date"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Start date
|
||||
</label>
|
||||
<input
|
||||
id="import_start_date"
|
||||
type="date"
|
||||
name="heartbeat_import_source[initial_backfill_start_date]"
|
||||
bind:value={importStartDate}
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-surface px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="import_end_date"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
End date
|
||||
</label>
|
||||
<input
|
||||
id="import_end_date"
|
||||
type="date"
|
||||
name="heartbeat_import_source[initial_backfill_end_date]"
|
||||
bind:value={importEndDate}
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-surface px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<input
|
||||
type="hidden"
|
||||
name="heartbeat_import_source[sync_enabled]"
|
||||
value="0"
|
||||
/>
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="heartbeat_import_source[sync_enabled]"
|
||||
value="1"
|
||||
checked={importSource ? importSource.sync_enabled : true}
|
||||
class="h-4 w-4 rounded border-surface-200 bg-surface text-primary"
|
||||
/>
|
||||
Continuous sync enabled
|
||||
</label>
|
||||
{#if importSource}
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="heartbeat_import_source[sync_enabled]"
|
||||
name="heartbeat_import_source[rerun_backfill]"
|
||||
value="1"
|
||||
checked={importSource ? importSource.sync_enabled : true}
|
||||
class="h-4 w-4 rounded border-surface-200 bg-surface text-primary"
|
||||
/>
|
||||
Continuous sync enabled
|
||||
Re-run backfill
|
||||
</label>
|
||||
{#if importSource}
|
||||
<label
|
||||
class="inline-flex items-center gap-2 text-sm text-surface-content"
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<Button type="submit" variant="primary">
|
||||
{importSource ? "Update source" : "Create source"}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#if importSource}
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_sync_path}
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
<Button type="submit" variant="surface">Sync now</Button>
|
||||
</form>
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_path}
|
||||
onsubmit={(event) => {
|
||||
if (!window.confirm("Remove import source configuration?")) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
<Button type="submit" variant="surface">Remove source</Button>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section id="wakatime_mirror">
|
||||
<h3 class="text-lg font-semibold text-surface-content">
|
||||
Mirror to WakaTime
|
||||
</h3>
|
||||
|
||||
{#if mirrors.length > 0}
|
||||
<div class="mt-3 space-y-2">
|
||||
{#each mirrors as mirror}
|
||||
<div
|
||||
class="rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<p class="text-sm font-semibold text-surface-content">
|
||||
{mirror.endpoint_url}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Status: {mirror.enabled ? "enabled" : "paused"}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Last synced: {mirror.last_synced_ago}
|
||||
</p>
|
||||
{#if mirror.last_error_message}
|
||||
<p class="mt-1 text-xs text-red-300">
|
||||
Last error: {mirror.last_error_message}
|
||||
</p>
|
||||
{/if}
|
||||
{#if mirror.consecutive_failures && mirror.consecutive_failures > 0}
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Consecutive failures: {mirror.consecutive_failures}
|
||||
</p>
|
||||
{/if}
|
||||
<form
|
||||
method="post"
|
||||
action={mirror.destroy_path}
|
||||
class="mt-3"
|
||||
onsubmit={(event) => {
|
||||
if (!window.confirm("Delete this mirror endpoint?")) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="heartbeat_import_source[rerun_backfill]"
|
||||
value="1"
|
||||
class="h-4 w-4 rounded border-surface-200 bg-surface text-primary"
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
Re-run backfill
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
<Button type="submit" variant="surface" size="xs">
|
||||
Delete mirror
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<Button type="submit" variant="primary">
|
||||
{importSource ? "Update source" : "Create source"}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#if importSource}
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_sync_path}
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
<Button type="submit" variant="surface">Sync now</Button>
|
||||
</form>
|
||||
<form
|
||||
method="post"
|
||||
action={paths.heartbeat_import_source_path}
|
||||
onsubmit={(event) => {
|
||||
if (
|
||||
!window.confirm("Remove import source configuration?")
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
<Button type="submit" variant="surface">Remove source</Button>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section id="wakatime_mirror">
|
||||
<h3 class="text-lg font-semibold text-surface-content">
|
||||
Mirror to WakaTime
|
||||
</h3>
|
||||
|
||||
{#if mirrors.length > 0}
|
||||
<div class="mt-3 space-y-2">
|
||||
{#each mirrors as mirror}
|
||||
<div
|
||||
class="rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<p class="text-sm font-semibold text-surface-content">
|
||||
{mirror.endpoint_url}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Status: {mirror.enabled ? "enabled" : "paused"}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Last synced: {mirror.last_synced_ago}
|
||||
</p>
|
||||
{#if mirror.last_error_message}
|
||||
<p class="mt-1 text-xs text-red-300">
|
||||
Last error: {mirror.last_error_message}
|
||||
</p>
|
||||
{/if}
|
||||
{#if mirror.consecutive_failures && mirror.consecutive_failures > 0}
|
||||
<p class="mt-1 text-xs text-muted">
|
||||
Consecutive failures: {mirror.consecutive_failures}
|
||||
</p>
|
||||
{/if}
|
||||
<form
|
||||
method="post"
|
||||
action={mirror.destroy_path}
|
||||
class="mt-3"
|
||||
onsubmit={(event) => {
|
||||
if (!window.confirm("Delete this mirror endpoint?")) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
/>
|
||||
<Button type="submit" variant="surface" size="xs">
|
||||
Delete mirror
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form
|
||||
method="post"
|
||||
action={paths.user_wakatime_mirrors_path}
|
||||
class="mt-3 space-y-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<form
|
||||
method="post"
|
||||
action={paths.user_wakatime_mirrors_path}
|
||||
class="mt-3 space-y-3 rounded-md border border-surface-200 bg-surface p-3"
|
||||
>
|
||||
<input type="hidden" name="authenticity_token" value={csrfToken} />
|
||||
<div>
|
||||
<label
|
||||
for="mirror_endpoint_url"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Endpoint URL
|
||||
</label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
value={csrfToken}
|
||||
id="mirror_endpoint_url"
|
||||
type="url"
|
||||
name="wakatime_mirror[endpoint_url]"
|
||||
value="https://wakatime.com/api/v1"
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
for="mirror_endpoint_url"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
Endpoint URL
|
||||
</label>
|
||||
<input
|
||||
id="mirror_endpoint_url"
|
||||
type="url"
|
||||
name="wakatime_mirror[endpoint_url]"
|
||||
value="https://wakatime.com/api/v1"
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="mirror_key"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
WakaTime API Key
|
||||
</label>
|
||||
<input
|
||||
id="mirror_key"
|
||||
type="password"
|
||||
name="wakatime_mirror[encrypted_api_key]"
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" variant="primary">Add mirror</Button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="mirror_key"
|
||||
class="mb-2 block text-sm text-surface-content"
|
||||
>
|
||||
WakaTime API Key
|
||||
</label>
|
||||
<input
|
||||
id="mirror_key"
|
||||
type="password"
|
||||
name="wakatime_mirror[encrypted_api_key]"
|
||||
required
|
||||
class="w-full rounded-md border border-surface-200 bg-darker px-3 py-2 text-sm text-surface-content focus:border-primary focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" variant="primary">Add mirror</Button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section id="download_user_data">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue