65.9K
CodeProject 正在变化。 阅读更多。
Home

集成 PrizmDoc Editor 并将工作流用于您的应用程序

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2019 年 4 月 11 日

CPOL
viewsIcon

4299

我将与您一起编写一个示例应用程序,该应用程序集成了 PrizmDoc Editor,并经历了相当基本(但典型)的工作流。

将近一年了,我一直致力于 Accusoft 最近发布的 PrizmDoc 编辑器,我真的很兴奋看到我们的客户如何将其集成到他们的产品中!最初我打算写一篇关于如何在您的应用程序中运行和嵌入 PrizmDoc 编辑器的文章,但是如果您看过我们的 入门指南,您就会知道它有多么容易。相反,我将与您一起编写一个示例应用程序,该应用程序集成了编辑器并完成一个非常基本(但典型)的工作流程。如果您还没有阅读入门指南,请立即阅读并确保您了解如何启动 Docker 容器。我会在这里等您。

我们的目标是创建一个名为 SketchyDocx 的应用程序,允许用户上传和编辑 DOCX 文件。我们将使用 React 创建示例的 UI,使用 handdrawn.css 进行样式设置,并(为了简化示例)使用 Parcel 来构建项目。我选择使用 yarn 作为我的包管理器,但 npm 也一样好用。如果您想克隆代码并一起学习,您可以在 GitHub 上找到它。

让我们从初始化项目和安装一些依赖项开始

yarn init
# Set up the project however you want, then:
yarn add react react-dom
yarn add -D parcel-bundler

现在让我们设置一些脚本和一个基本的 React 应用程序。package.json(根据您在 yarn init 中指定的內容,您的看起来会略有不同)

 {
 "name": "SketchyDocx",
 "version": "1.0.0",
 "description": "Sample application using PrizmDoc Editor",
 "main": "index.js",
 "author": "Joshua Letcher <jletcher@accusoft.com>",
 "license": "MIT",
 "scripts": {
   "start": "parcel src/index.html"
 },
 "dependencies": {
   "react": “^16.7.0",
   "react-dom": “^16.7.0"
 },
 "devDependencies": {
   "parcel-bundler": “^1.11.0"
 }
}

src/index.html

<!DOCTYPE html>
<html>
   <head>
       <title>SketchyDocx – PrizmDoc Editor Sample App</title>
       <link rel="stylesheet" type="text/css" href="http://fxaeberhard.github.io/handdrawn.css/handdrawn.css" />
   </head>
   <body>
       <div id="app"></div>
       <script src="index.jsx"></script>
   </body>
</html>

src/index.jsx

import React from "react";
import ReactDOM from "react-dom";

class SketchyDocx extends React.Component {
 render() {
   return <div>Hello SketchyDocx!</div>;
 }
}

var mountNode = document.getElementById("app");
ReactDOM.render(<SketchyDocx />, mountNode);

如果您现在运行 yarn start,Parcel 将为您构建项目并启动一个开发服务器,以便您可以在浏览器中访问它。默认位置应该是 https://:1234/

将文档上传到 PrizmDoc 编辑器

在我们的应用程序中开始使用 PrizmDoc 编辑器,首先需要为其提供一个要处理的文档。我们将通过创建一个 UploadArea 组件来实现,该组件允许用户拖动(或点击并选择)要上传的文档。

首先,让我们安装一个 dropzone 组件。

终结符

>#install react-dropzone with
>yarn add react-dropzone

现在我们可以用它来创建一个上传区域。由于我们在这个项目中没有使用 redux(为了简单起见),我们将让操作在我们的主组件 (SketchyDocx) 中进行,并通过 props 传递给 UploadArea。

src/components/UploadArea/index.jsx

