Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
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
import { useCallback, useContext, useEffect, useState } from "react";
import { Card, Menu } from "../../../components";
import { Button, Dropdown } from "@humansignal/ui";
import { ApiContext } from "../../../providers/ApiProvider";
import { StorageSummary } from "./StorageSummary";
import { IconEllipsisVertical } from "@humansignal/icons";
 
export const StorageCard = ({ rootClass, target, storage, onEditStorage, onDeleteStorage, storageTypes }) => {
  const [syncing, setSyncing] = useState(false);
  const api = useContext(ApiContext);
  const [storageData, setStorageData] = useState({ ...storage });
  const [synced, setSynced] = useState(null);
 
  const startSync = useCallback(async () => {
    setSyncing(true);
    setSynced(null);
 
    const result = await api.callApi("syncStorage", {
      params: {
        target,
        type: storageData.type,
        pk: storageData.id,
      },
    });
 
    if (result) {
      setStorageData(result);
      setSynced(result.last_sync_count);
    }
 
    setSyncing(false);
  }, [storage]);
 
  useEffect(() => {
    setStorageData(storage);
  }, [storage]);
 
  const notSyncedYet = synced !== null || ["in_progress", "queued"].includes(storageData.status);
 
  return (
    <Card
      header={storageData.title ?? `未命名 ${storageData.type}`}
      extra={
        <Dropdown.Trigger
          align="right"
          content={
            <Menu size="compact" style={{ width: 110 }}>
              <Menu.Item onClick={() => onEditStorage(storageData)}>编辑</Menu.Item>
              <Menu.Item onClick={() => onDeleteStorage(storageData)}>删除</Menu.Item>
            </Menu>
          }
        >
          <Button look="string" className="-ml-3" aria-label="存储选项">
            <IconEllipsisVertical />
          </Button>
        </Dropdown.Trigger>
      }
    >
      <StorageSummary
        target={target}
        storage={storageData}
        className={rootClass.elem("summary")}
        storageTypes={storageTypes}
      />
      <div className={rootClass.elem("sync")}>
        <div className="mt-base">
          <Button
            look="outlined"
            waiting={syncing}
            onClick={startSync}
            disabled={notSyncedYet}
            aria-label="同步存储"
          >
            同步存储
          </Button>
          {notSyncedYet && (
            <div className={rootClass.elem("sync-count")}>
              同步可能需要一些时间,请刷新页面查看当前状态。
            </div>
          )}
        </div>
      </div>
    </Card>
  );
};