From 81dd51be8a3ae063a16804603d730d44b9000ee7 Mon Sep 17 00:00:00 2001 From: Nikolay <46225163+vigdorov@users.noreply.github.com> Date: Wed, 6 Jan 2021 09:52:05 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20indexedDB=20?= =?UTF-8?q?(#52)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/api/commonApi.ts | 30 +++++++ .../consts.ts => core/consts/initBase.ts} | 14 +++- src/core/enums/common.ts | 6 ++ src/core/utils/indexedDB.ts | 82 +++++++++++++++++++ .../information/components/page/Page.tsx | 9 +- 5 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 src/core/api/commonApi.ts rename src/{pages/information/consts.ts => core/consts/initBase.ts} (88%) create mode 100644 src/core/utils/indexedDB.ts diff --git a/src/core/api/commonApi.ts b/src/core/api/commonApi.ts new file mode 100644 index 0000000..0505806 --- /dev/null +++ b/src/core/api/commonApi.ts @@ -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(connection, CommonApiName.TaskList)), + folderList: makeApi(makeStoreObject(connection, CommonApiName.FolderList)), + tagList: makeApi(makeStoreObject(connection, CommonApiName.TagList)), +}; diff --git a/src/pages/information/consts.ts b/src/core/consts/initBase.ts similarity index 88% rename from src/pages/information/consts.ts rename to src/core/consts/initBase.ts index 1ab8468..8fc5aa1 100644 --- a/src/pages/information/consts.ts +++ b/src/core/consts/initBase.ts @@ -1,8 +1,7 @@ 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'; -// Псевдоданные const TagList: Tag[] = [ {id: '33', name: 'Tag', color: '#2fc036'}, {id: '66', name: 'Tag', color: '#2fc036'}, @@ -10,14 +9,14 @@ const TagList: Tag[] = [ {id: '22', name: 'Tag', color: '#2fc036'}, ]; -export const FolderList: Folder[] = [ +const FolderList: Folder[] = [ {id: '4', name: 'Folder 1', type: FolderType.Information}, {id: '6', name: 'Folder 34', type: FolderType.Information}, {id: '7', name: 'Folder ffd', type: FolderType.Information}, {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 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'}, @@ -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 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, +}; + diff --git a/src/core/enums/common.ts b/src/core/enums/common.ts index 2611e03..089dcb7 100644 --- a/src/core/enums/common.ts +++ b/src/core/enums/common.ts @@ -25,3 +25,9 @@ export enum Icon { Apple = 'apple', Apartment = 'apartment', } + +export enum CommonApiName { + TaskList = 'taskList', + FolderList = 'folderList', + TagList = 'tagList', +} diff --git a/src/core/utils/indexedDB.ts b/src/core/utils/indexedDB.ts new file mode 100644 index 0000000..b9e10df --- /dev/null +++ b/src/core/utils/indexedDB.ts @@ -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 => { + 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, + storeName: string, +) => async (mode: TransactionMode): Promise => { + const db = await connection; + const transaction = db.transaction(storeName, mode); + return transaction.objectStore(storeName); +}; + +const makeStoreRequest = (request: IDBRequest): Promise => new Promise((resolve, reject) => { + request.addEventListener(StoreRequestEvent.Success, () => { + resolve(request.result); + }); + request.addEventListener(StoreRequestEvent.Error, () => { + reject(request.error); + }); +}); + +export const makeStoreObject = (connection: Promise, storeName: string) => { + const makeStore = makeTransaction(connection, storeName); + return { + getAll: async () => { + const store = await makeStore(TransactionMode.ReadOnly); + return makeStoreRequest>(store.getAll()); + }, + add: async (task: T) => { + const store = await makeStore(TransactionMode.ReadWrite); + return makeStoreRequest(store.add(task)); + }, + put: async (task: T) => { + const store = await makeStore(TransactionMode.ReadWrite); + return makeStoreRequest(store.put(task)); + }, + delete: async (id: string) => { + const store = await makeStore(TransactionMode.ReadWrite); + return makeStoreRequest(store.delete(id)); + }, + }; +}; diff --git a/src/pages/information/components/page/Page.tsx b/src/pages/information/components/page/Page.tsx index 5f780ae..a2bf1be 100644 --- a/src/pages/information/components/page/Page.tsx +++ b/src/pages/information/components/page/Page.tsx @@ -1,12 +1,17 @@ +import {combine} from '@most/core'; import React, {Fragment, memo} from 'react'; import {isNotEmpty} from '_referers/common'; 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'; -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 tree = useStream(() => stream$, []); return ( {isNotEmpty(tree) && (