import React from "react";
import Dropzone from ‘react-dropzone’;
class UploadArea extends React.Component {
    constructor(props) {
        super(props);
    }
render() {
    return (
        <Dropzone
            multiple={false}
            onDrop={this.props.uploadDocument}
            accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        >
            {({ getInputProps, getRootProps }) => {
                return (
                    <fieldset
                        {...getRootProps()}
                    >
                        <input {...getInputProps()} />
                        <div>
                            <i className="icon-cloud-upload"></i><br />
                            Drop your document here<br />
                            <span>or click to browse</span>
                        </div>
                    </fieldset>
                );
            }}
        </Dropzone>
    )
 }
};

并更新我们的入口点 (index.jsx) 以使用它。

src/index.jsx

import React from "react";
import ReactDOM from "react-dom";

import UploadArea from ‘./components/UploadArea’;

import config from ‘./config.json’;

class SketchyDocx extends React.Component {
    constructor(props) {
        super(props);

        this.uploadDocument = this.uploadDocument.bind(this);
        
        this.state = { documents: []};
    }
uploadDocument(files) {
    fetch(`${config.apiRoot}/api/v1/documents`, {
        method: ‘POST’,
        headers: {
            "Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        },
        body: files[0]
    }).then(response => response.json())
      .then(success => {
        this.setState({ documents: [ ...this.state.documents, { name: files[0].name,
documentId: success.documentId }]})
    })
    .catch(error => console.error(error));
}

render() {
    return (
        <div>
            <UploadArea uploadDocument={this.uploadDocument} />
        </div>
    );
 }
}

var mountNode = document.getElementById("app");
ReactDOM.render(<SketchyDocx />, mountNode);

uploadDocument 方法现在将上传 dropzone 接受的第一个文档到 PrizmDoc 编辑器,并在状态中保存返回的 documentId。很简单,对吧?

请注意,我还创建了一个 config.json 文件,以便我们可以轻松地编辑 API 的位置

{
    "apiRoot": "https://:21412"
}

如果您之前没有终止 yarn start 命令,您的浏览器页面将刷新,您将看到我们新奇的 UploadArea!确保您的 prizmdoc-editor 容器正在运行,然后尝试使用上传区域。如果一切顺利,您应该不会看到任何事情发生。令人兴奋!

让我们再添加一个组件,暂时只显示上传的文档,以便我们可以验证状态是否正确更新。

src/components/DocumentList.jsx

import React from "react";

class EditorContainer extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <table>
                <thead>
                    <tr>
                        <th>My Documents</th>
                    </tr>
                </thead>
                <tbody>
                    {this.props.documents.map((document) => {
                        return (
                            <tr key={document.documentId}>
                                <td>{document.name}</td>
                            </tr>
                        );
                    })}
                </tbody>
            </table>
        );
    }
};

export default EditorContainer;

现在只需在 src/index.jsx 中导入它并像这样更新您的渲染方法

render() {
    const { documents } = this.state;
    return (
        <div>
            <UploadArea uploadDocument={this.uploadDocument} />
            <DocumentList documents={documents} />
        </div>
    );
}

创建编辑会话和嵌入编辑器

好了,我们现在可以将文档上传到 PrizmDoc 编辑器了。下一步是允许我们编辑这些文档。如果您回顾入门指南,您会看到最好的方法是在您的应用程序中使用 iframe 嵌入编辑器,并且要使用的 URL 只是 {apiRoot}/?sessionId={sessionId}。看起来我们需要先创建一个会话,所以让我们向 SketchyDocx 组件添加一个方法来执行此操作。

src/index.jsx

...
class SketchyDocx extends React.Component {
    // Updated constructor to bind the createSession Method
    constructor(props) {
        super(props);

        this.uploadDocument = this.uploadDocument.bind(this);
        this.createSession = this.createSession.bind(this);

        this.state = { documents: []}
    }

createSession(documentId) {
    fetch(`${config.apiRoot}/api/v1/sessions`, {
        method: ‘POST’,
        headers: {
            ‘Content-Type’: ‘application/json’
        },
        body: JSON.stringify({
            documentId
        })
    }).then(response => response.json())
      .then(success => {
        this.setState({
            sessionId: success.sessionId
        });
    })
    .catch(error => console.error(error))
}

