summaryrefslogtreecommitdiff
path: root/frontend/src/pages/ProjectDataTab.svelte
blob: 7b9f8ea1e65499ad69610159ebd98fb57982e4f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<script lang="ts">
  import Status from '../components/Status.svelte';
  import DatasetCard from '../components/DatasetCard.svelte';
  import DatasetWizard from '../components/DatasetWizard.svelte';
  import { listDatasets } from '../lib/client';
  import { extractStatusMessage } from '../lib/state';
  import type { Dataset } from '../lib/types';
  import { Button } from '$lib/components/ui/button';

  interface Props {
    projectId?: string;
    showWizard?: boolean;
  }
  let { projectId: _projectId, showWizard = false }: Props = $props();

  let items: Dataset[] = $state([]);
  let busy = $state(true);
  let error: string | null = $state(null);
  // svelte-ignore state_referenced_locally
  let wizardOpen = $state(showWizard);


  let refreshTimer: ReturnType<typeof setInterval> | null = null;

  $effect(() => {
    void load();
    return () => {
      if (refreshTimer) clearInterval(refreshTimer);
      refreshTimer = null;
    };
  });

  async function load() {
    error = null;
    try {
      const { items: got } = await listDatasets();
      items = got;
      const active = got.some((d) => d.status === 'pending' || d.status === 'running');
      if (active && !refreshTimer) {
        refreshTimer = setInterval(async () => {
          try {
            const { items: fresh } = await listDatasets();
            items = fresh;
            const still = fresh.some((d) => d.status === 'pending' || d.status === 'running');
            if (!still && refreshTimer) {
              clearInterval(refreshTimer);
              refreshTimer = null;
            }
          } catch {
            /* transient error, keep polling */
          }
        }, 2000);
      }
    } catch (e) {
      error = extractStatusMessage(e);
    } finally {
      busy = false;
    }
  }
</script>

<div class="flex flex-col gap-3">
  {#if wizardOpen}
    <DatasetWizard onCreated={() => void load()} />
    <Button variant="ghost" size="sm" onclick={() => (wizardOpen = false)}>收起新建面板</Button>
  {:else}
    <Button size="sm" class="w-fit" onclick={() => (wizardOpen = true)}>新建数据集</Button>
  {/if}

  <h2>我的数据集</h2>
  <Status busy={busy} error={error} busyText="加载数据集列表…" empty={null} />

  {#if !busy && !error && items.length === 0}
    <Status
      busy={false}
      empty="还没有数据集"
      emptyHint="先创建数据集:选择标的、日期范围与复权方式,提交后异步获取并给出覆盖预览"
    />
  {/if}

  {#if !busy && !error && items.length > 0}
    {#each items as ds (ds.id)}
      <DatasetCard dsId={ds.id} onRecreated={() => void load()} />
    {/each}
  {/if}
</div>