Skip to content

Commit

Permalink
Merge pull request #14 from ONLYOFFICE/release/2.1.0
Browse files Browse the repository at this point in the history
Release/2.1.0
  • Loading branch information
LinneyS authored Jan 18, 2022
2 parents c2a4508 + ddc9fc7 commit 9b63040
Show file tree
Hide file tree
Showing 34 changed files with 1,253 additions and 80 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "src/onlyoffice/connector/browser/app_data"]
path = src/onlyoffice/connector/browser/app_data
url = https://github.com/ONLYOFFICE/document-templates
branch = main/new
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## 2.1.0
## Added
- support docxf and oform formats
- create blank docxf from creation menu
- "save as" in editor

## 2.0.0
## Added
- JWT support
Expand Down
49 changes: 28 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Plone ONLYOFFICE integration plugin
# Plone ONLYOFFICE integration plugin

This plugin allows users to edit office documents within [Plone](https://plone.org/) using ONLYOFFICE Docs packaged as Document Server - [Community or Enterprise Edition](#onlyoffice-docs-editions).

Expand All @@ -12,7 +12,7 @@ The plugin allows to:

Supported formats:

* For viewing and editing: DOCX, XLSX, PPTX.
* For viewing and editing: DOCX, XLSX, PPTX, DOCXF, OFORM.
* For viewing only: PDF, ODT, ODS, ODP, DOC, XLS, PPT.

## Installing ONLYOFFICE Docs
Expand Down Expand Up @@ -137,22 +137,25 @@ The table below will help you make the right choice.
| Pricing and licensing | Community Edition | Enterprise Edition |
| ------------- | ------------- | ------------- |
| | [Get it now](https://www.onlyoffice.com/download.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) | [Start Free Trial](https://www.onlyoffice.com/enterprise-edition-free.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) |
| Cost | FREE | [Go to the pricing page](https://www.onlyoffice.com/enterprise-edition.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) |
| | [Get it now](https://www.onlyoffice.com/download-docs.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone#docs-community) | [Start Free Trial](https://www.onlyoffice.com/download-docs.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone#docs-enterprise) |
| Cost | FREE | [Go to the pricing page](https://www.onlyoffice.com/docs-enterprise-prices.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) |
| Simultaneous connections | up to 20 maximum | As in chosen pricing plan |
| Number of users | up to 20 recommended | As in chosen pricing plan |
| License | GNU AGPL v.3 | Proprietary |
| **Support** | **Community Edition** | **Enterprise Edition** |
| Documentation | [Help Center](https://helpcenter.onlyoffice.com/server/docker/opensource/index.aspx) | [Help Center](https://helpcenter.onlyoffice.com/server/integration-edition/index.aspx) |
| **Support** | **Community Edition** | **Enterprise Edition** |
| Documentation | [Help Center](https://helpcenter.onlyoffice.com/installation/docs-community-index.aspx) | [Help Center](https://helpcenter.onlyoffice.com/installation/docs-enterprise-index.aspx) |
| Standard support | [GitHub](https://github.com/ONLYOFFICE/DocumentServer/issues) or paid | One year support included |
| Premium support | [Buy Now](https://www.onlyoffice.com/support.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) | [Buy Now](https://www.onlyoffice.com/support.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) |
| **Services** | **Community Edition** | **Enterprise Edition** |
| Conversion Service | + | + |
| Document Builder Service | + | + |
| Premium support | [Contact us](mailto:sales@onlyoffice.com) | [Contact us](mailto:sales@onlyoffice.com) |
| **Services** | **Community Edition** | **Enterprise Edition** |
| Conversion Service | + | + |
| Document Builder Service | + | + |
| **Interface** | **Community Edition** | **Enterprise Edition** |
| Tabbed interface | + | + |
| Dark theme | + | + |
| 125%, 150%, 175%, 200% scaling | + | + |
| White Label | - | - |
| Integrated test example (node.js) | - | + |
| Integrated test example (node.js) | + | + |
| Mobile web editors | - | +* |
| **Plugins & Macros** | **Community Edition** | **Enterprise Edition** |
| Plugins | + | + |
| Macros | + | + |
Expand All @@ -166,29 +169,33 @@ The table below will help you make the right choice.
| **Document Editor features** | **Community Edition** | **Enterprise Edition** |
| Font and paragraph formatting | + | + |
| Object insertion | + | + |
| Adding Content control | - | + |
| Adding Content control | + | + |
| Editing Content control | + | + |
| Layout tools | + | + |
| Table of contents | + | + |
| Navigation panel | + | + |
| Comparing Documents | - | +* |
| Mail Merge | + | + |
| Comparing Documents | + | + |
| **Spreadsheet Editor features** | **Community Edition** | **Enterprise Edition** |
| Font and paragraph formatting | + | + |
| Object insertion | + | + |
| Functions, formulas, equations | + | + |
| Table templates | + | + |
| Pivot tables | + | + |
| Conditional formatting for viewing | +** | +** |
| Sheet views | - | + |
| Data validation | + | + |
| Conditional formatting | + | + |
| Sparklines | + | + |
| Sheet Views | + | + |
| **Presentation Editor features** | **Community Edition** | **Enterprise Edition** |
| Font and paragraph formatting | + | + |
| Object insertion | + | + |
| Animations | + | + |
| Transitions | + | + |
| Presenter mode | + | + |
| Notes | + | + |
| | [Get it now](https://www.onlyoffice.com/download.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) | [Start Free Trial](https://www.onlyoffice.com/enterprise-edition-free.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone) |
\* It's possible to add documents for comparison from your local drive and from URL. Adding files for comparison from storage is not available yet.
\** Support for all conditions and gradient. Adding/Editing capabilities are coming soon
| **Form creator features** | **Community Edition** | **Enterprise Edition** |
| Adding form fields | + | + |
| Form preview | + | + |
| Saving as PDF | + | + |
| | [Get it now](https://www.onlyoffice.com/download-docs.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone#docs-community) | [Start Free Trial](https://www.onlyoffice.com/download-docs.aspx?utm_source=github&utm_medium=cpc&utm_campaign=GitHubPlone#docs-enterprise) |
\* If supported by DMS.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

setup(
name='onlyoffice.connector',
version='2.0.0',
version='2.1.0',
description="Plone ONLYOFFICE integration plugin",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
135 changes: 128 additions & 7 deletions src/onlyoffice/connector/browser/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,28 @@
from zope.component import getMultiAdapter
from zope.component import getUtility
from zope.publisher.interfaces import NotFound
from plone.app.uuid.utils import uuidToObject
from plone.protect.utils import addTokenToUrl
from Acquisition import aq_inner
from Acquisition import aq_parent
from plone.app.dexterity.interfaces import IDXFileFactory
from zExceptions import BadRequest
from plone.app.content.utils import json_dumps
from AccessControl import getSecurityManager
from Products.CMFPlone.permissions import AddPortalContent
from Products.CMFCore.utils import getToolByName
from onlyoffice.connector.core.config import Config
from onlyoffice.connector.core import fileUtils
from onlyoffice.connector.core import utils
from onlyoffice.connector.core import featureUtils
from onlyoffice.connector.interfaces import logger
from onlyoffice.connector.interfaces import _
from urllib.request import urlopen
from onlyoffice.connector.interfaces import _

import json
import os
import mimetypes

class Edit(form.EditForm):
def isAvailable(self):
Expand All @@ -44,7 +59,29 @@ def isAvailable(self):

def __call__(self):
self.docUrl = Config(getUtility(IRegistry)).docUrl
self.saveAs = featureUtils.getSaveAsObject(self.context)
self.editorCfg = get_config(self, True)
self.relatedItemsOptions = json.dumps(fileUtils.getRelatedRtemsOptions(self.context))
self.token = get_token(self)
if not self.editorCfg:
index = ViewPageTemplateFile("templates/error.pt")
return index(self)
return self.index()

class FillForm(form.EditForm):
def isAvailable(self):
filename = self.context.file.filename
return fileUtils.canFillForm(filename)

docUrl = None
editorCfg = None

def __call__(self):
self.docUrl = Config(getUtility(IRegistry)).docUrl
self.saveAs = featureUtils.getSaveAsObject(self.context)
self.editorCfg = get_config(self, True)
self.relatedItemsOptions = json.dumps(fileUtils.getRelatedRtemsOptions(self.context))
self.token = get_token(self)
if not self.editorCfg:
index = ViewPageTemplateFile("templates/error.pt")
return index(self)
Expand All @@ -60,27 +97,35 @@ def isAvailable(self):

def __call__(self):
self.docUrl = Config(getUtility(IRegistry)).docUrl
self.saveAs = featureUtils.getSaveAsObject(self.context)
self.editorCfg = get_config(self, False)
self.relatedItemsOptions = json.dumps(fileUtils.getRelatedRtemsOptions(self.context))
self.token = get_token(self)
if not self.editorCfg:
index = ViewPageTemplateFile("templates/error.pt")
return index(self)
return self.index()

def portal_state(self):
context = aq_inner(self.context)
portal_state = getMultiAdapter((context, self.request), name=u'plone_portal_state')
return portal_state

def get_token(self):
authenticator = getMultiAdapter((self.context, self.request), name="authenticator")

return authenticator.token()

def get_config(self, forEdit):
# def viewURLFor(self, item):
# cstate = getMultiAdapter((item, item.REQUEST), name='plone_context_state')
# return cstate.view_url()

def portal_state(self):
context = aq_inner(self.context)
portal_state = getMultiAdapter((context, self.request), name=u'plone_portal_state')
return portal_state

logger.info("getting config for " + self.context.absolute_url())
canEdit = forEdit and bool(getSecurityManager().checkPermission('Modify portal content', self.context))

filename = self.context.file.filename
if not fileUtils.canView(filename) or (forEdit and not fileUtils.canEdit(filename)):
if not fileUtils.canView(filename) or (forEdit and not fileUtils.canEdit(filename) and not fileUtils.canFillForm(filename)):
# self.request.response.status = 500
# self.request.response.setHeader('Location', self.viewURLFor(self.context))
return None
Expand Down Expand Up @@ -199,4 +244,80 @@ def _getFile(self):
if file is None:
raise NotFound(self, self.fieldname, self.request)

return file
return file

class Create(BrowserView):
def __call__(
self,
documentType
):
fileName = fileUtils.getDefaultNameByType(documentType)
fileExt = fileUtils.getDefaultExtByType(documentType)

if fileName is None or fileExt is None:
raise NotFound(self, documentType, self.request)

template = 'new.' + fileExt

state = portal_state(self)
language = state.language()

localePath = fileUtils.localePath.get(language)
if localePath is None:
language = language.split('-')[0]
localePath = fileUtils.localePath.get(language)
if localePath is None:
localePath = fileUtils.localePath.get('en')

file = open(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'app_data', localePath, template), 'rb')

try:
data = file.read()
finally:
file.close()

factory = IDXFileFactory(self.context)
contentType = mimetypes.guess_type(template)[0] or ''

file = factory(fileName + '.' + fileExt, contentType, data)

self.request.response.redirect(addTokenToUrl('{0}/onlyoffice-edit'.format(file.absolute_url())))

class SaveAs(BrowserView):
def __call__(self):
body = json.loads(self.request.get('BODY'))
url = body.get('url')
fileType = body.get('fileType')
fileTitle = body.get('fileTitle')
folderUID = body.get('folderUID')

if not url or not fileType or not fileTitle:
raise BadRequest(u'Required url or fileType or fileTitle parameters not found.')

if not folderUID:
portal_url = getToolByName(self.context, "portal_url")
folder = portal_url.getPortalObject()
else:
folder = uuidToObject(folderUID)

if not getSecurityManager().checkPermission(AddPortalContent, folder):
response = self.request.RESPONSE
response.setStatus(403)
return "You are not authorized to add content to this folder."

fileName = fileUtils.getCorrectFileName(fileTitle + "." + fileType)
contentType = mimetypes.guess_type(fileName)[0] or ''

data = urlopen(url).read()

factory = IDXFileFactory(folder)
file = factory(fileName, contentType, data)

self.request.response.setHeader(
"Content-Type", "application/json; charset=utf-8"
)

return json_dumps({
"status": "success",
"fileName": fileName
})
1 change: 1 addition & 0 deletions src/onlyoffice/connector/browser/app_data
Submodule app_data added at 47e28a
37 changes: 37 additions & 0 deletions src/onlyoffice/connector/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
/>
-->

<browser:resourceDirectory
name="onlyoffice-static"
directory="static" />

<browser:page
name="onlyoffice-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
Expand All @@ -37,6 +41,14 @@
template="templates/view.pt"
/>

<browser:page
name="onlyoffice-fill-form"
for="plone.app.contenttypes.interfaces.IFile"
class=".api.FillForm"
permission="cmf.ModifyPortalContent"
template="templates/view.pt"
/>

<browser:page
name="onlyoffice-callback"
for="plone.app.contenttypes.interfaces.IFile"
Expand All @@ -60,4 +72,29 @@
permission="zope2.View"
/>

<adapter for="* *"
name="plone.contentmenu.onlyoffice.create"
factory=".menu.OnlyofficeCreateSubMenuItem"
provides="plone.app.contentmenu.interfaces.IContentMenuItem" />

<browser:menu
id="plone_contentmenu_onlyoffice_create"
title="The 'Create in ONLYOFFICE' menu - allows the user to add new document, spredsheet or presentation"
class=".menu.OnlyofficeCreateMenu"
/>

<browser:page
for="*"
name="onlyoffice-create"
class=".api.Create"
permission="cmf.AddPortalContent"
/>

<browser:page
name="onlyoffice-save-as"
for="plone.app.contenttypes.interfaces.IFile"
class=".api.SaveAs"
permission="zope2.View"
/>

</configure>
Loading

0 comments on commit 9b63040

Please sign in to comment.