UNPKG

dpu-onlyoffice-react

Version:

React component for OnlyOffice Document Server integration with version history support

477 lines (402 loc) โ€ข 12 kB
# dpu-onlyoffice-react A React component library for integrating OnlyOffice Document Server with React and Next.js applications. This package provides a clean, TypeScript-first API for viewing and editing Office documents with full version history support. ## Features - ๐Ÿ“„ **Document Viewing & Editing** - Support for Word, Excel, and PowerPoint documents - ๐Ÿ”„ **Version History** - Complete version management with restore capabilities - โšก **React 18+ & Next.js** - Optimized for modern React applications - ๐ŸŽฏ **TypeScript** - Full TypeScript support with comprehensive type definitions - ๐Ÿ› ๏ธ **Customizable** - Flexible configuration options and event handling - ๐Ÿงน **Memory Management** - Proper cleanup and instance management - ๐Ÿ“ฆ **Tree Shaking** - Optimized bundle size with ES modules ## Installation ```bash npm install dpu-onlyoffice-react # or yarn add dpu-onlyoffice-react # or pnpm add dpu-onlyoffice-react ``` ## Quick Start ### Basic Usage ```tsx import React from 'react'; import { DocumentEditor, OnlyOfficeConfig } from 'dpu-onlyoffice-react'; const MyComponent = () => { const config: OnlyOfficeConfig = { document: { fileType: 'docx', key: 'unique-document-key', title: 'My Document', url: 'https://example.com/document.docx', permissions: { edit: true, download: true, print: true } }, documentType: 'word', editorConfig: { mode: 'edit', lang: 'en', user: { id: 'user-123', name: 'John Doe' }, callbackUrl: 'https://your-api.com/callback' }, height: '100%', width: '100%' }; return ( <div style={{ height: '100vh' }}> <DocumentEditor config={config} editorKey="my-editor" onError={(error) => console.error('Editor error:', error)} /> </div> ); }; ``` ### Simple Data-Driven Usage (Recommended) ```tsx import React from 'react'; import { DocumentEditor, OnlyOfficeConfig, DocumentEventHandlers, refreshHistory, setHistoryData } from 'dpu-onlyoffice-react'; const MyComponent = ({ fileId, documentUrl }) => { // Your API functions const fetchVersionHistory = async (fileId) => { const response = await fetch(`/api/files/${fileId}/history`); return response.json(); }; const fetchHistoryData = async (fileId, version) => { const response = await fetch(`/api/files/${fileId}/history/${version}`); return response.json(); }; // Event handlers - you call API, library handles OnlyOffice const eventHandlers: DocumentEventHandlers = { onRequestHistory: async (event) => { try { const history = await fetchVersionHistory(fileId); refreshHistory(history, 'History loaded', fileId); } catch (error) { refreshHistory({ error: 'Failed to load history' }, 'Error', fileId); } }, onRequestHistoryData: async (event) => { try { const data = await fetchHistoryData(fileId, event.data); setHistoryData(data, fileId); } catch (error) { setHistoryData({ error: error.message }, fileId); } } }; const config: OnlyOfficeConfig = { document: { fileType: 'docx', key: fileId, title: 'My Document', url: documentUrl }, documentType: 'word', editorConfig: { mode: 'edit', user: { id: 'user-123', name: 'John Doe' } } }; return ( <div style={{ height: '100vh' }}> <DocumentEditor config={config} editorKey={fileId} eventHandlers={eventHandlers} onError={(error) => console.error('Editor error:', error)} /> </div> ); }; ``` ### With Version History ```tsx import React from 'react'; import { DocumentEditor, useOnlyOfficeEditor, OnlyOfficeConfig } from 'dpu-onlyoffice-react'; const DocumentWithHistory = ({ fileId }: { fileId: string }) => { const { createEventHandlers } = useOnlyOfficeEditor(); const config: OnlyOfficeConfig = { document: { fileType: 'docx', key: fileId, title: 'Document with History', url: `https://api.example.com/files/${fileId}/download` }, documentType: 'word', editorConfig: { mode: 'edit', user: { id: 'user-123', name: 'John Doe' } }, events: createEventHandlers({ fileId, onHistoryRequest: async (fileId) => { const response = await fetch(`/api/files/${fileId}/history`); return response.json(); }, onHistoryDataRequest: async (fileId, version) => { const response = await fetch(`/api/files/${fileId}/history/${version}`); return response.json(); }, onRestore: async (fileId, version) => { const response = await fetch(`/api/files/${fileId}/restore`, { method: 'POST', body: JSON.stringify({ version }) }); return response.json(); } }) }; return ( <div style={{ height: '100vh' }}> <DocumentEditor config={config} editorKey={fileId} /> </div> ); }; ``` ### Custom Script Loading ```tsx import React, { useEffect } from 'react'; import { loadOnlyOfficeScript, DocumentEditor } from '@dpu/onlyoffice-react'; const App = () => { useEffect(() => { // Load OnlyOffice script with custom configuration loadOnlyOfficeScript({ scriptUrl: 'https://your-onlyoffice-server.com/web-apps/apps/api/documents/api.js', fallbackUrl: 'https://backup-server.com/web-apps/apps/api/documents/api.js', timeout: 30000 }).catch(console.error); }, []); return ( <DocumentEditor config={config} editorKey="custom-editor" /> ); }; ``` ## API Reference ### DocumentEditor Props | Prop | Type | Required | Description | |------|------|----------|-------------| | `config` | `OnlyOfficeConfig` | โœ… | OnlyOffice configuration object | | `editorKey` | `string \| number` | โŒ | Unique key for editor instance (default: 1) | | `className` | `string` | โŒ | CSS class name for container | | `style` | `React.CSSProperties` | โŒ | Inline styles for container | | `onError` | `(error: Error) => void` | โŒ | Error callback function | ### OnlyOfficeConfig ```typescript interface OnlyOfficeConfig { document: { fileType: string; key: string; title: string; url: string; permissions?: { edit?: boolean; download?: boolean; print?: boolean; review?: boolean; }; }; documentType: 'word' | 'cell' | 'slide'; editorConfig: { mode?: 'edit' | 'view'; lang?: string; location?: string; customization?: { uiTheme?: string; logo?: { image?: string; url?: string; }; about?: { visible?: boolean; text?: string; }; feedback?: { visible?: boolean; url?: string; }; }; user?: { id: string; name: string; group?: string; }; callbackUrl?: string; coEditing?: { mode?: 'fast' | 'strict'; change?: boolean; }; }; height?: string | number; width?: string | number; events?: OnlyOfficeEvents; } ``` ### useOnlyOfficeEditor Hook ```typescript const { isLoading, error, setError, getEditorInstance, setEditorInstance, refreshHistory, setHistoryData, requestClose, destroyEditor, createEventHandlers } = useOnlyOfficeEditor(); ``` ### Script Loader Functions ```typescript // Load OnlyOffice script loadOnlyOfficeScript(options?: OnlyOfficeScriptOptions): Promise<void> // Check if script is loaded isOnlyOfficeScriptLoaded(): boolean // Reset script state (for testing) resetScriptState(): void // Get current script state getScriptState(): { loaded: boolean; loading: boolean; hasPromise: boolean } ``` ## Configuration ### OnlyOffice Server Setup 1. Install OnlyOffice Document Server 2. Configure your server URL in the script loader 3. Set up proper CORS headers 4. Configure callback URL for document saving ### Environment Variables ```bash # .env.local NEXT_PUBLIC_ONLYOFFICE_SERVER_URL=https://your-onlyoffice-server.com NEXT_PUBLIC_ONLYOFFICE_CALLBACK_URL=https://your-app.com/api/onlyoffice/callback ``` ## Examples ### Next.js Integration ```tsx // pages/document/[id].tsx import { GetServerSideProps } from 'next'; import { DocumentEditor, OnlyOfficeConfig } from 'dpu-onlyoffice-react'; interface DocumentPageProps { document: { id: string; title: string; url: string; fileType: string; }; } export default function DocumentPage({ document }: DocumentPageProps) { const config: OnlyOfficeConfig = { document: { fileType: document.fileType, key: document.id, title: document.title, url: document.url }, documentType: document.fileType.includes('word') ? 'word' : document.fileType.includes('excel') ? 'cell' : 'slide', editorConfig: { mode: 'edit', user: { id: 'current-user-id', name: 'Current User' }, callbackUrl: `${process.env.NEXT_PUBLIC_ONLYOFFICE_CALLBACK_URL}?documentId=${document.id}` } }; return ( <div style={{ height: '100vh' }}> <DocumentEditor config={config} editorKey={document.id} /> </div> ); } export const getServerSideProps: GetServerSideProps = async ({ params }) => { // Fetch document data from your API const document = await fetchDocument(params?.id as string); return { props: { document } }; }; ``` ### Error Handling ```tsx import React, { useState } from 'react'; import { DocumentEditor, OnlyOfficeConfig } from 'dpu-onlyoffice-react'; const DocumentWithErrorHandling = () => { const [error, setError] = useState<Error | null>(null); const config: OnlyOfficeConfig = { // ... your config }; if (error) { return ( <div style={{ padding: '20px', textAlign: 'center' }}> <h3>Error loading document</h3> <p>{error.message}</p> <button onClick={() => setError(null)}>Retry</button> </div> ); } return ( <DocumentEditor config={config} onError={setError} /> ); }; ``` ## Troubleshooting ### Common Issues 1. **Script Loading Errors** - Check OnlyOffice server URL - Verify CORS configuration - Check network connectivity 2. **Document Not Loading** - Verify document URL is accessible - Check document key uniqueness - Ensure proper file permissions 3. **Version History Issues** - Implement proper API endpoints - Check data format compatibility - Verify user permissions ### Debug Mode Enable debug logging by setting the log level: ```typescript // In your app initialization if (process.env.NODE_ENV === 'development') { console.log('OnlyOffice Debug Mode Enabled'); } ``` ## Contributing 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Support For support and questions: - Create an issue on GitHub - Check the [OnlyOffice Documentation](https://api.onlyoffice.com/) - Review the [React Documentation](https://reactjs.org/docs/) ## Changelog ### 1.0.0 - Initial release - React 18+ support - TypeScript definitions - Version history support - Memory management - Custom script loading