        ‘Content-Type’: ‘application/json’
    },
    body: JSON.stringify({
        documentId
    })
}).then(response => response.json())
  .then(success => {
    this.setState({
        sessionId: success.sessionId
    });
 })
 .catch(error => console.error(error))
 }
…

我们需要在某处调用此方法,因此我们将将其传递给 DocumentList,并使其在用户点击列表中的文档时为该文档创建编辑会话。

src/components/DocumentList.jsx

render() {
    return (
        <table>
            <thead>
                <tr>
                    <th>My Documents</th>
                </tr>
            </thead>
            <tbody>
                {this.props.documents.map((document) => {
                    return (
                        <tr key={document.documentId}>
                            <td><a onClick={() => this.props.createSession(document.
documentId)}>{document.name}</a></td>
                        </tr>
                    );
                })}
            </tbody>
        </table>
 );

src/index.jsx

render() {
    const { documents, sessionId } = this.state;
    return (
        <div>
            <UploadArea uploadDocument={this.uploadDocument} />
            <DocumentList createSession={this.createSession} documents={documents} />
        </div>
    );
}

最后,我们可以嵌入编辑器并让用户查看和修改他们的文档。

创建一个新组件来包含编辑器 iframe

src/components/EditorContainer/index.jsx

import React from "react";

class EditorContainer extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        if (!this.props.sessionId) {
            return (
                <div>
                    Select a document to open an editor!
                </div>
            );
        }
        const href = `${this.props.apiRoot}/?sessionId=${this.props.sessionId}`;
        return (
            <iframe style={{width: ‘100vw’, height: ‘100vh’}} src={href} />
        );
    }
};

export default EditorContainer;

并修改 SketchyDocx 渲染函数以显示此新组件

src/index.jsx

render() {
    const { documents, sessionId } = this.state;
    return (
    
        <div>
            <UploadArea uploadDocument={this.uploadDocument} />
            <DocumentList createSession={this.createSession} documents={documents} />
            <EditorContainer apiRoot={config.apiRoot} sessionId={sessionId} />
        </div>
    );
}

现在,用户不仅可以上传文档,还可以从列表中选择一个文档并进行编辑。

清理界面

我们现在已经介绍了在 PrizmDoc 编辑器中加载要编辑的文档的所有基础知识。现在我们将稍微清理一下这个示例界面。

src/index.jsx

render() {
    const { documents, sessionId } = this.state;
    return (
        <div>
            <h1>SketchyDocx</h1>
            <div style={{ display: ‘flex’, alignItems: ‘stretch’, height: ‘85vh’}}>
                <nav style={{ paddingRight: ‘15px’}}>
                    <UploadArea uploadDocument={this.uploadDocument} />
                    <DocumentList createSession={this.createSession} documents={documents} />
                </nav>
                <main style={{flexGrow: 2}}>
                    <EditorContainer apiRoot={config.apiRoot} sessionId={sessionId} />
                </main>
            </div>
        </div>
    );
}

src/components/EditorContainer/index.jsx

render() {
    if (!this.props.sessionId) {
        return (
            <div>
                Select a document to open an editor!
            </div>
        );
    }
    const href = `${this.props.apiRoot}/?sessionId=${this.props.sessionId}`;
    return (
        <iframe style={{width: ‘100%’, height: ‘100%’}} src={href} />
    );
}

src/components/DocumentList/index.jsx

render() {
    return (
        <table style={{width: ‘100%’}}>
            <thead>
                <tr>
                    <th>My Documents</th>
                </tr>
            </thead>
            <tbody>
                {this.props.documents.map((document) => {
                    return (
                        <tr key={document.documentId}>
                            <td><a style={{cursor: ‘pointer’}} onClick={() =>
                        this.props.createSession(document.documentId)}>{document.name}</a></td>
                        </tr>
                    );
                })}
            </tbody>
        </table>
    );
}

瞧:SketchyDocx

现在您知道了如何集成 PrizmDoc 编辑器,您可以分享您的作品并开始协同处理文档。所有代码示例都可在 GitHub 上找到。

© . All rights reserved.