Добавление методов работы с indexedDB (#52)
This commit is contained in:
30
src/core/api/commonApi.ts
Normal file
30
src/core/api/commonApi.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {INIT_BASE} from '_consts/initBase';
|
||||||
|
import {CommonApiName} from '_enums/common';
|
||||||
|
import {Folder, Tag, Task} from '_types/common';
|
||||||
|
import {makeStoreObject, openConnection} from '_utils/indexedDB';
|
||||||
|
import {makeApi} from '_utils/makeApi';
|
||||||
|
|
||||||
|
const STORE_NAME_LIST = [CommonApiName.TaskList, CommonApiName.FolderList, CommonApiName.TagList];
|
||||||
|
|
||||||
|
const connection = openConnection({
|
||||||
|
dbName: 'FYB',
|
||||||
|
version: 1,
|
||||||
|
onUpdate: db => {
|
||||||
|
switch (db.version) {
|
||||||
|
default: {
|
||||||
|
STORE_NAME_LIST.forEach(storeName => {
|
||||||
|
const objectStore = db.createObjectStore(storeName, {keyPath: 'id'});
|
||||||
|
INIT_BASE[storeName].forEach((item: unknown) => {
|
||||||
|
objectStore.add(item);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const commonApi = {
|
||||||
|
taskList: makeApi(makeStoreObject<Task>(connection, CommonApiName.TaskList)),
|
||||||
|
folderList: makeApi(makeStoreObject<Folder>(connection, CommonApiName.FolderList)),
|
||||||
|
tagList: makeApi(makeStoreObject<Tag>(connection, CommonApiName.TagList)),
|
||||||
|
};
|
||||||
@ -1,8 +1,7 @@
|
|||||||
import {v4} from 'uuid';
|
import {v4} from 'uuid';
|
||||||
import {FolderType, Icon, TaskStatus} from '_enums/common';
|
import {CommonApiName, FolderType, Icon, TaskStatus} from '_enums/common';
|
||||||
import {Folder, Tag, Task} from '_types/common';
|
import {Folder, Tag, Task} from '_types/common';
|
||||||
|
|
||||||
// Псевдоданные
|
|
||||||
const TagList: Tag[] = [
|
const TagList: Tag[] = [
|
||||||
{id: '33', name: 'Tag', color: '#2fc036'},
|
{id: '33', name: 'Tag', color: '#2fc036'},
|
||||||
{id: '66', name: 'Tag', color: '#2fc036'},
|
{id: '66', name: 'Tag', color: '#2fc036'},
|
||||||
@ -10,14 +9,14 @@ const TagList: Tag[] = [
|
|||||||
{id: '22', name: 'Tag', color: '#2fc036'},
|
{id: '22', name: 'Tag', color: '#2fc036'},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const FolderList: Folder[] = [
|
const FolderList: Folder[] = [
|
||||||
{id: '4', name: 'Folder 1', type: FolderType.Information},
|
{id: '4', name: 'Folder 1', type: FolderType.Information},
|
||||||
{id: '6', name: 'Folder 34', type: FolderType.Information},
|
{id: '6', name: 'Folder 34', type: FolderType.Information},
|
||||||
{id: '7', name: 'Folder ffd', type: FolderType.Information},
|
{id: '7', name: 'Folder ffd', type: FolderType.Information},
|
||||||
{id: '73', name: 'Folder ffd', type: FolderType.Information, folder: '7'},
|
{id: '73', name: 'Folder ffd', type: FolderType.Information, folder: '7'},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const TaskList: Task[] = [
|
const TaskList: Task[] = [
|
||||||
{id: v4(), title: 'Title number 1', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '4'},
|
{id: v4(), title: 'Title number 1', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '4'},
|
||||||
{id: v4(), title: 'Title number 2', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '4'},
|
{id: v4(), title: 'Title number 2', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '4'},
|
||||||
{id: v4(), title: 'Title number 3', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '6'},
|
{id: v4(), title: 'Title number 3', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '6'},
|
||||||
@ -30,3 +29,10 @@ export const TaskList: Task[] = [
|
|||||||
{id: v4(), title: 'Title number 10', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '7'},
|
{id: v4(), title: 'Title number 10', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '7'},
|
||||||
{id: v4(), title: 'Title number 11', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '73'},
|
{id: v4(), title: 'Title number 11', body: 'Description', created_at: '2019-01-01T13:00', icon: Icon.Apple, status: TaskStatus.Progress, folder: '73'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const INIT_BASE = {
|
||||||
|
[CommonApiName.TaskList]: TaskList,
|
||||||
|
[CommonApiName.FolderList]: FolderList,
|
||||||
|
[CommonApiName.TagList]: TagList,
|
||||||
|
};
|
||||||
|
|
||||||
@ -25,3 +25,9 @@ export enum Icon {
|
|||||||
Apple = 'apple',
|
Apple = 'apple',
|
||||||
Apartment = 'apartment',
|
Apartment = 'apartment',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CommonApiName {
|
||||||
|
TaskList = 'taskList',
|
||||||
|
FolderList = 'folderList',
|
||||||
|
TagList = 'tagList',
|
||||||
|
}
|
||||||
|
|||||||
82
src/core/utils/indexedDB.ts
Normal file
82
src/core/utils/indexedDB.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
enum TransactionMode {
|
||||||
|
ReadOnly = 'readonly',
|
||||||
|
ReadWrite = 'readwrite',
|
||||||
|
VersionChange = 'versionchange',
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OpenRequestEvent {
|
||||||
|
Success = 'success',
|
||||||
|
Error = 'error',
|
||||||
|
UpgradeNeeded = 'upgradeneeded',
|
||||||
|
Blocked = 'blocked',
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StoreRequestEvent {
|
||||||
|
Success = 'success',
|
||||||
|
Error = 'error',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const openConnection = (
|
||||||
|
{dbName, version, onUpdate, onBlocked}: {
|
||||||
|
dbName: string;
|
||||||
|
version: number;
|
||||||
|
onUpdate: (db: IDBDatabase) => void;
|
||||||
|
onBlocked?: (db: IDBDatabase) => void;
|
||||||
|
}
|
||||||
|
): Promise<IDBDatabase> => {
|
||||||
|
const openRequest = indexedDB.open(dbName, version);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openRequest.addEventListener(OpenRequestEvent.Success, () => {
|
||||||
|
resolve(openRequest.result);
|
||||||
|
});
|
||||||
|
openRequest.addEventListener(OpenRequestEvent.Error, () => {
|
||||||
|
reject(openRequest.error);
|
||||||
|
});
|
||||||
|
openRequest.addEventListener(OpenRequestEvent.UpgradeNeeded, () => {
|
||||||
|
onUpdate(openRequest.result);
|
||||||
|
});
|
||||||
|
openRequest.addEventListener(OpenRequestEvent.Blocked, () => {
|
||||||
|
onBlocked?.(openRequest.result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeTransaction = (
|
||||||
|
connection: Promise<IDBDatabase>,
|
||||||
|
storeName: string,
|
||||||
|
) => async (mode: TransactionMode): Promise<IDBObjectStore> => {
|
||||||
|
const db = await connection;
|
||||||
|
const transaction = db.transaction(storeName, mode);
|
||||||
|
return transaction.objectStore(storeName);
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeStoreRequest = <T>(request: IDBRequest): Promise<T> => new Promise((resolve, reject) => {
|
||||||
|
request.addEventListener(StoreRequestEvent.Success, () => {
|
||||||
|
resolve(request.result);
|
||||||
|
});
|
||||||
|
request.addEventListener(StoreRequestEvent.Error, () => {
|
||||||
|
reject(request.error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const makeStoreObject = <T>(connection: Promise<IDBDatabase>, storeName: string) => {
|
||||||
|
const makeStore = makeTransaction(connection, storeName);
|
||||||
|
return {
|
||||||
|
getAll: async () => {
|
||||||
|
const store = await makeStore(TransactionMode.ReadOnly);
|
||||||
|
return makeStoreRequest<Array<T>>(store.getAll());
|
||||||
|
},
|
||||||
|
add: async (task: T) => {
|
||||||
|
const store = await makeStore(TransactionMode.ReadWrite);
|
||||||
|
return makeStoreRequest<void>(store.add(task));
|
||||||
|
},
|
||||||
|
put: async (task: T) => {
|
||||||
|
const store = await makeStore(TransactionMode.ReadWrite);
|
||||||
|
return makeStoreRequest<void>(store.put(task));
|
||||||
|
},
|
||||||
|
delete: async (id: string) => {
|
||||||
|
const store = await makeStore(TransactionMode.ReadWrite);
|
||||||
|
return makeStoreRequest<void>(store.delete(id));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,12 +1,17 @@
|
|||||||
|
import {combine} from '@most/core';
|
||||||
import React, {Fragment, memo} from 'react';
|
import React, {Fragment, memo} from 'react';
|
||||||
import {isNotEmpty} from '_referers/common';
|
import {isNotEmpty} from '_referers/common';
|
||||||
import {makeTreeList} from '_utils/makeTreeList';
|
import {makeTreeList} from '_utils/makeTreeList';
|
||||||
import {FolderList, TaskList} from '../../consts';
|
import {commonApi} from '_api/commonApi';
|
||||||
|
import {useStream} from '_utils/useStream';
|
||||||
import InfoList from '../info-list';
|
import InfoList from '../info-list';
|
||||||
|
|
||||||
const tree = makeTreeList(FolderList, TaskList);
|
const stream$ = combine((taskList, folderList) => {
|
||||||
|
return makeTreeList(folderList, taskList);
|
||||||
|
}, commonApi.taskList.getAll(), commonApi.folderList.getAll());
|
||||||
|
|
||||||
const Page: React.FC = () => {
|
const Page: React.FC = () => {
|
||||||
|
const tree = useStream(() => stream$, []);
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{isNotEmpty(tree) && (
|
{isNotEmpty(tree) && (
|
||||||
|
|||||||
Reference in New Issue
Block a user