aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/src/components/InstancesView.svelte
diff options
context:
space:
mode:
author苏向夜 <46275354+fu050409@users.noreply.github.com>2026-01-19 11:06:38 +0800
committerGitHub <noreply@github.com>2026-01-19 11:06:38 +0800
commitf5560d7e8abe4a41c5f959cb6eb888f6aef6ca65 (patch)
treef3675bdb552a79ddb4601ccf2f5ddd81eb47c9fb /ui/src/components/InstancesView.svelte
parentee767338d6db510ef15d6b8cc11f6fb9a6215a43 (diff)
parentbdff2175a8470accdab030b3931406495c56074d (diff)
downloadDropOut-f5560d7e8abe4a41c5f959cb6eb888f6aef6ca65.tar.gz
DropOut-f5560d7e8abe4a41c5f959cb6eb888f6aef6ca65.zip
Merge branch 'main' into chore/migrate-repository
Diffstat (limited to 'ui/src/components/InstancesView.svelte')
-rw-r--r--ui/src/components/InstancesView.svelte110
1 files changed, 19 insertions, 91 deletions
diff --git a/ui/src/components/InstancesView.svelte b/ui/src/components/InstancesView.svelte
index a4881e6..5334f9e 100644
--- a/ui/src/components/InstancesView.svelte
+++ b/ui/src/components/InstancesView.svelte
@@ -3,12 +3,15 @@
import { instancesState } from "../stores/instances.svelte";
import { Plus, Trash2, Edit2, Copy, Check, X } from "lucide-svelte";
import type { Instance } from "../types";
+ import InstanceCreationModal from "./InstanceCreationModal.svelte";
+ import InstanceEditorModal from "./InstanceEditorModal.svelte";
let showCreateModal = $state(false);
let showEditModal = $state(false);
let showDeleteConfirm = $state(false);
let showDuplicateModal = $state(false);
let selectedInstance: Instance | null = $state(null);
+ let editingInstance: Instance | null = $state(null);
let newInstanceName = $state("");
let duplicateName = $state("");
@@ -17,14 +20,11 @@
});
function handleCreate() {
- newInstanceName = "";
showCreateModal = true;
}
function handleEdit(instance: Instance) {
- selectedInstance = instance;
- newInstanceName = instance.name;
- showEditModal = true;
+ editingInstance = instance;
}
function handleDelete(instance: Instance) {
@@ -38,24 +38,6 @@
showDuplicateModal = true;
}
- async function confirmCreate() {
- if (!newInstanceName.trim()) return;
- await instancesState.createInstance(newInstanceName.trim());
- showCreateModal = false;
- newInstanceName = "";
- }
-
- async function confirmEdit() {
- if (!selectedInstance || !newInstanceName.trim()) return;
- await instancesState.updateInstance({
- ...selectedInstance,
- name: newInstanceName.trim(),
- });
- showEditModal = false;
- selectedInstance = null;
- newInstanceName = "";
- }
-
async function confirmDelete() {
if (!selectedInstance) return;
await instancesState.deleteInstance(selectedInstance.id);
@@ -111,10 +93,13 @@
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{#each instancesState.instances as instance (instance.id)}
<div
+ role="button"
+ tabindex="0"
class="relative p-4 bg-gray-100 dark:bg-gray-800 rounded-lg border-2 transition-all cursor-pointer hover:border-blue-500 {instancesState.activeInstanceId === instance.id
? 'border-blue-500'
: 'border-transparent'}"
onclick={() => instancesState.setActiveInstance(instance.id)}
+ onkeydown={(e) => e.key === "Enter" && instancesState.setActiveInstance(instance.id)}
>
{#if instancesState.activeInstanceId === instance.id}
<div class="absolute top-2 right-2">
@@ -128,6 +113,7 @@
</h3>
<div class="flex gap-1">
<button
+ type="button"
onclick={(e) => {
e.stopPropagation();
handleEdit(instance);
@@ -138,6 +124,7 @@
<Edit2 size={16} class="text-gray-600 dark:text-gray-400" />
</button>
<button
+ type="button"
onclick={(e) => {
e.stopPropagation();
handleDuplicate(instance);
@@ -148,6 +135,7 @@
<Copy size={16} class="text-gray-600 dark:text-gray-400" />
</button>
<button
+ type="button"
onclick={(e) => {
e.stopPropagation();
handleDelete(instance);
@@ -195,75 +183,16 @@
</div>
<!-- Create Modal -->
-{#if showCreateModal}
- <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-96">
- <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">Create Instance</h2>
- <input
- type="text"
- bind:value={newInstanceName}
- placeholder="Instance name"
- class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white mb-4"
- onkeydown={(e) => e.key === "Enter" && confirmCreate()}
- autofocus
- />
- <div class="flex gap-2 justify-end">
- <button
- onclick={() => {
- showCreateModal = false;
- newInstanceName = "";
- }}
- class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
- >
- Cancel
- </button>
- <button
- onclick={confirmCreate}
- disabled={!newInstanceName.trim()}
- class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
- >
- Create
- </button>
- </div>
- </div>
- </div>
-{/if}
+<InstanceCreationModal isOpen={showCreateModal} onClose={() => (showCreateModal = false)} />
-<!-- Edit Modal -->
-{#if showEditModal && selectedInstance}
- <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-96">
- <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">Edit Instance</h2>
- <input
- type="text"
- bind:value={newInstanceName}
- placeholder="Instance name"
- class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white mb-4"
- onkeydown={(e) => e.key === "Enter" && confirmEdit()}
- autofocus
- />
- <div class="flex gap-2 justify-end">
- <button
- onclick={() => {
- showEditModal = false;
- selectedInstance = null;
- newInstanceName = "";
- }}
- class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
- >
- Cancel
- </button>
- <button
- onclick={confirmEdit}
- disabled={!newInstanceName.trim()}
- class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
- >
- Save
- </button>
- </div>
- </div>
- </div>
-{/if}
+<!-- Instance Editor Modal -->
+<InstanceEditorModal
+ isOpen={editingInstance !== null}
+ instance={editingInstance}
+ onClose={() => {
+ editingInstance = null;
+ }}
+/>
<!-- Delete Confirmation -->
{#if showDeleteConfirm && selectedInstance}
@@ -305,7 +234,6 @@
placeholder="New instance name"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white mb-4"
onkeydown={(e) => e.key === "Enter" && confirmDuplicate()}
- autofocus
/>
<div class="flex gap-2 justify-end">
<button