Skip to content

Commit

Permalink
chore:本地历史逻辑初步跑通
Browse files Browse the repository at this point in the history
  • Loading branch information
LinFeng1997 committed Nov 30, 2019
1 parent dad08a5 commit e8af3cc
Show file tree
Hide file tree
Showing 7 changed files with 405 additions and 11 deletions.
28 changes: 21 additions & 7 deletions src/component/Dialog/HistoryDialog.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import React, {Component} from "react";
import {observer, inject} from "mobx-react";
import {Modal} from "antd";
import {Drawer} from "antd";
import LocalHistory from "../LocalHistory";

@inject("dialog")
@inject("content")
@observer
class HistoryDialog extends Component {
closeDialog = () => {
this.props.dialog.setHistoryOpen(false);
};

editLocalDocument = (content) => {
this.props.content.setContent(content);
this.closeDialog();
};

render() {
return (
<Modal
<Drawer
className="nice-md-local-history"
title="本地历史"
okText="确认"
cancelText="取消"
placement="right"
closable={false}
width={450}
visible={this.props.dialog.isHistoryOpen}
onOk={this.closeDialog}
onCancel={this.closeDialog}
onClose={this.closeDialog}
>
</Modal>
<LocalHistory
editor={this.props.content.markdownEditor}
content={this.props.content.content}
documentID={1}
onEdit={this.editLocalDocument}
/>
</Drawer>
);
}
}
Expand Down
160 changes: 160 additions & 0 deletions src/component/LocalHistory/index.js
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;
63 changes: 63 additions & 0 deletions src/component/LocalHistory/indexdb.js
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);
}
}
7 changes: 7 additions & 0 deletions src/component/LocalHistory/localHistory.css
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;
}
32 changes: 32 additions & 0 deletions src/component/LocalHistory/preview.js
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;
Loading

0 comments on commit e8af3cc

Please sign in to comment.