Skip to content

Commit b2a746b

Browse files
committed
Add indexedDB
1 parent b9e5fb0 commit b2a746b

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

src/App.tsx

+14-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Header from './components/Header/Header';
99
import Footer from './components/Footer/Footer';
1010
import { useLocalStorageState } from './utils';
1111
import { Theme } from './utils/theme.cont';
12+
import IndexedDB from './utils/indexedDB';
1213

1314
function App() {
1415
const [ content, setContent ] = useState<string | undefined>();
@@ -17,11 +18,21 @@ function App() {
1718
const [ themeState ] = useLocalStorageState('theme', Theme.LIGHT);
1819
const bodyElRef = useRef(document.querySelector('body'));
1920
const [ currentTheme, setCurrentTheme ] = useState<string>(themeState);
21+
const indexedDBIns = new IndexedDB('editor-db', 'editorContent', 'value');
2022

2123
useEffect(() => {
22-
// Check IndexedDB to grab API Specification
23-
// if there is no exsiting spec.
24-
setContent(JSON.stringify(petStoreAPISpec, null, 2));
24+
// Check IndexedDB to grab API Specification
25+
indexedDBIns.loadContentFromDB()
26+
.then(async (res) => {
27+
if(!res){
28+
// if there is no exsiting spec, use pet store api spec.
29+
await indexedDBIns.saveContentToDB(petStoreAPISpec);
30+
setContent(JSON.stringify(petStoreAPISpec, null, 2));
31+
}else{
32+
// if it exists, display it on Editor.
33+
setContent(JSON.stringify(res, null, 2));
34+
}
35+
})
2536
}, [])
2637
useEffect(() => {
2738
// Check Theme
@@ -48,8 +59,6 @@ function App() {
4859
<Editor content={content} setContent={setContent} currentTheme={currentTheme}/>
4960
<div className={`p-2 vh-100`}
5061
style={{overflowY: "auto"}}>
51-
<>{console.log(currentTheme)}</>
52-
{/* {currentTheme === Theme.DARK && <ThemeComponent />} */}
5362
<SwaggerUI spec={content} />
5463
</div>
5564
</ReactSplitPane>

src/components/Editor/components/MonacoEditor.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Editor from '@monaco-editor/react';
22
import Spinner from 'react-bootstrap/Spinner';
33
import { SpectralLinter, applyErrorMarkers } from '../../../utils';
44
import { Theme, EditorThemeData } from '../../../utils/theme.cont';
5+
import IndexedDB from '../../../utils/indexedDB';
56

67
interface MonacoEditorTypes {
78
editorRef: any
@@ -12,6 +13,8 @@ interface MonacoEditorTypes {
1213
}
1314
const MonacoEditor:React.FC<MonacoEditorTypes> = ({ editorRef, monacoRef, content, setContent, currentTheme }) => {
1415
const { lintScan } = SpectralLinter();
16+
const indexedDBIns = new IndexedDB('editor-db', 'editorContent', 'content');
17+
1518
function handleEditorWillMount(monaco:any){
1619
monaco.editor.defineTheme(Theme.LIGHT, EditorThemeData[Theme.LIGHT]);
1720
monaco.editor.defineTheme(Theme.DARK, EditorThemeData[Theme.DARK]);
@@ -25,9 +28,11 @@ const MonacoEditor:React.FC<MonacoEditorTypes> = ({ editorRef, monacoRef, conten
2528
applyErrorMarkers(res, editorRef.current, monacoRef.current)
2629
});
2730
}
28-
function onChange() {
31+
async function onChange() {
2932
const editorValue = editorRef.current?.getValue();
3033
setContent(editorValue);
34+
// Store value into indexedDB
35+
indexedDBIns.saveContentToDB(JSON.parse(editorValue))
3136
}
3237
return(<>
3338
{

src/utils/indexedDB.ts

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
export default class IndexedDB {
2+
dbName:string;
3+
objectStoreName:string;
4+
storeId: string;
5+
request:any;
6+
constructor(dbName:string, objectStoreName:string, storeId:string) {
7+
this.dbName = dbName;
8+
this.objectStoreName = objectStoreName;
9+
this.storeId = storeId;
10+
11+
// Open DB
12+
this.request = indexedDB.open(dbName, 1);
13+
// Create ObjectStore
14+
this.request.onupgradeneeded = () => {
15+
const db = this.request.result;
16+
if (!db.objectStoreNames.contains(this.objectStoreName)) {
17+
db.createObjectStore(this.objectStoreName, { keyPath: 'id' });
18+
}
19+
};
20+
this.request.onerror = (event:any) => {
21+
console.log(`Error opening IndexedDB: ${event}`);
22+
};
23+
}
24+
25+
saveContentToDB(value: Record<string, any>) {
26+
return new Promise((resolve) => {
27+
const db = this.request.result;
28+
const transaction = db.transaction([this.objectStoreName], 'readwrite');
29+
const store = transaction.objectStore(this.objectStoreName);
30+
store.put({ id: this.storeId, value });
31+
32+
transaction.oncomplete = () => {
33+
resolve('Content saved to IndexedDB');
34+
};
35+
});
36+
}
37+
38+
loadContentFromDB() {
39+
return new Promise((resolve, reject) => {
40+
this.request.onsuccess = () => {
41+
const db = this.request.result;
42+
const transaction = db.transaction([this.objectStoreName], 'readonly');
43+
const store = transaction.objectStore(this.objectStoreName);
44+
const getRequest = store.get('content');
45+
getRequest.onsuccess = () => {
46+
if (getRequest.result) {
47+
resolve(getRequest.result.value);
48+
}else{
49+
resolve(undefined)
50+
}
51+
};
52+
53+
getRequest.onerror = (event:any) => {
54+
console.error('Error getting content from IndexedDB:', event);
55+
reject({status:"error", message: `'Error getting content from IndexedDB: ${event}` });
56+
};
57+
};
58+
59+
this.request.onerror = (event:any) => {
60+
console.error('Error opening IndexedDB:', event);
61+
reject({status:"error", message: `Error opening IndexedDB: ${event}` });
62+
};
63+
})
64+
}
65+
}

0 commit comments

Comments
 (0)