ready for test
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
|
||||
const DEFAULT_LLM_PROMPTS = {
|
||||
dashboard_validation_prompt:
|
||||
"Analyze the attached dashboard screenshot and the following execution logs for health and visual issues.\\n\\nLogs:\\n{logs}\\n\\nProvide the analysis in JSON format with the following structure:\\n{\\n \\\"status\\\": \\\"PASS\\\" | \\\"WARN\\\" | \\\"FAIL\\\",\\n \\\"summary\\\": \\\"Short summary of findings\\\",\\n \\\"issues\\\": [\\n {\\n \\\"severity\\\": \\\"WARN\\\" | \\\"FAIL\\\",\\n \\\"message\\\": \\\"Description of the issue\\\",\\n \\\"location\\\": \\\"Optional location info (e.g. chart name)\\\"\\n }\\n ]\\n}",
|
||||
'Analyze the attached dashboard screenshot and the following execution logs for health and visual issues.\\n\\nLogs:\\n{logs}\\n\\nProvide the analysis in JSON format with the following structure:\\n{\\n \\"status\\": \\"PASS\\" | \\"WARN\\" | \\"FAIL\\",\\n \\"summary\\": \\"Short summary of findings\\",\\n \\"issues\\": [\\n {\\n \\"severity\\": \\"WARN\\" | \\"FAIL\\",\\n \\"message\\": \\"Description of the issue\\",\\n \\"location\\": \\"Optional location info (e.g. chart name)\\"\\n }\\n ]\\n}',
|
||||
documentation_prompt:
|
||||
"Generate professional documentation for the following dataset and its columns.\\nDataset: {dataset_name}\\nColumns: {columns_json}\\n\\nProvide the documentation in JSON format:\\n{\\n \\\"dataset_description\\\": \\\"General description of the dataset\\\",\\n \\\"column_descriptions\\\": [\\n {\\n \\\"name\\\": \\\"column_name\\\",\\n \\\"description\\\": \\\"Generated description\\\"\\n }\\n ]\\n}",
|
||||
'Generate professional documentation for the following dataset and its columns.\\nDataset: {dataset_name}\\nColumns: {columns_json}\\n\\nProvide the documentation in JSON format:\\n{\\n \\"dataset_description\\": \\"General description of the dataset\\",\\n \\"column_descriptions\\": [\\n {\\n \\"name\\": \\"column_name\\",\\n \\"description\\": \\"Generated description\\"\\n }\\n ]\\n}',
|
||||
git_commit_prompt:
|
||||
"Generate a concise and professional git commit message based on the following diff and recent history.\\nUse Conventional Commits format (e.g., feat: ..., fix: ..., docs: ...).\\n\\nRecent History:\\n{history}\\n\\nDiff:\\n{diff}\\n\\nCommit Message:",
|
||||
};
|
||||
@@ -59,6 +59,7 @@
|
||||
// Load settings on mount
|
||||
onMount(async () => {
|
||||
await loadSettings();
|
||||
await loadMigrationSettings();
|
||||
});
|
||||
|
||||
// Load consolidated settings from API
|
||||
@@ -95,7 +96,8 @@
|
||||
...DEFAULT_LLM_PROVIDER_BINDINGS,
|
||||
...(llm?.provider_bindings || {}),
|
||||
};
|
||||
normalized.assistant_planner_provider = llm?.assistant_planner_provider || "";
|
||||
normalized.assistant_planner_provider =
|
||||
llm?.assistant_planner_provider || "";
|
||||
normalized.assistant_planner_model = llm?.assistant_planner_model || "";
|
||||
return normalized;
|
||||
}
|
||||
@@ -116,7 +118,9 @@
|
||||
|
||||
function getProviderById(providerId) {
|
||||
if (!providerId) return null;
|
||||
return (settings?.llm_providers || []).find((p) => p.id === providerId) || null;
|
||||
return (
|
||||
(settings?.llm_providers || []).find((p) => p.id === providerId) || null
|
||||
);
|
||||
}
|
||||
|
||||
function isDashboardValidationBindingValid() {
|
||||
@@ -129,6 +133,9 @@
|
||||
// Handle tab change
|
||||
function handleTabChange(tab) {
|
||||
activeTab = tab;
|
||||
if (tab === "migration") {
|
||||
loadMigrationSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// Get tab class
|
||||
@@ -138,6 +145,44 @@
|
||||
: "text-gray-600 hover:text-gray-800 border-transparent hover:border-gray-300";
|
||||
}
|
||||
|
||||
// Migration Settings State
|
||||
let migrationCron = "0 2 * * *";
|
||||
let displayMappings = [];
|
||||
let isSavingMigration = false;
|
||||
let isLoadingMigration = false;
|
||||
|
||||
async function loadMigrationSettings() {
|
||||
isLoadingMigration = true;
|
||||
try {
|
||||
const settingsRes = await api.requestApi("/migration/settings");
|
||||
migrationCron = settingsRes.cron;
|
||||
const mappingsRes = await api.requestApi("/migration/mappings-data");
|
||||
displayMappings = mappingsRes;
|
||||
} catch (err) {
|
||||
console.error("[SettingsPage][Migration] Failed to load:", err);
|
||||
} finally {
|
||||
isLoadingMigration = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function saveMigrationSettings() {
|
||||
isSavingMigration = true;
|
||||
try {
|
||||
await api.putApi("/migration/settings", { cron: migrationCron });
|
||||
addToast(
|
||||
$t.settings?.save_success || "Migration settings saved",
|
||||
"success",
|
||||
);
|
||||
} catch (err) {
|
||||
addToast(
|
||||
$t.settings?.save_failed || "Failed to save migration settings",
|
||||
"error",
|
||||
);
|
||||
} finally {
|
||||
isSavingMigration = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle global settings save (Logging, Storage)
|
||||
async function handleSave() {
|
||||
console.log("[SettingsPage][Action] Saving settings");
|
||||
@@ -327,6 +372,14 @@
|
||||
>
|
||||
{$t.settings?.llm || "LLM"}
|
||||
</button>
|
||||
<button
|
||||
class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none {getTabClass(
|
||||
'migration',
|
||||
)}"
|
||||
on:click={() => handleTabChange("migration")}
|
||||
>
|
||||
Migration Sync
|
||||
</button>
|
||||
<button
|
||||
class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none {getTabClass(
|
||||
'storage',
|
||||
@@ -712,7 +765,8 @@
|
||||
|
||||
<div class="mt-6 rounded-lg border border-gray-200 bg-white p-4">
|
||||
<h3 class="text-base font-semibold text-gray-900">
|
||||
{$t.settings?.llm_chatbot_settings_title || "Chatbot Planner Settings"}
|
||||
{$t.settings?.llm_chatbot_settings_title ||
|
||||
"Chatbot Planner Settings"}
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-gray-600">
|
||||
{$t.settings?.llm_chatbot_settings_description ||
|
||||
@@ -721,7 +775,10 @@
|
||||
|
||||
<div class="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label for="planner-provider" class="block text-sm font-medium text-gray-700">
|
||||
<label
|
||||
for="planner-provider"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_chatbot_provider || "Chatbot Provider"}
|
||||
</label>
|
||||
<select
|
||||
@@ -729,7 +786,9 @@
|
||||
bind:value={settings.llm.assistant_planner_provider}
|
||||
class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
|
||||
>
|
||||
<option value="">{$t.dashboard?.use_default || "Use Default"}</option>
|
||||
<option value=""
|
||||
>{$t.dashboard?.use_default || "Use Default"}</option
|
||||
>
|
||||
{#each settings.llm_providers || [] as provider}
|
||||
<option value={provider.id}>
|
||||
{provider.name} ({provider.default_model})
|
||||
@@ -739,14 +798,18 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="planner-model" class="block text-sm font-medium text-gray-700">
|
||||
<label
|
||||
for="planner-model"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_chatbot_model || "Chatbot Model Override"}
|
||||
</label>
|
||||
<input
|
||||
id="planner-model"
|
||||
type="text"
|
||||
bind:value={settings.llm.assistant_planner_model}
|
||||
placeholder={$t.settings?.llm_chatbot_model_placeholder || "Optional, e.g. gpt-4.1-mini"}
|
||||
placeholder={$t.settings?.llm_chatbot_model_placeholder ||
|
||||
"Optional, e.g. gpt-4.1-mini"}
|
||||
class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
@@ -755,7 +818,8 @@
|
||||
|
||||
<div class="mt-6 rounded-lg border border-gray-200 bg-white p-4">
|
||||
<h3 class="text-base font-semibold text-gray-900">
|
||||
{$t.settings?.llm_provider_bindings_title || "Provider Bindings by Task"}
|
||||
{$t.settings?.llm_provider_bindings_title ||
|
||||
"Provider Bindings by Task"}
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-gray-600">
|
||||
{$t.settings?.llm_provider_bindings_description ||
|
||||
@@ -764,15 +828,23 @@
|
||||
|
||||
<div class="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label for="binding-dashboard-validation" class="block text-sm font-medium text-gray-700">
|
||||
{$t.settings?.llm_binding_dashboard_validation || "Dashboard Validation Provider"}
|
||||
<label
|
||||
for="binding-dashboard-validation"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_binding_dashboard_validation ||
|
||||
"Dashboard Validation Provider"}
|
||||
</label>
|
||||
<select
|
||||
id="binding-dashboard-validation"
|
||||
bind:value={settings.llm.provider_bindings.dashboard_validation}
|
||||
bind:value={
|
||||
settings.llm.provider_bindings.dashboard_validation
|
||||
}
|
||||
class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
|
||||
>
|
||||
<option value="">{$t.dashboard?.use_default || "Use Default"}</option>
|
||||
<option value=""
|
||||
>{$t.dashboard?.use_default || "Use Default"}</option
|
||||
>
|
||||
{#each settings.llm_providers || [] as provider}
|
||||
<option value={provider.id}>
|
||||
{provider.name} ({provider.default_model})
|
||||
@@ -788,15 +860,21 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="binding-documentation" class="block text-sm font-medium text-gray-700">
|
||||
{$t.settings?.llm_binding_documentation || "Documentation Provider"}
|
||||
<label
|
||||
for="binding-documentation"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_binding_documentation ||
|
||||
"Documentation Provider"}
|
||||
</label>
|
||||
<select
|
||||
id="binding-documentation"
|
||||
bind:value={settings.llm.provider_bindings.documentation}
|
||||
class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
|
||||
>
|
||||
<option value="">{$t.dashboard?.use_default || "Use Default"}</option>
|
||||
<option value=""
|
||||
>{$t.dashboard?.use_default || "Use Default"}</option
|
||||
>
|
||||
{#each settings.llm_providers || [] as provider}
|
||||
<option value={provider.id}>
|
||||
{provider.name} ({provider.default_model})
|
||||
@@ -806,7 +884,10 @@
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label for="binding-git-commit" class="block text-sm font-medium text-gray-700">
|
||||
<label
|
||||
for="binding-git-commit"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_binding_git_commit || "Git Commit Provider"}
|
||||
</label>
|
||||
<select
|
||||
@@ -814,7 +895,9 @@
|
||||
bind:value={settings.llm.provider_bindings.git_commit}
|
||||
class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
|
||||
>
|
||||
<option value="">{$t.dashboard?.use_default || "Use Default"}</option>
|
||||
<option value=""
|
||||
>{$t.dashboard?.use_default || "Use Default"}</option
|
||||
>
|
||||
{#each settings.llm_providers || [] as provider}
|
||||
<option value={provider.id}>
|
||||
{provider.name} ({provider.default_model})
|
||||
@@ -840,7 +923,8 @@
|
||||
for="documentation-prompt"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{$t.settings?.llm_prompt_documentation || "Documentation Prompt"}
|
||||
{$t.settings?.llm_prompt_documentation ||
|
||||
"Documentation Prompt"}
|
||||
</label>
|
||||
<textarea
|
||||
id="documentation-prompt"
|
||||
@@ -892,6 +976,150 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if activeTab === "migration"}
|
||||
<!-- Migration Sync Tab -->
|
||||
<div class="text-lg font-medium mb-4">
|
||||
<h2 class="text-xl font-bold mb-4">
|
||||
Cross-Environment ID Synchronization
|
||||
</h2>
|
||||
<p class="text-gray-600 mb-6">
|
||||
Configure the background synchronization schedule and view the
|
||||
currently mapped Dashboard, Chart, and Dataset IDs.
|
||||
</p>
|
||||
|
||||
<!-- Cron Configuration -->
|
||||
<div class="bg-gray-50 p-6 rounded-lg border border-gray-200 mb-6">
|
||||
<h3 class="text-lg font-medium mb-4">Sync Schedule (Cron)</h3>
|
||||
<div class="flex items-end gap-4">
|
||||
<div class="flex-grow">
|
||||
<label
|
||||
for="migration_cron"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>Cron Expression</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="migration_cron"
|
||||
bind:value={migrationCron}
|
||||
placeholder="0 2 * * *"
|
||||
class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2 font-mono text-sm"
|
||||
/>
|
||||
<p class="text-xs text-gray-500 mt-1">
|
||||
Example: 0 2 * * * (daily at 2 AM UTC)
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
on:click={saveMigrationSettings}
|
||||
disabled={isSavingMigration}
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 h-[42px] min-w-[100px] flex items-center justify-center disabled:opacity-50"
|
||||
>
|
||||
{isSavingMigration ? "Saving..." : "Save"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mappings Table -->
|
||||
<div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
|
||||
<h3
|
||||
class="text-lg font-medium mb-4 flex items-center justify-between"
|
||||
>
|
||||
<span>Synchronized Resources</span>
|
||||
<button
|
||||
on:click={loadMigrationSettings}
|
||||
class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center gap-1"
|
||||
disabled={isLoadingMigration}
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 {isLoadingMigration ? 'animate-spin' : ''}"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
></path></svg
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
</h3>
|
||||
|
||||
<div class="overflow-x-auto border border-gray-200 rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
<th
|
||||
class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
|
||||
>Resource Name</th
|
||||
>
|
||||
<th
|
||||
class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
|
||||
>Type</th
|
||||
>
|
||||
<th
|
||||
class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
|
||||
>UUID</th
|
||||
>
|
||||
<th
|
||||
class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
|
||||
>Target ID</th
|
||||
>
|
||||
<th
|
||||
class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
|
||||
>Env</th
|
||||
>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
{#if isLoadingMigration && displayMappings.length === 0}
|
||||
<tr
|
||||
><td
|
||||
colspan="5"
|
||||
class="px-6 py-8 text-center text-gray-500"
|
||||
>Loading mappings...</td
|
||||
></tr
|
||||
>
|
||||
{:else if displayMappings.length === 0}
|
||||
<tr
|
||||
><td
|
||||
colspan="5"
|
||||
class="px-6 py-8 text-center text-gray-500"
|
||||
>No synchronized resources found.</td
|
||||
></tr
|
||||
>
|
||||
{:else}
|
||||
{#each displayMappings as mapping}
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap font-medium text-gray-900"
|
||||
>{mapping.resource_name || "N/A"}</td
|
||||
>
|
||||
<td class="px-6 py-4 whitespace-nowrap"
|
||||
><span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||
>{mapping.resource_type}</span
|
||||
></td
|
||||
>
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap font-mono text-xs text-gray-500"
|
||||
>{mapping.uuid}</td
|
||||
>
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap font-mono text-xs font-bold text-gray-700"
|
||||
>{mapping.remote_id}</td
|
||||
>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-gray-500"
|
||||
>{mapping.environment_id}</td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if activeTab === "storage"}
|
||||
<!-- Storage Tab -->
|
||||
<div class="text-lg font-medium mb-4">
|
||||
|
||||
Reference in New Issue
Block a user