forked from mdnice/markdown-nice
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dad08a5
commit e8af3cc
Showing
7 changed files
with
405 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import * as React from "react"; | ||
import {Button} from "antd"; | ||
import PreviewForm from "./preview"; | ||
import IndexDB from "./indexdb"; | ||
import {getLocalDocuments, setLocalDocuments, setLocalDraft, AutoSaveInterval} from "./util"; | ||
// import debouce from 'lodash/debounce'; | ||
import "./localHistory.css"; | ||
|
||
const NOOP = () => {}; | ||
class LocalHistory extends React.Component { | ||
timer = null; | ||
|
||
db = null; | ||
|
||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
documents: [], | ||
showPreview: false, | ||
markDownString: "", | ||
}; | ||
} | ||
|
||
async componentDidMount() { | ||
await this.initIndexDB(); | ||
} | ||
|
||
componentWillUnmount() { | ||
clearInterval(this.timer); | ||
} | ||
// | ||
// async UNSAFE_componentWillReceiveProps(nextProps) { | ||
// // 文档 id 变更 | ||
// if (this.props.documentID !== nextProps.documentID && nextProps.documentID != null) { | ||
// if (this.db) { | ||
// await this.refreshLocalDocuments(nextProps.documentID); | ||
// } | ||
// } | ||
// } | ||
|
||
preview = (content) => { | ||
this.setState({ | ||
showPreview: true, | ||
markDownString: content, | ||
}); | ||
}; | ||
|
||
hidePreview = () => { | ||
this.setState({ | ||
showPreview: false, | ||
markDownString: "", | ||
}); | ||
}; | ||
|
||
// | ||
autoSave = async (isRecent = false) => { | ||
const Content = this.props.editor.getValue(); | ||
if (Content.trim() !== "") { | ||
const document = { | ||
Content, | ||
DocumentID: +this.props.documentID, | ||
BusinessID: +this.props.businessID, | ||
SaveTime: new Date(), | ||
}; | ||
const setLocalDocumentMethod = isRecent && this.state.documents.length > 0 ? setLocalDraft : setLocalDocuments; | ||
await setLocalDocumentMethod(this.db, this.state.documents, document); | ||
await this.refreshLocalDocuments(this.props.documentID); | ||
} | ||
}; | ||
|
||
async initIndexDB() { | ||
console.log("initIndexDB"); | ||
try { | ||
const indexDB = new IndexDB({ | ||
name: "mdnice-local-history", | ||
storeName: "customers", | ||
storeOptions: {keyPath: "id", autoIncrement: true}, | ||
storeInit: (objectStore) => { | ||
objectStore.createIndex("DocumentID", "DocumentID", {unique: false}); | ||
objectStore.createIndex("SaveTime", "SaveTime", {unique: false}); | ||
}, | ||
}); | ||
this.db = await indexDB.init(); | ||
|
||
if (this.db && this.props.documentID) { | ||
await this.refreshLocalDocuments(this.props.documentID); | ||
} | ||
// 每隔一段时间自动保存 | ||
this.timer = setInterval(async () => { | ||
await this.autoSave(); | ||
}, AutoSaveInterval); | ||
// 每改变内容自动保存最近的一条 | ||
this.props.editor.on && | ||
this.props.editor.on( | ||
"change", | ||
async () => { | ||
console.log("change"); | ||
await this.autoSave(true); | ||
}, | ||
// debouce(async () => { | ||
// await this.autoSave(true); | ||
// }, 1000), | ||
); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
|
||
// 刷新本地历史文档 | ||
async refreshLocalDocuments(documentID) { | ||
const localDocuments = await getLocalDocuments(this.db, +documentID); | ||
// console.log('refresh local',localDocuments); | ||
this.setState({ | ||
documents: localDocuments, | ||
}); | ||
} | ||
|
||
render() { | ||
const {documents} = this.state; | ||
return ( | ||
<> | ||
{documents.map((d) => ( | ||
<div key={d.id}> | ||
{/* 保存时间:{moment(d.SaveTime).format('YYYY-MM-DD HH:mm:ss')} */} | ||
保存时间: | ||
{d.SaveTime.toLocaleString()} | ||
<Button | ||
type="primary" | ||
onClick={() => { | ||
this.preview(d.Content); | ||
}} | ||
> | ||
预览 | ||
</Button> | ||
<Button | ||
onClick={() => { | ||
this.props.onEdit(d.Content); | ||
}} | ||
> | ||
编辑 | ||
</Button> | ||
<PreviewForm | ||
hideModal={this.hidePreview} | ||
visible={this.state.showPreview} | ||
markDownString={this.state.markDownString} | ||
/> | ||
</div> | ||
))} | ||
</> | ||
); | ||
} | ||
} | ||
|
||
LocalHistory.defaultProps = { | ||
visible: false, | ||
document: [], | ||
onEdit: NOOP, | ||
}; | ||
|
||
export default LocalHistory; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import {message} from "antd"; | ||
|
||
// In the following line, you should include the prefixes of implementations you want to test. | ||
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; | ||
// DON'T use "var indexedDB = ..." if you're not in a function. | ||
// Moreover, you may need references to some window.IDB* objects: | ||
// const IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction; | ||
// const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange; | ||
|
||
// (Mozilla has never prefixed these objects, so we don't need window.mozIDB*) | ||
|
||
export default class IndexDB { | ||
constructor(options = {}) { | ||
this.options = options; | ||
} | ||
|
||
async init() { | ||
if (!indexedDB) { | ||
message.error("初始化 indexdb 失败!浏览器不支持"); | ||
throw Error("浏览器不支持 indexdb"); | ||
} | ||
|
||
const {name, storeName = "", storeOptions = {}, storeInit = () => {}} = this.options; | ||
|
||
this.storeName = storeName; | ||
this.storeOptions = storeOptions; | ||
this.storeInit = storeInit; | ||
|
||
const request = indexedDB.open(name); | ||
const result = await this.initEvent(request); | ||
return result; | ||
} | ||
|
||
initEvent(request) { | ||
return new Promise((resolve, reject) => { | ||
request.onerror = (event) => { | ||
// Do something with request.errorCode! | ||
message.error("初始化数据库失败!", event.target.errorCode); | ||
reject(new Error("初始化数据库失败!")); | ||
}; | ||
|
||
request.onsuccess = (event) => { | ||
const db = event.target.result; | ||
console.log("成功初始化数据库"); | ||
// this.db = db; | ||
resolve(db); | ||
}; | ||
|
||
// 该事件仅在较新的浏览器中被实现 | ||
request.onupgradeneeded = (event) => { | ||
// 更新对象存储空间和索引 .... | ||
const db = event.target.result; | ||
this.initStore(db, this.storeName, this.storeOptions, this.storeInit); | ||
}; | ||
}); | ||
} | ||
|
||
initStore(db, name, options, func) { | ||
// 创建一个对象存储空间来持有信息。 | ||
const objectStore = db.createObjectStore(name, options); | ||
if (func) func(objectStore); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.nice-md-local-history button { | ||
margin: 5px 10px; | ||
} | ||
|
||
.nice-md-local-history button:last-child { | ||
margin: 5px 10px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import * as React from "react"; | ||
import {Modal} from "antd"; | ||
// import MarkDownPreview from '@component/MarkdownPreview'; | ||
|
||
const MarkDownPreview = (props) => <div>{props.markDownString}</div>; | ||
class PreviewForm extends React.PureComponent { | ||
render() { | ||
const {visible, hideModal, markDownString} = this.props; | ||
return ( | ||
<Modal | ||
title="预览" | ||
visible={visible} | ||
onCancel={hideModal} | ||
onOk={hideModal} | ||
width={600} | ||
destroyOnClose | ||
closable | ||
centered | ||
footer={null} | ||
> | ||
<MarkDownPreview markDownString={markDownString} /> | ||
</Modal> | ||
); | ||
} | ||
} | ||
|
||
PreviewForm.defaultProps = { | ||
visible: false, | ||
hideModal: () => {}, | ||
markDownString: "", | ||
}; | ||
export default PreviewForm; |
Oops, something went wrong.