File size: 3,803 Bytes
5a81b95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const DB_NAME = 'CyberDashboardDB';
const DB_VERSION = 1;

interface DBSchema {
  dashboards: { id: string; name: string; widgets: any[]; createdAt: number; updatedAt: number };
  snapshots: { id: string; dashboardId: string; name: string; data: any; createdAt: number };
  settings: { key: string; value: any };
}

let db: IDBDatabase | null = null;

export const initDB = (): Promise<IDBDatabase> => {
  return new Promise((resolve, reject) => {
    if (db) {
      resolve(db);
      return;
    }

    const request = indexedDB.open(DB_NAME, DB_VERSION);

    request.onerror = () => reject(request.error);
    request.onsuccess = () => {
      db = request.result;
      resolve(db);
    };

    request.onupgradeneeded = (event) => {
      const database = (event.target as IDBOpenDBRequest).result;

      // Dashboards store
      if (!database.objectStoreNames.contains('dashboards')) {
        const dashboardStore = database.createObjectStore('dashboards', { keyPath: 'id' });
        dashboardStore.createIndex('updatedAt', 'updatedAt');
      }

      // Snapshots store
      if (!database.objectStoreNames.contains('snapshots')) {
        const snapshotStore = database.createObjectStore('snapshots', { keyPath: 'id' });
        snapshotStore.createIndex('dashboardId', 'dashboardId');
        snapshotStore.createIndex('createdAt', 'createdAt');
      }

      // Settings store
      if (!database.objectStoreNames.contains('settings')) {
        database.createObjectStore('settings', { keyPath: 'key' });
      }
    };
  });
};

export const dbOperation = async <T>(
  storeName: keyof DBSchema,
  mode: IDBTransactionMode,
  operation: (store: IDBObjectStore) => IDBRequest<T>
): Promise<T> => {
  const database = await initDB();
  return new Promise((resolve, reject) => {
    const transaction = database.transaction(storeName, mode);
    const store = transaction.objectStore(storeName);
    const request = operation(store);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
};

// Dashboard operations
export const saveDashboard = (dashboard: DBSchema['dashboards']) =>
  dbOperation('dashboards', 'readwrite', (store) => store.put(dashboard));

export const getDashboard = (id: string) =>
  dbOperation<DBSchema['dashboards'] | undefined>('dashboards', 'readonly', (store) => store.get(id));

export const getAllDashboards = () =>
  dbOperation<DBSchema['dashboards'][]>('dashboards', 'readonly', (store) => store.getAll());

export const deleteDashboard = (id: string) =>
  dbOperation('dashboards', 'readwrite', (store) => store.delete(id));

// Snapshot operations
export const saveSnapshot = (snapshot: DBSchema['snapshots']) =>
  dbOperation('snapshots', 'readwrite', (store) => store.put(snapshot));

export const getSnapshots = (dashboardId: string): Promise<DBSchema['snapshots'][]> =>
  new Promise(async (resolve, reject) => {
    const database = await initDB();
    const transaction = database.transaction('snapshots', 'readonly');
    const store = transaction.objectStore('snapshots');
    const index = store.index('dashboardId');
    const request = index.getAll(dashboardId);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });

export const deleteSnapshot = (id: string) =>
  dbOperation('snapshots', 'readwrite', (store) => store.delete(id));

// Settings operations
export const saveSetting = (key: string, value: any) =>
  dbOperation('settings', 'readwrite', (store) => store.put({ key, value }));

export const getSetting = async <T>(key: string): Promise<T | undefined> => {
  const result = await dbOperation<{ key: string; value: T } | undefined>('settings', 'readonly', (store) => store.get(key));
  return result?.value;
};