mirror of
https://github.com/ONLYOFFICE/document-server-integration.git
synced 2026-04-07 14:06:11 +08:00
Compare commits
118 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e34ed7f67 | |||
| eee6246d0c | |||
| 36513d3544 | |||
| fafc3d3d4f | |||
| c1e4abf362 | |||
| 06c1c1bf21 | |||
| 24a2e0bd14 | |||
| 05cd67a2f1 | |||
| 6f691b6b9f | |||
| 85e3f83d84 | |||
| b00a4dba31 | |||
| 3d12d3c38c | |||
| 5d0f190dc8 | |||
| 2782f8f9bd | |||
| 54ed6d8913 | |||
| 75e14c9452 | |||
| e1b800aa69 | |||
| 4e69a7dfa5 | |||
| 61cbba05f3 | |||
| ab03bb5490 | |||
| 1deeade91e | |||
| 417bd3b9f2 | |||
| c3fa000cea | |||
| f8484cfe0e | |||
| b396419d05 | |||
| 2d4490e21a | |||
| 61295628de | |||
| 90c7a8440e | |||
| 40eada3a17 | |||
| 66d977abaf | |||
| e259b303be | |||
| 4d091e892e | |||
| 34bc5d53ee | |||
| 3b514b7f5f | |||
| ee0c1571f6 | |||
| ba5a4e64f5 | |||
| 500f93deb8 | |||
| b732f6e8cc | |||
| a815d30725 | |||
| b9e70b913a | |||
| 31cd3c2dad | |||
| 2082d24132 | |||
| cdf629e863 | |||
| 6b8623795d | |||
| 38e32a69f8 | |||
| 3180d00b2d | |||
| 9d3f4731d6 | |||
| f44659ac7c | |||
| badc6644c2 | |||
| 3bf8d72454 | |||
| aebcbe058e | |||
| 15de3e414f | |||
| f3718a0f44 | |||
| 6227d9c965 | |||
| 90e7922d7c | |||
| e3f42fffba | |||
| 6ea3293a96 | |||
| b36668468e | |||
| 5c3c0b4361 | |||
| a9b82a299a | |||
| 07d11f0bae | |||
| 60992ecb38 | |||
| af4cfa8074 | |||
| 922143bf37 | |||
| 6d0312feee | |||
| d876e04b9e | |||
| 9295d83609 | |||
| 6c022134d0 | |||
| 97fc45a15c | |||
| 487adb11a7 | |||
| c052bbae31 | |||
| 667ff98142 | |||
| 304d628dbe | |||
| 50b9aa4296 | |||
| 76dd0b6d7b | |||
| 25ccda7e89 | |||
| b3dd5bc15d | |||
| 46961db654 | |||
| 4790aa074e | |||
| 0392ffbc9a | |||
| b6b980de92 | |||
| 06e93c5b0f | |||
| d75bcb85c9 | |||
| c1bd8458fb | |||
| bd2a94176e | |||
| c16359b1c0 | |||
| 73f7b31bfa | |||
| 2ea4dbf289 | |||
| cb54ca9821 | |||
| 0278fd05e2 | |||
| 511301260b | |||
| 0e454c8def | |||
| 334f60cdac | |||
| fecc69a00e | |||
| 22cf4c7c24 | |||
| c780ed127c | |||
| 9cea54a949 | |||
| 4d3059ffa0 | |||
| 22179d6c4f | |||
| 9dd43e892b | |||
| 675511fb0e | |||
| bfc7ee2ad6 | |||
| c03e4f3896 | |||
| f23f0bd3d3 | |||
| f451a7032d | |||
| 312209cd5a | |||
| fa346a0c27 | |||
| 12f88044b7 | |||
| 0e0eea3ebd | |||
| b5ef247245 | |||
| 5645a0fc2c | |||
| a9a48d5816 | |||
| b6cb5150dd | |||
| 667b9abc0d | |||
| e34cdf0098 | |||
| e321503dca | |||
| 4d64347fb9 | |||
| bfb202dd4f |
@ -112,10 +112,18 @@ express - Fast, unopinionated, minimalist web framework for node. (https:/
|
||||
License: MIT
|
||||
License File: express.license
|
||||
|
||||
fast-xml-parser - Validate XML, Parse XML to JS/JSON and vice versa, or parse XML to Nimn rapidly without C/C++ based libraries and no callback. (https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/LICENSE)
|
||||
License: MIT
|
||||
License File: fast-xml-parser.license
|
||||
|
||||
formidable - A Node.js module for parsing form data, especially file uploads. (https://github.com/node-formidable/formidable/blob/master/LICENSE)
|
||||
License: MIT
|
||||
License File: formidable.license
|
||||
|
||||
he - a robust HTML entity encoder/decoder written in JavaScript. (https://github.com/mathiasbynens/he/blob/master/LICENSE-MIT.txt)
|
||||
License: MIT
|
||||
License File: he.license
|
||||
|
||||
jQuery - jQuery is a new kind of JavaScript Library. jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. NOTE: This package is maintained on behalf of the library owners by the NuGet Community Packages project at https://nugetpackages.codeplex.com/ (https://jquery.org/license/)
|
||||
License: MIT
|
||||
License File: jQuery.license
|
||||
|
||||
@ -308,6 +308,28 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
// get image url for templates
|
||||
public static string GetTemplateImageUrl(FileUtility.FileType fileType)
|
||||
{
|
||||
var path = new UriBuilder(GetServerUrl(true)) // templates image url in the "From Template" section
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "Content\\images\\"
|
||||
};
|
||||
switch (fileType)
|
||||
{
|
||||
case FileUtility.FileType.Word: // for word file type
|
||||
return path + "file_docx.svg";
|
||||
case FileUtility.FileType.Cell: // for cell file type
|
||||
return path + "file_xlsx.svg";
|
||||
case FileUtility.FileType.Slide: // for slide file type
|
||||
return path + "file_pptx.svg";
|
||||
default:
|
||||
return path + "file_docx.svg"; // the default value
|
||||
}
|
||||
}
|
||||
|
||||
// get file information
|
||||
public static List<Dictionary<string, object>> GetFilesInfo(string fileId = null)
|
||||
{
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OnlineEditorsExampleMVC.Helpers
|
||||
{
|
||||
@ -25,43 +26,106 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
static List<string> descr_user_1 = new List<string>()
|
||||
{
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_2 = new List<string>()
|
||||
{
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_3 = new List<string>()
|
||||
{
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
{
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
};
|
||||
|
||||
private static List<User> users = new List<User>() {
|
||||
new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, new List<string>(), descr_user_1),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", new List<string>() { "group-2", "" }, true, new List<string>(), descr_user_2),
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", new List<string>() { "group-2" }, false, new List<string>() { "copy", "download", "print" }, descr_user_3),
|
||||
new User("uid-0", null, null, null, null, null, new List<string>(), descr_user_0)
|
||||
new User(
|
||||
"uid-1",
|
||||
"John Smith",
|
||||
"smith@mail.ru",
|
||||
null,
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true
|
||||
),
|
||||
new User(
|
||||
"uid-2",
|
||||
"Mark Pottato",
|
||||
"pottato@mail.ru",
|
||||
"group-2",
|
||||
new List<string>() { "group-2", "" },
|
||||
new Dictionary<string, object>()
|
||||
{
|
||||
{ "view", "" },
|
||||
{ "edit", new List<string>() { "group-2", "" } },
|
||||
{ "remove", new List<string>() { "group-2" } }
|
||||
},
|
||||
true,
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
false
|
||||
),
|
||||
new User(
|
||||
"uid-3",
|
||||
"Hamish Mitchell",
|
||||
"mitchell@mail.ru",
|
||||
"group-3",
|
||||
new List<string>() { "group-2" },
|
||||
new Dictionary<string,object>()
|
||||
{
|
||||
{ "view", new List<string>() { "group-2", "group-3" } },
|
||||
{ "edit", new List<string>() { "group-2" } },
|
||||
{ "remove", new List<string>() { } }
|
||||
},
|
||||
false,
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
false
|
||||
),
|
||||
new User(
|
||||
"uid-0",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new Dictionary<string,object>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_0,
|
||||
false
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
public static User getUser(string id)
|
||||
{
|
||||
foreach(User user in users)
|
||||
@ -75,6 +139,23 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, object>> getUsersForMentions(string id)
|
||||
{
|
||||
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
|
||||
foreach (User user in users)
|
||||
{
|
||||
if (!user.id.Equals(id) && user.name != null && user.email != null)
|
||||
{
|
||||
usersData.Add(new Dictionary<string, object>()
|
||||
{
|
||||
{"name", user.name },
|
||||
{"email", user.email }
|
||||
});
|
||||
}
|
||||
}
|
||||
return usersData;
|
||||
}
|
||||
}
|
||||
|
||||
public class User
|
||||
@ -84,21 +165,24 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
public string email;
|
||||
public string group;
|
||||
public List<string> reviewGroups;
|
||||
public Dictionary<string, object> commentGroups;
|
||||
public bool? favorite;
|
||||
public List<string> deniedPermissions;
|
||||
public List<string> descriptions;
|
||||
public bool templates;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions)
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.group = group;
|
||||
this.reviewGroups = reviewGroups;
|
||||
this.commentGroups = commentGroups;
|
||||
this.favorite = favorite;
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,11 +65,6 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
get { return DocManagerHelper.GetCallback(FileName); }
|
||||
}
|
||||
|
||||
public string CreateUrl
|
||||
{
|
||||
get { return DocManagerHelper.GetCreateUrl(FileUtility.GetFileType(FileName)); }
|
||||
}
|
||||
|
||||
public string DownloadUrl
|
||||
{
|
||||
get { return DocManagerHelper.GetDownloadUrl(FileName); }
|
||||
@ -96,6 +91,24 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
var actionLink = request.GetOrDefault("actionLink", null); // get the action link (comment or bookmark) if it exists
|
||||
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink); // get action data for the action link
|
||||
|
||||
var createUrl = DocManagerHelper.GetCreateUrl(FileUtility.GetFileType(FileName));
|
||||
var templatesImageUrl = DocManagerHelper.GetTemplateImageUrl(FileUtility.GetFileType(FileName)); // image url for templates
|
||||
var templates = new List<Dictionary<string, string>>
|
||||
{
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "image", templatesImageUrl },
|
||||
{ "title", "Blank" },
|
||||
{ "url", createUrl },
|
||||
},
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "image", templatesImageUrl },
|
||||
{ "title", "With sample content" },
|
||||
{ "url", createUrl + "&sample=true" },
|
||||
}
|
||||
};
|
||||
|
||||
// specify the document config
|
||||
var config = new Dictionary<string, object>
|
||||
{
|
||||
@ -129,7 +142,8 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{ "modifyFilter", editorsMode != "filter" },
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
|
||||
{ "reviewGroups", user.reviewGroups }
|
||||
{ "reviewGroups", user.reviewGroups },
|
||||
{ "commentGroups", user.commentGroups }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,7 +155,8 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{ "mode", mode },
|
||||
{ "lang", request.Cookies.GetOrDefault("ulang", "en") },
|
||||
{ "callbackUrl", CallbackUrl }, // absolute URL to the document storage service
|
||||
{ "createUrl", CreateUrl },
|
||||
{ "createUrl", !user.id.Equals("uid-0") ? createUrl : null },
|
||||
{ "templates", user.templates ? templates : null },
|
||||
{
|
||||
// the user currently viewing or editing the document
|
||||
"user", new Dictionary<string, object>
|
||||
@ -241,13 +256,16 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "changes.json")));
|
||||
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
obj.Add("changes", changes["changes"]);
|
||||
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change["created"]);
|
||||
obj.Add("user", change["user"]);
|
||||
obj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
obj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
@ -365,5 +383,14 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
|
||||
dataMailMergeRecipients = jss.Serialize(mailMergeConfig);
|
||||
}
|
||||
|
||||
//get a users for mentions
|
||||
public void GetUsersMentions(HttpRequest request, out string usersForMentions)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var id = request.Cookies.GetOrDefault("uid", null);
|
||||
var user = Users.getUser(id);
|
||||
usersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(Users.getUsersForMentions(user.id)) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,7 +149,6 @@
|
||||
<Content Include="favicon.ico" />
|
||||
<Content Include="Global.asax" />
|
||||
<Content Include="LICENSE" />
|
||||
<Content Include="ReadMe.txt" />
|
||||
<Content Include="Scripts\jquery-1.8.2.js" />
|
||||
<Content Include="Scripts\jquery-ui.js" />
|
||||
<Content Include="Scripts\jquery.blockUI.js" />
|
||||
|
||||
@ -1,35 +1,34 @@
|
||||
## How to integrate online editors into your own web site on .Net (C# MVC)
|
||||
### Introduction
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **.Net (C# MVC)** you need to download and install ONLYOFFICE editors on your local server and use the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) for their integration.
|
||||
## Overview
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in .Net (C# MVC).
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
### Step 1. Download and Install Document Server
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_csharp_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_csharp_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_csharp_example).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
### Step 2. Download the .Net (C# MVC) code for the editors integration
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx).
|
||||
|
||||
## Step 2. Download the .Net (C# MVC) code for the editors integration
|
||||
|
||||
Download the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
You need to connnect the editors to your web site. For that specify the path to the editors installation in the *settings.config* file:
|
||||
You need to connnect the editors to your web site. Specify path to the editors installation in the *settings.config* file:
|
||||
```
|
||||
<add key="files.docservice.url.site" value="https://documentserver/" />
|
||||
```
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *DocEditor.aspx* file.
|
||||
|
||||
### Step 3. Install the prerequisites
|
||||
To run your website with the editors successfully, check if your system meets the necessary system requirements:
|
||||
## Step 3. Install the prerequisites
|
||||
Сheck if your system meets the system requirements:
|
||||
* Microsoft .NET Framework: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
|
||||
* Internet Information Services: version 7 or later.
|
||||
|
||||
### Step 4. Running your web site with the editors
|
||||
## Step 4. Run your website with the editors
|
||||
1. Run the Internet Information Service (IIS) manager
|
||||
Start -> ControlPanel -> System and Security -> Administrative Tools -> Internet Information Services (IIS) Manager
|
||||
2. Add your web site in the IIS Manager
|
||||
2. Add your website in the IIS Manager
|
||||
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
|
||||

|
||||
3. In the **Add Website** dialog box specify the name of the folder with the .Net (C# MVC) project in the **Site name** box.
|
||||
@ -39,11 +38,12 @@ To run your website with the editors successfully, check if your system meets th
|
||||
4. Check for the .NET platform version specified in IIS manager for you web site. Choose **v4.0.** version.
|
||||
Click the **Application Pool** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
|
||||

|
||||
5. Browse your web site with the IIS manager:
|
||||
5. Browse your website with the IIS manager:
|
||||
Right-click the site -> **Manage Website** -> **Browse**
|
||||

|
||||
|
||||
### Step 5. Checking accessibility
|
||||
## Step 5. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
@ -173,6 +173,24 @@
|
||||
};
|
||||
<% } %>
|
||||
|
||||
<% string usersForMentions; %>
|
||||
<% Model.GetUsersMentions(Request, out usersForMentions); %>
|
||||
<% if (!string.IsNullOrEmpty(usersForMentions))
|
||||
// add mentions for not anonymous users
|
||||
{ %>
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": <%= usersForMentions%>
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
Submodule web/documentserver-example/csharp-mvc/assets updated: 4a1673c5ca...65addf50e4
@ -11,7 +11,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="icon" href="<%= "app_themes/images/" + documentType + ".ico" %>" type="image/x-icon" />
|
||||
<link rel="icon" href="<%= "app_themes/images/" + DocumentType + ".ico" %>" type="image/x-icon" />
|
||||
<title>ONLYOFFICE</title>
|
||||
<!--
|
||||
*
|
||||
@ -133,18 +133,18 @@
|
||||
var onRequestInsertImage = function (event) {
|
||||
docEditor.insertImage({ // insert an image into the file
|
||||
"c": event.data.c,
|
||||
<%= InsertImageConfig%>
|
||||
<%= InsertImageConfig %>
|
||||
})
|
||||
};
|
||||
|
||||
// the user is trying to select document for comparing by clicking the Document from Storage button
|
||||
var onRequestCompareFile = function () {
|
||||
docEditor.setRevisedFile(<%= compareFileData%>); // select a document for comparing
|
||||
docEditor.setRevisedFile(<%= CompareFileData %>); // select a document for comparing
|
||||
};
|
||||
|
||||
// the user is trying to select recipients data by clicking the Mail merge button
|
||||
var onRequestMailMergeRecipients = function (event) {
|
||||
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>); // insert recipient data for mail merge into the file
|
||||
docEditor.setMailMergeRecipients(<%= DataMailMergeRecipients %>); // insert recipient data for mail merge into the file
|
||||
};
|
||||
|
||||
var config = <%= DocConfig %>;
|
||||
@ -180,6 +180,22 @@
|
||||
};
|
||||
<% } %>
|
||||
|
||||
<% if (!string.IsNullOrEmpty(UsersForMentions))
|
||||
{ %>
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": <%= UsersForMentions %>
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
@ -64,9 +64,10 @@ namespace OnlineEditorsExample
|
||||
protected string History { get; private set; }
|
||||
protected string HistoryData { get; private set; }
|
||||
protected string InsertImageConfig { get; private set; }
|
||||
protected string compareFileData { get; private set; }
|
||||
protected string dataMailMergeRecipients { get; private set; }
|
||||
protected string documentType { get { return _Default.DocumentType(FileName); } }
|
||||
protected string CompareFileData { get; private set; }
|
||||
protected string DataMailMergeRecipients { get; private set; }
|
||||
protected string UsersForMentions { get; private set; }
|
||||
protected string DocumentType { get { return _Default.DocumentType(FileName); } }
|
||||
|
||||
// get callback url
|
||||
public static string CallbackUrl
|
||||
@ -160,11 +161,29 @@ namespace OnlineEditorsExample
|
||||
var actionLink = Request.GetOrDefault("actionLink", null); // get the action link (comment or bookmark) if it exists
|
||||
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink); // get action data for the action link
|
||||
|
||||
var createUrl = getCreateUrl(DocumentType, editorsType);
|
||||
var templatesImageUrl = GetTemplateImageUrl(ext); // image url for templates
|
||||
var templates = new List<Dictionary<string, string>>
|
||||
{
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "image", templatesImageUrl },
|
||||
{ "title", "Blank" },
|
||||
{ "url", createUrl }
|
||||
},
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "image", templatesImageUrl },
|
||||
{ "title", "With sample content" },
|
||||
{ "url", createUrl + "&sample=true" }
|
||||
}
|
||||
};
|
||||
|
||||
// specify the document config
|
||||
var config = new Dictionary<string, object>
|
||||
{
|
||||
{ "type", editorsType },
|
||||
{ "documentType", documentType },
|
||||
{ "documentType", DocumentType },
|
||||
{
|
||||
"document", new Dictionary<string, object>
|
||||
{
|
||||
@ -193,7 +212,8 @@ namespace OnlineEditorsExample
|
||||
{ "modifyFilter", editorsMode != "filter" },
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
|
||||
{ "reviewGroups", user.reviewGroups }
|
||||
{ "reviewGroups", user.reviewGroups },
|
||||
{ "commentGroups", user.commentGroups }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,7 +225,8 @@ namespace OnlineEditorsExample
|
||||
{ "mode", mode },
|
||||
{ "lang", Request.Cookies.GetOrDefault("ulang", "en") },
|
||||
{ "callbackUrl", CallbackUrl }, // absolute URL to the document storage service
|
||||
{ "createUrl", getCreateUrl(documentType, editorsType)},
|
||||
{ "createUrl", !user.id.Equals("uid-0") ? createUrl : null },
|
||||
{ "templates", user.templates ? templates : null },
|
||||
{
|
||||
// the user currently viewing or editing the document
|
||||
"user", new Dictionary<string, object>
|
||||
@ -263,12 +284,15 @@ namespace OnlineEditorsExample
|
||||
|
||||
// a document which will be compared with the current document
|
||||
Dictionary<string, object> compareFile = GetCompareFile();
|
||||
compareFileData = jss.Serialize(compareFile);
|
||||
CompareFileData = jss.Serialize(compareFile);
|
||||
|
||||
// recipient data for mail merging
|
||||
Dictionary<string, object> mailMergeConfig = GetMailMergeConfig();
|
||||
dataMailMergeRecipients = jss.Serialize(mailMergeConfig);
|
||||
DataMailMergeRecipients = jss.Serialize(mailMergeConfig);
|
||||
|
||||
// get users for mentions
|
||||
List<Dictionary<string, object>> usersData = Users.getUsersForMentions(user.id);
|
||||
UsersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(usersData) : null;
|
||||
|
||||
Dictionary<string, object> hist;
|
||||
Dictionary<string, object> histData;
|
||||
@ -331,13 +355,16 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i - 1), "changes.json")));
|
||||
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
obj.Add("changes", changes["changes"]);
|
||||
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change["created"]);
|
||||
obj.Add("user", change["user"]);
|
||||
obj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
obj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
@ -444,6 +471,28 @@ namespace OnlineEditorsExample
|
||||
return mailMergeConfig;
|
||||
}
|
||||
|
||||
// get image url for templates
|
||||
private string GetTemplateImageUrl (string ext)
|
||||
{
|
||||
var path = new UriBuilder(_Default.GetServerUrl(true)) // templates image url in the "From Template" section
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "App_Themes\\images\\"
|
||||
};
|
||||
switch (ext)
|
||||
{
|
||||
case ".docx":
|
||||
return path + "file_docx.svg"; // for word document type
|
||||
case ".xlsx":
|
||||
return path + "file_xlsx.svg"; // .xlsx for cell document type
|
||||
case ".pptx":
|
||||
return path + "file_pptx.svg"; // .pptx for slide document type
|
||||
default:
|
||||
return path + "file_docx.svg"; // the default value
|
||||
}
|
||||
}
|
||||
|
||||
// create the public url
|
||||
private string MakePublicUrl(string fullPath)
|
||||
{
|
||||
|
||||
@ -91,7 +91,6 @@
|
||||
<Content Include="App_Themes\images\word.ico" />
|
||||
<Content Include="LICENSE" />
|
||||
<Content Include="licenses\jquery.license" />
|
||||
<Content Include="ReadMe.txt" />
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@ -1,49 +1,52 @@
|
||||
## How to integrate online editors into your own web site on .Net (C#)
|
||||
### Introduction
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **.Net (C#)** you need to download and install ONLYOFFICE editors on your local server and use the [.Net (C#) example](https://api.onlyoffice.com/editors/demopreview) for their integration.
|
||||
## Overview
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in .Net (C#).
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
### Step 1. Download and Install Document Server
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_csharp_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_csharp_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_csharp_example).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
### Step 2. Download the .Net (C#) code for the editors integration
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx).
|
||||
|
||||
## Step 2. Download the .Net (C#) code for the editors integration
|
||||
|
||||
Download the [.Net (C#) example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
You need to connnect the editors to your web site. For that specify the path to the editors installation in the *settings.config* file:
|
||||
|
||||
Connect the editors to your website by specifying the path to the editors installation in the *settings.config* file:
|
||||
```
|
||||
<add key="files.docservice.url.site" value="https://documentserver/" />
|
||||
```
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *DocEditor.aspx* file.
|
||||
|
||||
### Step 3. Install the prerequisites
|
||||
To run your website with the editors successfully, check if your system meets the necessary system requirements:
|
||||
## Step 3. Install the prerequisites
|
||||
|
||||
Check that your system meets the requirements:
|
||||
* Microsoft .NET Framework: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
|
||||
* Internet Information Services: version 7 or later.
|
||||
|
||||
### Step 4. Running your web site with the editors
|
||||
## Step 4. Run your website with the editors
|
||||
1. Run the Internet Information Service (IIS) manager
|
||||
Start -> ControlPanel -> System and Security -> Administrative Tools -> Internet Information Services (IIS) Manager
|
||||
2. Add your web site in the IIS Manager
|
||||
2. Add your website in the IIS Manager
|
||||
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
|
||||

|
||||
3. In the **Add Website** dialog box specify the name of the folder with the .Net (C#) project in the **Site name** box.
|
||||
Specify the path to the folder with your project in the **Physical Path** box.
|
||||
Specify the unique value used only for this website in the **Port** box.
|
||||

|
||||
4. Check for the .NET platform version specified in IIS manager for you web site. Choose **v4.0.** version.
|
||||
4. Check for the .NET platform version specified in IIS manager for you website. Choose **v4.0.** version.
|
||||
Click the **Application Pool** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
|
||||

|
||||
5. Browse your web site with the IIS manager:
|
||||
5. Browse your website with the IIS manager:
|
||||
Right-click the site -> **Manage Website** -> **Browse**
|
||||

|
||||
|
||||
### Step 5. Checking accessibility
|
||||
## Step 5. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
Make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
@ -25,41 +25,104 @@ namespace OnlineEditorsExample
|
||||
static List<string> descr_user_1 = new List<string>()
|
||||
{
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_2 = new List<string>()
|
||||
{
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_3 = new List<string>()
|
||||
{
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
{
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
};
|
||||
|
||||
private static List<User> users = new List<User>() {
|
||||
new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, new List<string>(), descr_user_1),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", new List<string>() { "group-2", "" }, true, new List<string>(), descr_user_2),
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", new List<string>() { "group-2" }, false, new List<string>() { "copy", "download", "print" }, descr_user_3),
|
||||
new User("uid-0", null, null, null, null, null, new List<string>(), descr_user_0)
|
||||
new User(
|
||||
"uid-1",
|
||||
"John Smith",
|
||||
"smith@mail.ru",
|
||||
null,
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true
|
||||
),
|
||||
new User(
|
||||
"uid-2",
|
||||
"Mark Pottato",
|
||||
"pottato@mail.ru",
|
||||
"group-2",
|
||||
new List<string>() { "group-2", "" },
|
||||
new Dictionary<string, object>()
|
||||
{
|
||||
{ "view", "" },
|
||||
{ "edit", new List<string>() { "group-2", "" } },
|
||||
{ "remove", new List<string>() { "group-2" } }
|
||||
},
|
||||
true,
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
false
|
||||
),
|
||||
new User(
|
||||
"uid-3",
|
||||
"Hamish Mitchell",
|
||||
"mitchell@mail.ru",
|
||||
"group-3",
|
||||
new List<string>() { "group-2" },
|
||||
new Dictionary<string,object>()
|
||||
{
|
||||
{ "view", new List<string>() { "group-2", "group-3" } },
|
||||
{ "edit", new List<string>() { "group-2" } },
|
||||
{ "remove", new List<string>() { } }
|
||||
},
|
||||
false,
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
false
|
||||
),
|
||||
new User(
|
||||
"uid-0",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_0,
|
||||
false
|
||||
)
|
||||
};
|
||||
|
||||
public static User getUser(string id)
|
||||
@ -75,6 +138,24 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, object>> getUsersForMentions(string id)
|
||||
{
|
||||
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
|
||||
|
||||
foreach (User user in users)
|
||||
{
|
||||
if (!user.id.Equals(id) && user.name != null && user.email != null)
|
||||
{
|
||||
usersData.Add(new Dictionary<string, object>()
|
||||
{
|
||||
{"name", user.name },
|
||||
{"email", user.email },
|
||||
});
|
||||
}
|
||||
}
|
||||
return usersData;
|
||||
}
|
||||
}
|
||||
|
||||
public class User
|
||||
@ -84,21 +165,24 @@ namespace OnlineEditorsExample
|
||||
public string email;
|
||||
public string group;
|
||||
public List<string> reviewGroups;
|
||||
public Dictionary<string, object> commentGroups;
|
||||
public bool? favorite;
|
||||
public List<string> deniedPermissions;
|
||||
public List<string> descriptions;
|
||||
public bool templates;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions)
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.group = group;
|
||||
this.reviewGroups = reviewGroups;
|
||||
this.commentGroups = commentGroups;
|
||||
this.favorite = favorite;
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submodule web/documentserver-example/csharp/assets updated: 4a1673c5ca...65addf50e4
@ -1,28 +1,22 @@
|
||||
# How to integrate online editors into your own web site on Java
|
||||
## Overview
|
||||
|
||||
## Introduction
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in Java.
|
||||
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **Java** you need to download and install ONLYOFFICE editors on your local server and use the [Java Example](https://api.onlyoffice.com/editors/demopreview) for their integration.
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
You can choose any appropriate way how to run the Java example code. We will show how to run the Java code using the **Apache Tomcat** web server on [Windows OS](#running-the-example-on-windows-os) and [Linux OS](#running-the-example-on-linux-os).
|
||||
## For Windows
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
## Running the example on Windows OS
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx).
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_java_example).
|
||||
|
||||
## Step 2. Download the Java code for the editors integration
|
||||
### Step 2. Download the Java code for the editors integration
|
||||
|
||||
Download the [Java example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
You need to connect the editors to your web site. For that specify the path to the editors installation in the *\src\main\resources\settings.properties* file:
|
||||
To connect the editors to your website, specify the path to the editors installation in the *\src\main\resources\settings.properties* file:
|
||||
|
||||
```
|
||||
files.docservice.url.site=https://documentserver/
|
||||
@ -32,16 +26,16 @@ where the **documentserver** is the name of the server with the ONLYOFFICE Docum
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *\src\main\webapp\editor.jsp* file.
|
||||
|
||||
## Step 3. Install the prerequisites
|
||||
### Step 3. Install the prerequisites
|
||||
|
||||
To run the Java example code you will need to install the Java version appropriate for your OS and web server **Apache Tomcat**:
|
||||
To run the Java example code, install the Java version appropriate for your OS and web server **Apache Tomcat**:
|
||||
|
||||
* Java (download from [the Oracle official web site](https://www.java.com/en/download/manual.jsp));
|
||||
* Java (download from [the Oracle official website](https://www.java.com/en/download/manual.jsp));
|
||||
* Apache Tomcat (download from [the official website](http://tomcat.apache.org/)).
|
||||
|
||||
## Step 4. Running Apache Tomcat
|
||||
### Step 4. Run Apache Tomcat
|
||||
|
||||
1. After you have installed Java in Windows, you must set the **JAVA_HOME** environment variable to point to the Java installation directory.
|
||||
1. After you have installed Java on Windows, set the **JAVA_HOME** environment variable to point to the Java installation directory.
|
||||
|
||||
Find out where Java is installed. If you didn't change the path during installation, it will be something like this:
|
||||
|
||||
@ -93,7 +87,7 @@ To run the Java example code you will need to install the Java version appropria
|
||||
|
||||
If everything is correct, you will see the Tomcat web page in the browser as shown below.
|
||||
|
||||
## Step 5 . Running the Java code
|
||||
### Step 5. Run the Java code
|
||||
|
||||
1. Open Tomcat Web Application Manager by clicking **Manager App:**
|
||||
|
||||
@ -103,7 +97,7 @@ To run the Java example code you will need to install the Java version appropria
|
||||

|
||||
|
||||
|
||||
For that you will need to specify user data in *tomcat-users.xml* file in the Apache Tomcat installation folder. Define the **manager-gui** user role, specify the **user name** and **password** values:
|
||||
Specify user data in *tomcat-users.xml* file in the Apache Tomcat installation folder. Define the **manager-gui** user role, specify the **user name** and **password** values:
|
||||
|
||||
```
|
||||
<tomcat-users>
|
||||
@ -121,21 +115,21 @@ To run the Java example code you will need to install the Java version appropria
|
||||
|
||||
5. Click the link with the application name to run it.
|
||||
|
||||
## Step 6. Checking accessibility
|
||||
### Step 6. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
## Running the example on Linux OS
|
||||
## For Linux
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_java_example).
|
||||
See the detailed guide to learn how to install Document Server [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx).
|
||||
|
||||
## Step 2. Install the prerequisites and run the web site with the editors
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Java**:
|
||||
|
||||
@ -226,15 +220,15 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
http://localhost:8080/OnlineEditorsExampleJava-1.0/
|
||||
```
|
||||
|
||||
## Step 3. Checking accessibility
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
## Build from Docker
|
||||
## For Docker
|
||||
|
||||
1. Edit the *settings.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed.
|
||||
1. Edit the *settings.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed ([installation instructions](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx)).
|
||||
|
||||
```
|
||||
nano src/main/resources/settings.properties
|
||||
@ -254,4 +248,4 @@ If you integrated the editors successfully the result should look like the [demo
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
4. After it, all the *bin* files will be passed to the *./target* folder.
|
||||
4. After it, all the *bin* files will be passed to the *./target* folder.
|
||||
|
||||
@ -26,6 +26,7 @@ import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
@ -88,6 +89,9 @@ public class EditorServlet extends HttpServlet
|
||||
dataMailMergeRecipients.put("fileType", "csv");
|
||||
dataMailMergeRecipients.put("url", DocumentManager.GetServerUrl(true) + "/IndexServlet?type=csv");
|
||||
|
||||
// users data for mentions
|
||||
List<Map<String, Object>> usersForMentions = Users.getUsersForMentions(user.id);
|
||||
|
||||
// check if the document token is enabled
|
||||
if (DocumentManager.TokenEnabled())
|
||||
{
|
||||
@ -103,6 +107,7 @@ public class EditorServlet extends HttpServlet
|
||||
request.setAttribute("dataInsertImage", gson.toJson(dataInsertImage).substring(1, gson.toJson(dataInsertImage).length()-1));
|
||||
request.setAttribute("dataCompareFile", gson.toJson(dataCompareFile));
|
||||
request.setAttribute("dataMailMergeRecipients", gson.toJson(dataMailMergeRecipients));
|
||||
request.setAttribute("usersForMentions", !user.id.equals("uid-0") ? gson.toJson(usersForMentions) : null);
|
||||
request.getRequestDispatcher("editor.jsp").forward(request, response);
|
||||
}
|
||||
|
||||
|
||||
17
web/documentserver-example/java/src/main/java/entities/CommentGroups.java
Executable file
17
web/documentserver-example/java/src/main/java/entities/CommentGroups.java
Executable file
@ -0,0 +1,17 @@
|
||||
package entities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CommentGroups {
|
||||
public List<String> view;
|
||||
public List<String> edit;
|
||||
public List<String> remove;
|
||||
public CommentGroups(){
|
||||
|
||||
}
|
||||
public CommentGroups(List<String> view, List<String> edit, List<String> remove){
|
||||
this.view = view;
|
||||
this.edit = edit;
|
||||
this.remove = remove;
|
||||
}
|
||||
}
|
||||
48
web/documentserver-example/java/src/main/java/entities/FileModel.java
Normal file → Executable file
48
web/documentserver-example/java/src/main/java/entities/FileModel.java
Normal file → Executable file
@ -18,20 +18,20 @@
|
||||
|
||||
package entities;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
|
||||
import helpers.DocumentManager;
|
||||
import helpers.ServiceConverter;
|
||||
import helpers.FileUtility;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import helpers.DocumentManager;
|
||||
import helpers.FileUtility;
|
||||
import helpers.ServiceConverter;
|
||||
import helpers.Users;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
|
||||
public class FileModel
|
||||
{
|
||||
public String type = "desktop";
|
||||
@ -61,12 +61,31 @@ public class FileModel
|
||||
document.info = new Info();
|
||||
document.info.favorite = user.favorite;
|
||||
|
||||
String templatesImageUrl = DocumentManager.GetTemplateImageUrl(FileUtility.GetFileType(fileName));
|
||||
List<Map<String, String>> templates = new ArrayList<>();
|
||||
String createUrl = DocumentManager.GetCreateUrl(FileUtility.GetFileType(fileName));
|
||||
|
||||
// add templates for the "Create New" from menu option
|
||||
Map<String, String> templateForBlankDocument = new HashMap<>();
|
||||
templateForBlankDocument.put("image", templatesImageUrl);
|
||||
templateForBlankDocument.put("title", "Blank");
|
||||
templateForBlankDocument.put("url", createUrl);
|
||||
templates.add(templateForBlankDocument);
|
||||
Map<String, String> templateForDocumentWithSampleContent = new HashMap<>();
|
||||
templateForDocumentWithSampleContent.put("image", templatesImageUrl);
|
||||
templateForDocumentWithSampleContent.put("title", "With sample content");
|
||||
templateForDocumentWithSampleContent.put("url", createUrl + "&sample=true");
|
||||
templates.add(templateForDocumentWithSampleContent);
|
||||
|
||||
// set the editor config parameters
|
||||
editorConfig = new EditorConfig(actionData);
|
||||
editorConfig.callbackUrl = DocumentManager.GetCallback(fileName); // get callback url
|
||||
editorConfig.createUrl = DocumentManager.GetCreateUrl(FileUtility.GetFileType(fileName));
|
||||
|
||||
if (lang != null) editorConfig.lang = lang; // write language parameter to the config
|
||||
|
||||
editorConfig.createUrl = !user.id.equals("uid-0") ? createUrl : null;
|
||||
editorConfig.templates = user.templates ? templates : null;
|
||||
|
||||
// write user information to the config (id, name and group)
|
||||
editorConfig.user.id = user.id;
|
||||
editorConfig.user.name = user.name;
|
||||
@ -163,10 +182,10 @@ public class FileModel
|
||||
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
|
||||
|
||||
// write information about changes to the object
|
||||
obj.put("changes", changes.get("changes"));
|
||||
obj.put("changes", !change.isEmpty() ? changes.get("changes") : null);
|
||||
obj.put("serverVersion", changes.get("serverVersion"));
|
||||
obj.put("created", change.get("created"));
|
||||
obj.put("user", change.get("user"));
|
||||
obj.put("created", !change.isEmpty() ? change.get("created") : null);
|
||||
obj.put("user", !change.isEmpty() ? change.get("user") : null);
|
||||
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2)); // get the history data from the previous file version
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
@ -241,6 +260,7 @@ public class FileModel
|
||||
public Boolean modifyContentControl;
|
||||
public Boolean review;
|
||||
public List<String> reviewGroups;
|
||||
public CommentGroups commentGroups;
|
||||
|
||||
// defines what can be done with a document
|
||||
public Permissions(String mode, String type, Boolean canEdit, User user)
|
||||
@ -255,6 +275,7 @@ public class FileModel
|
||||
modifyContentControl = !mode.equals("blockcontent");
|
||||
review = canEdit && (mode.equals("edit") || mode.equals("review"));
|
||||
reviewGroups = user.reviewGroups;
|
||||
commentGroups = user.commentGroups;
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,8 +290,9 @@ public class FileModel
|
||||
public HashMap<String, Object> actionLink = null;
|
||||
public String mode = "edit";
|
||||
public String callbackUrl;
|
||||
public String createUrl;
|
||||
public String lang = "en";
|
||||
public String createUrl;
|
||||
public List<Map<String, String>> templates;
|
||||
public User user;
|
||||
public Customization customization;
|
||||
public Embedded embedded;
|
||||
|
||||
7
web/documentserver-example/java/src/main/java/entities/User.java
Normal file → Executable file
7
web/documentserver-example/java/src/main/java/entities/User.java
Normal file → Executable file
@ -26,18 +26,23 @@ public class User {
|
||||
public String email;
|
||||
public String group;
|
||||
public List<String> reviewGroups;
|
||||
public CommentGroups commentGroups;
|
||||
public Boolean favorite;
|
||||
public List<String> deniedPermissions;
|
||||
public List<String> descriptions;
|
||||
public Boolean templates;
|
||||
|
||||
public User(String id, String name, String email, String group, List<String> reviewGroups, Boolean favorite, List<String> deniedPermissions, List<String> descriptions) {
|
||||
public User(String id, String name, String email, String group, List<String> reviewGroups, CommentGroups commentGroups,
|
||||
Boolean favorite, List<String> deniedPermissions, List<String> descriptions, Boolean templates) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.group = group;
|
||||
this.reviewGroups = reviewGroups;
|
||||
this.commentGroups = commentGroups;
|
||||
this.favorite = favorite;
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
}
|
||||
}
|
||||
@ -432,6 +432,26 @@ public class DocumentManager
|
||||
return ".docx";
|
||||
}
|
||||
|
||||
// get image url for templates
|
||||
public static String GetTemplateImageUrl(FileType fileType)
|
||||
{
|
||||
String path = GetServerUrl(true) + "/css/img/";
|
||||
// for word file type
|
||||
if (fileType.equals(FileType.Word))
|
||||
return path + "file_docx.svg";
|
||||
|
||||
// .xlsx for cell file type
|
||||
if (fileType.equals(FileType.Cell))
|
||||
return path + "file_xlsx.svg";
|
||||
|
||||
// .pptx for slide file type
|
||||
if (fileType.equals(FileType.Slide))
|
||||
return path + "file_pptx.svg";
|
||||
|
||||
// the default file type
|
||||
return path + "file_docx.svg";
|
||||
}
|
||||
|
||||
// create document token
|
||||
public static String CreateToken(Map<String, Object> payloadClaims)
|
||||
{
|
||||
|
||||
73
web/documentserver-example/java/src/main/java/helpers/Users.java
Normal file → Executable file
73
web/documentserver-example/java/src/main/java/helpers/Users.java
Normal file → Executable file
@ -18,47 +18,63 @@
|
||||
|
||||
package helpers;
|
||||
|
||||
import entities.User;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import entities.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Users {
|
||||
|
||||
static List<String> descr_user_1 = new ArrayList<String>() {{
|
||||
add("File author by default");
|
||||
add("He doesn’t belong to any of the groups");
|
||||
add("He can review all the changes");
|
||||
add("Doesn’t belong to any group");
|
||||
add("Can review all the changes");
|
||||
add("Can perform all actions with comments");
|
||||
add("The file favorite state is undefined");
|
||||
add("Can create files from templates using data from the editor");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_2 = new ArrayList<String>() {{
|
||||
add("He belongs to Group2");
|
||||
add("He can review only his own changes or the changes made by the users who don’t belong to any of the groups");
|
||||
add("This file is favorite");
|
||||
add("Belongs to Group2");
|
||||
add("Can review only his own changes or changes made by users with no group");
|
||||
add("Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only");
|
||||
add("This file is marked as favorite");
|
||||
add("Can create new files from the editor");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_3 = new ArrayList<String>() {{
|
||||
add("He belongs to Group3");
|
||||
add("He can review only the changes made by the users from Group2");
|
||||
add("This file isn’t favorite");
|
||||
add("He can’t copy data from the file into the clipboard");
|
||||
add("He can’t download the file");
|
||||
add("He can’t print the file");
|
||||
add("Belongs to Group3");
|
||||
add("Can review changes made by Group2 users");
|
||||
add("Can view comments left by Group2 and Group3 users. Can edit comments left by Group2 users");
|
||||
add("This file isn’t marked as favorite");
|
||||
add("Can’t copy data from the file to clipboard");
|
||||
add("Can’t download the file");
|
||||
add("Can’t print the file");
|
||||
add("Can create new files from the editor");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_0 = new ArrayList<String>() {{
|
||||
add("The user without a name. The name is requested upon the editor opening");
|
||||
add("He doesn’t belong to any of the groups");
|
||||
add("He can review all the changes");
|
||||
add("The name is requested when the editor is opened");
|
||||
add("Doesn’t belong to any group");
|
||||
add("Can review all the changes");
|
||||
add("Can perform all actions with comments");
|
||||
add("The file favorite state is undefined");
|
||||
add("Can't mention others in comments");
|
||||
add("Can't create new files from the editor");
|
||||
}};
|
||||
|
||||
private static List<User> users = new ArrayList<User>() {{
|
||||
add(new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, new ArrayList<String>(), descr_user_1));
|
||||
add(new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", Arrays.asList("group-2", ""), true, new ArrayList<String>(), descr_user_2));
|
||||
add(new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", Arrays.asList("group-2"), false, Arrays.asList("copy", "download", "print"), descr_user_3));
|
||||
add(new User("uid-0", null, null, null, null, null, new ArrayList<String>(), descr_user_0));
|
||||
add(new User("uid-1", "John Smith", "smith@mail.ru",
|
||||
null, null, new CommentGroups(),
|
||||
null, new ArrayList<String>(), descr_user_1, true));
|
||||
add(new User("uid-2", "Mark Pottato", "pottato@mail.ru",
|
||||
"group-2", Arrays.asList("group-2", ""), new CommentGroups(null, Arrays.asList("group-2", ""), Arrays.asList("group-2")),
|
||||
true, new ArrayList<String>(), descr_user_2, false));
|
||||
add(new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru",
|
||||
"group-3", Arrays.asList("group-2"), new CommentGroups(Arrays.asList("group-3", "group-2"), Arrays.asList("group-2"), new ArrayList<String>()),
|
||||
false, Arrays.asList("copy", "download", "print"), descr_user_3, false));
|
||||
add(new User("uid-0", null, null,
|
||||
null, null, new CommentGroups(),
|
||||
null, new ArrayList<String>(), descr_user_0, false));
|
||||
}};
|
||||
|
||||
public static User getUser (String id) {
|
||||
@ -73,5 +89,18 @@ public class Users {
|
||||
public static List<User> getAllUsers () {
|
||||
return users;
|
||||
}
|
||||
|
||||
public static List<Map<String, Object>> getUsersForMentions (String id) {
|
||||
List<Map<String, Object>> usersData = new ArrayList<>();
|
||||
for (User user : users) {
|
||||
if (!user.id.equals(id) && user.name != null && user.email != null) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("name", user.name);
|
||||
data.put("email", user.email);
|
||||
usersData.add(data);
|
||||
}
|
||||
}
|
||||
return usersData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Submodule web/documentserver-example/java/src/main/resources/assets updated: 4a1673c5ca...65addf50e4
@ -139,6 +139,7 @@
|
||||
String[] histArray = Model.GetHistory();
|
||||
String history = histArray[0];
|
||||
String historyData = histArray[1];
|
||||
String usersForMentions = (String) request.getAttribute("usersForMentions");
|
||||
%>
|
||||
|
||||
<% if (!history.isEmpty() && !historyData.isEmpty()) { %>
|
||||
@ -158,6 +159,21 @@
|
||||
};
|
||||
<% } %>
|
||||
|
||||
<% if (usersForMentions != null) { %>
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": ${usersForMentions}
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
@ -20,10 +20,18 @@ express - Fast, unopinionated, minimalist web framework for node. (https:/
|
||||
License: MIT
|
||||
License File: express.license
|
||||
|
||||
fast-xml-parser - Validate XML, Parse XML to JS/JSON and vice versa, or parse XML to Nimn rapidly without C/C++ based libraries and no callback. (https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/LICENSE)
|
||||
License: MIT
|
||||
License File: fast-xml-parser.license
|
||||
|
||||
formidable - A Node.js module for parsing form data, especially file uploads. (https://github.com/node-formidable/formidable/blob/master/LICENSE)
|
||||
License: MIT
|
||||
License File: formidable.license
|
||||
|
||||
he - a robust HTML entity encoder/decoder written in JavaScript. (https://github.com/mathiasbynens/he/blob/master/LICENSE-MIT.txt)
|
||||
License: MIT
|
||||
License File: he.license
|
||||
|
||||
jQuery - jQuery is a new kind of JavaScript Library. jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. NOTE: This package is maintained on behalf of the library owners by the NuGet Community Packages project at https://nugetpackages.codeplex.com/ (https://jquery.org/license/)
|
||||
License: MIT
|
||||
License File: jQuery.license
|
||||
|
||||
@ -1,26 +1,22 @@
|
||||
# How to integrate online editors into your own web site on Node.js
|
||||
## Overview
|
||||
|
||||
## Introduction
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application on Node.js.
|
||||
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **Node.js** you need to download and install ONLYOFFICE editors on your local server and use the [Node.js Example](https://api.onlyoffice.com/editors/demopreview) for their integration. We will show you how to run the Node.js example on [Windows OS](#running-the-example-on-windows-os) and [Linux OS](#running-the-example-on-linux-os).
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
Please nore that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
## For Windows
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
## Running the example on Windows OS
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx).
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_nodejs_example).
|
||||
|
||||
## Step 2. Download the Node.js code for the editors integration
|
||||
### Step 2. Download the Node.js code for the editors integration
|
||||
|
||||
Download the [Node.js example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
You need to connect the editors to your web site. For that specify the path to the editors installation in the *config/default.json* file:
|
||||
You need to connect the editors to your website. Specify the path to the editors installation in the *config/default.json* file:
|
||||
|
||||
```
|
||||
"siteUrl": "https://documentserver/"
|
||||
@ -30,11 +26,11 @@ where the **documentserver** is the name of the server with the ONLYOFFICE Docum
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *\views\editor.ejs* file.
|
||||
|
||||
## Step 3. System requirements
|
||||
### Step 3. Install Node.js environment
|
||||
|
||||
Download and install the **node.js** environment which is going to be used to run the Node.js project. Please follow the link at the official website: https://nodejs.org/en/download/, choosing the correct version for your Windows OS (32-bit or 64-bit).
|
||||
Install the **node.js** environment which is going to be used to run the Node.js project. Please follow the link at the official website: https://nodejs.org/en/download/ choosing the correct version for your Windows OS (32-bit or 64-bit).
|
||||
|
||||
## Step 4. Running the Node.js code
|
||||
### Step 4. Run the Node.js code
|
||||
|
||||
We will run the code in Node.js runtime environment and will interact with it using the command line interface (cmd).
|
||||
|
||||
@ -64,19 +60,21 @@ We will run the code in Node.js runtime environment and will interact with it us
|
||||
http://localhost:3000
|
||||
```
|
||||
|
||||
## Step 5. Checking accessibility
|
||||
### Step 5. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
## Running the example on Linux OS
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
## For Linux
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_nodejs_example).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
## Step 2. Install the prerequisites and run the web site with the editors
|
||||
See the detailed guide to learn how to [install Document Server for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx).
|
||||
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Node.js**:
|
||||
|
||||
@ -88,7 +86,7 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
2. Download the archive with the Node.js example and unpack the archive:
|
||||
2. Download the archive with the Node.js example and unpack it:
|
||||
|
||||
```
|
||||
wget https://api.onlyoffice.com/app_data/editor/Node.js%20Example.zip
|
||||
@ -136,6 +134,8 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
http://localhost:3000
|
||||
```
|
||||
|
||||
## Step 3. Checking accessibility
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
@ -33,6 +33,7 @@ const mime = require("mime");
|
||||
const docManager = require("./helpers/docManager");
|
||||
const documentService = require("./helpers/documentService");
|
||||
const fileUtility = require("./helpers/fileUtility");
|
||||
const wopiApp = require("./helpers/wopi/wopiRouting");
|
||||
const users = require("./helpers/users");
|
||||
const siteUrl = configServer.get('siteUrl');
|
||||
const fileChoiceUrl = configServer.has('fileChoiceUrl') ? configServer.get('fileChoiceUrl') : "";
|
||||
@ -628,6 +629,7 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
|
||||
var fileName = fileUtility.getFileName(req.query.fileName);
|
||||
var fileExt = req.query.fileExt;
|
||||
var history = [];
|
||||
var historyData = [];
|
||||
@ -638,8 +640,24 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
var name = user.name;
|
||||
var actionData = req.query.action ? req.query.action : "null";
|
||||
|
||||
var templatesImageUrl = docManager.getTemplateImageUrl(fileUtility.getFileType(fileName));
|
||||
var createUrl = docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang);
|
||||
var templates = [
|
||||
{
|
||||
"image": templatesImageUrl,
|
||||
"title": "Blank",
|
||||
"url": createUrl
|
||||
},
|
||||
{
|
||||
"image": templatesImageUrl,
|
||||
"title": "With sample content",
|
||||
"url": createUrl + "&sample=true"
|
||||
}
|
||||
];
|
||||
|
||||
var userGroup = user.group;
|
||||
var reviewGroups = user.reviewGroups;
|
||||
var commentGroups = user.commentGroups;
|
||||
|
||||
if (fileExt != null) {
|
||||
var fileName = docManager.createDemo(!!req.query.sample, fileExt, userid, name); // create demo document of a given extension
|
||||
@ -651,7 +669,6 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
}
|
||||
|
||||
var userAddress = docManager.curUserHostAddress();
|
||||
var fileName = fileUtility.getFileName(req.query.fileName);
|
||||
if (!docManager.existsSync(docManager.storagePath(fileName, userAddress))) { // if the file with a given name doesn't exist
|
||||
throw {
|
||||
"message": "File not found: " + fileName // display error message
|
||||
@ -681,6 +698,7 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
for (var i = 1; i <= countVersion; i++) { // get keys to all the file versions
|
||||
if (i < countVersion) {
|
||||
var keyPath = docManager.keyPath(fileName, userAddress, i);
|
||||
if (!fileSystem.existsSync(keyPath)) continue;
|
||||
keyVersion = "" + fileSystem.readFileSync(keyPath);
|
||||
} else {
|
||||
keyVersion = key;
|
||||
@ -741,7 +759,8 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
key: key,
|
||||
token: "",
|
||||
callbackUrl: docManager.getCallback(fileName),
|
||||
createUrl: docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang),
|
||||
createUrl: userid != "uid-0" ? createUrl : null,
|
||||
templates: user.templates ? templates : null,
|
||||
isEdit: canEdit && (mode == "edit" || mode == "view" || mode == "filter" || mode == "blockcontent"),
|
||||
review: canEdit && (mode == "edit" || mode == "review"),
|
||||
comment: mode != "view" && mode != "fillForms" && mode != "embedded" && mode != "blockcontent",
|
||||
@ -760,6 +779,7 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
name: name,
|
||||
userGroup: userGroup,
|
||||
reviewGroups: JSON.stringify(reviewGroups),
|
||||
commentGroups: JSON.stringify(commentGroups),
|
||||
fileChoiceUrl: fileChoiceUrl,
|
||||
submitForm: submitForm,
|
||||
plugins: JSON.stringify(plugins),
|
||||
@ -778,7 +798,8 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
dataMailMergeRecipients: {
|
||||
fileType: "csv",
|
||||
url: docManager.getServerUrl(true) + "/csv"
|
||||
}
|
||||
},
|
||||
usersForMentions: user.id != "uid-0" ? users.getUsersForMentions(user.id) : null,
|
||||
};
|
||||
|
||||
if (cfgSignatureEnable) {
|
||||
@ -805,6 +826,8 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
}
|
||||
});
|
||||
|
||||
wopiApp.registerRoutes(app);
|
||||
|
||||
// "Not found" error with 404 status
|
||||
app.use(function (req, res, next) {
|
||||
const err = new Error("Not Found");
|
||||
@ -821,4 +844,4 @@ app.use(function (err, req, res, next) {
|
||||
});
|
||||
|
||||
// save all the functions to the app module to export it later in other files
|
||||
module.exports = app;
|
||||
module.exports = app;
|
||||
@ -13,6 +13,9 @@
|
||||
"server": {
|
||||
"port": 3000,
|
||||
"siteUrl": "https://documentserver/",
|
||||
"wopi": {
|
||||
"discovery": "hosting/discovery"
|
||||
},
|
||||
"commandUrl": "coauthoring/CommandService.ashx",
|
||||
"converterUrl": "ConvertService.ashx",
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"server": {
|
||||
"port": 3000,
|
||||
"siteUrl": "http://127.0.0.1:8001/",
|
||||
"siteUrl": "http://127.0.0.1:8000/",
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"server": {
|
||||
"port": 3000,
|
||||
"siteUrl": "http://127.0.0.1:8001/",
|
||||
"siteUrl": "http://127.0.0.1:8000/",
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"server": {
|
||||
"port": 80,
|
||||
"siteUrl": "http://127.0.0.1:8001/",
|
||||
"siteUrl": "http://127.0.0.1:8000/",
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
|
||||
}
|
||||
|
||||
@ -331,6 +331,20 @@ docManager.getInternalExtension = function (fileType) {
|
||||
return ".docx"; // the default value is .docx
|
||||
};
|
||||
|
||||
docManager.getTemplateImageUrl = function (fileType) {
|
||||
let path = docManager.getServerUrl(true);
|
||||
if (fileType == fileUtility.fileType.word) // for word type
|
||||
return path + "/images/file_docx.svg";
|
||||
|
||||
if (fileType == fileUtility.fileType.cell) // for cell type
|
||||
return path + "/images/file_xlsx.svg";
|
||||
|
||||
if (fileType == fileUtility.fileType.slide) // for slide type
|
||||
return path + "/images/file_pptx.svg";
|
||||
|
||||
return path + "/images/file_docx.svg"; // the default value
|
||||
}
|
||||
|
||||
// get document key
|
||||
docManager.getKey = function (fileName) {
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
@ -376,11 +390,13 @@ docManager.getHistory = function (fileName, content, keyVersion, version) {
|
||||
let oldVersion = false;
|
||||
let contentJson = null;
|
||||
if (content) { // if content is defined
|
||||
if (content.changes) { // and there are some modifications in the content
|
||||
if (content.changes && content.changes.length) { // and there are some modifications in the content
|
||||
contentJson = content.changes[0]; // write these modifications to the json content
|
||||
} else {
|
||||
} else if (content.length){
|
||||
contentJson = content[0]; // otherwise, write original content to the json content
|
||||
oldVersion = true; // and note that this is an old version
|
||||
} else {
|
||||
content = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,49 +18,80 @@
|
||||
|
||||
var descr_user_1 = [
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
];
|
||||
|
||||
var descr_user_2 = [
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
var descr_user_3 = [
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
var descr_user_0 = [
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
];
|
||||
|
||||
var users = [
|
||||
new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, [], descr_user_1),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", ["group-2", ""], true, [], descr_user_2), // own and without group
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", ["group-2"], false, ["copy", "download", "print"], descr_user_3), // other group only
|
||||
new User("uid-0", null, null, null, null, null, [], descr_user_0),
|
||||
new User("uid-1", "John Smith", "smith@mail.ru",
|
||||
null, null, {},
|
||||
null, [], descr_user_1, true),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mail.ru",
|
||||
"group-2", ["group-2", ""], {
|
||||
view: "",
|
||||
edit: ["group-2", ""],
|
||||
remove: ["group-2"]
|
||||
},
|
||||
true, [], descr_user_2, false), // own and without group
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru",
|
||||
"group-3", ["group-2"], {
|
||||
view: ["group-3", "group-2"],
|
||||
edit: ["group-2"],
|
||||
remove: []
|
||||
},
|
||||
false, ["copy", "download", "print"], descr_user_3, false), // other group only
|
||||
new User("uid-0", null, null,
|
||||
null, null, {},
|
||||
null, [], descr_user_0, false),
|
||||
];
|
||||
|
||||
function User(id, name, email, group, reviewGroups, favorite, deniedPermissions, descriptions) {
|
||||
function User(id, name, email, group, reviewGroups, commentGroups, favorite, deniedPermissions, descriptions, templates) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.group = group;
|
||||
this.reviewGroups = reviewGroups;
|
||||
this.commentGroups = commentGroups;
|
||||
this.favorite = favorite;
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
};
|
||||
|
||||
users.getAllUsers = function () {
|
||||
return users;
|
||||
};
|
||||
|
||||
users.getUser = function (id) {
|
||||
@ -73,4 +104,14 @@ users.getUser = function (id) {
|
||||
return result ? result : this[0];
|
||||
};
|
||||
|
||||
module.exports = users;
|
||||
users.getUsersForMentions = function (id) {
|
||||
var result = [];
|
||||
this.forEach(user => {
|
||||
if (user.id != id && user.name != null && user.email != null) {
|
||||
result.push({ name: user.name, email: user.email });
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports = users;
|
||||
|
||||
@ -0,0 +1,303 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
const reqConsts = require('./request');
|
||||
const docManager = require("../docManager");
|
||||
const fileUtility = require("../fileUtility");
|
||||
const lockManager = require("./lockManager");
|
||||
const utils = require("./utils");
|
||||
const fileSystem = require("fs");
|
||||
const mime = require("mime");
|
||||
const path = require("path");
|
||||
const users = require("../users");
|
||||
|
||||
const actionMapping = {};
|
||||
actionMapping[reqConsts.requestType.GetFile] = getFile;
|
||||
actionMapping[reqConsts.requestType.PutFile] = putFile;
|
||||
actionMapping[reqConsts.requestType.CheckFileInfo] = checkFileInfo;
|
||||
actionMapping[reqConsts.requestType.UnlockAndRelock] = unlockAndRelock;
|
||||
actionMapping[reqConsts.requestType.Lock] = lock;
|
||||
actionMapping[reqConsts.requestType.GetLock] = getLock;
|
||||
actionMapping[reqConsts.requestType.RefreshLock] = refreshLock;
|
||||
actionMapping[reqConsts.requestType.Unlock] = unlock;
|
||||
|
||||
function parseWopiRequest(req) {
|
||||
let wopiData = {
|
||||
requestType: reqConsts.requestType.None,
|
||||
accessToken: req.query["access_token"],
|
||||
id: req.params['id']
|
||||
}
|
||||
|
||||
let reqPath = req.path.substring("/wopi/".length)
|
||||
|
||||
if (reqPath.startsWith("files")) {
|
||||
if (reqPath.endsWith("/contents")) {
|
||||
if (req.method == "GET") {
|
||||
wopiData.requestType = reqConsts.requestType.GetFile;
|
||||
} else if (req.method == "POST") {
|
||||
wopiData.requestType = reqConsts.requestType.PutFile;
|
||||
}
|
||||
} else {
|
||||
if (req.method == "GET") {
|
||||
wopiData.requestType = reqConsts.requestType.CheckFileInfo;
|
||||
} else if (req.method == "POST") {
|
||||
let wopiOverride = req.headers[reqConsts.requestHeaders.RequestType.toLowerCase()];
|
||||
switch (wopiOverride) {
|
||||
case "LOCK":
|
||||
if (req.headers[reqConsts.requestHeaders.OldLock.toLowerCase()]) {
|
||||
wopiData.requestType = reqConsts.requestType.UnlockAndRelock;
|
||||
} else {
|
||||
wopiData.requestType = reqConsts.requestType.Lock;
|
||||
}
|
||||
break;
|
||||
|
||||
case "GET_LOCK":
|
||||
wopiData.requestType = reqConsts.requestType.GetLock;
|
||||
break;
|
||||
|
||||
case "REFRESH_LOCK":
|
||||
wopiData.requestType = reqConsts.requestType.RefreshLock;
|
||||
break;
|
||||
|
||||
case "UNLOCK":
|
||||
wopiData.requestType = reqConsts.requestType.Unlock;
|
||||
break;
|
||||
|
||||
case "PUT_RELATIVE":
|
||||
wopiData.requestType = reqConsts.requestType.PutRelativeFile;
|
||||
break;
|
||||
|
||||
case "RENAME_FILE":
|
||||
wopiData.requestType = reqConsts.requestType.RenameFile;
|
||||
break;
|
||||
|
||||
case "PUT_USER_INFO":
|
||||
wopiData.requestType = reqConsts.requestType.PutUserInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (reqPath.startsWith("folders")) {
|
||||
|
||||
}
|
||||
|
||||
return wopiData;
|
||||
}
|
||||
|
||||
function lock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => lock
|
||||
lockManager.lock(filePath, requestLock);
|
||||
res.sendStatus(200);
|
||||
} else if (lockManager.getLock(filePath) == requestLock) {
|
||||
// lock matches current lock => extend duration
|
||||
lockManager.lock(filePath, requestLock);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
// file locked by someone else => return lock mismatch
|
||||
let lock = lockManager.getLock(filePath);
|
||||
returnLockMismatch(res, lock, "File already locked by " + lock)
|
||||
}
|
||||
}
|
||||
|
||||
function getLock(wopi, req, res, userHost) {
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
res.setHeader(reqConsts.requestHeaders.lock, lockManager.getLock(filePath));
|
||||
res.sendStatus(200);
|
||||
}
|
||||
|
||||
function refreshLock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
returnLockMismatch(res, "", "File isn't locked");
|
||||
} else if (lockManager.getLock(filePath) == requestLock) {
|
||||
// lock matches current lock => extend duration
|
||||
lockManager.lock(filePath, requestLock);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
// lock mismatch
|
||||
returnLockMismatch(res, lockManager.getLock(filePath), "Lock mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
function unlock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
returnLockMismatch(res, "", "File isn't locked");
|
||||
} else if (lockManager.getLock(filePath) == requestLock) {
|
||||
// lock matches current lock => unlock
|
||||
lockManager.unlock(filePath);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
// lock mismatch
|
||||
returnLockMismatch(res, lockManager.getLock(filePath), "Lock mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
function unlockAndRelock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
let oldLock = req.headers[reqConsts.requestHeaders.oldLock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
returnLockMismatch(res, "", "File isn't locked");
|
||||
} else if (lockManager.getLock(filePath) == oldLock) {
|
||||
// lock matches current lock => lock with new key
|
||||
lockManager.lock(filePath, requestLock);
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
// lock mismatch
|
||||
returnLockMismatch(res, lockManager.getLock(filePath), "Lock mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
function getFile(wopi, req, res, userHost) {
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
|
||||
let path = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
res.setHeader("Content-Length", fileSystem.statSync(path).size);
|
||||
res.setHeader("Content-Type", mime.getType(path));
|
||||
|
||||
res.setHeader("Content-Disposition", "attachment; filename*=UTF-8\'\'" + encodeURIComponent(wopi.id));
|
||||
|
||||
let filestream = fileSystem.createReadStream(path);
|
||||
filestream.pipe(res);
|
||||
}
|
||||
|
||||
function putFile(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let storagePath = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(storagePath)) {
|
||||
// ToDo: if body length is 0 bytes => handle document creation
|
||||
|
||||
// file isn't locked => mismatch
|
||||
returnLockMismatch(res, "", "File isn't locked");
|
||||
} else if (lockManager.getLock(storagePath) == requestLock) {
|
||||
// lock matches current lock => put file
|
||||
if (req.body) {
|
||||
var historyPath = docManager.historyPath(wopi.id, userAddress);
|
||||
if (historyPath == "") {
|
||||
historyPath = docManager.historyPath(wopi.id, userAddress, true);
|
||||
docManager.createDirectory(historyPath);
|
||||
}
|
||||
|
||||
var count_version = docManager.countVersion(historyPath);
|
||||
version = count_version + 1;
|
||||
res.setHeader(reqConsts.requestHeaders.ItemVersion, version + 1);
|
||||
var versionPath = docManager.versionPath(wopi.id, userAddress, version);
|
||||
docManager.createDirectory(versionPath);
|
||||
|
||||
var path_prev = path.join(versionPath, "prev" + fileUtility.getFileExtension(wopi.id));
|
||||
fileSystem.renameSync(docManager.storagePath(wopi.id, userAddress), path_prev);
|
||||
|
||||
let filestream = fileSystem.createWriteStream(storagePath);
|
||||
req.pipe(filestream);
|
||||
req.on('end', () => {
|
||||
filestream.close();
|
||||
res.sendStatus(200);
|
||||
})
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
} else {
|
||||
// lock mismatch
|
||||
returnLockMismatch(res, lockManager.getLock(storagePath), "Lock mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
function checkFileInfo(wopi, req, res, userHost) {
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let historyPath = docManager.historyPath(wopi.id, userAddress);
|
||||
let version = 1;
|
||||
if (historyPath != "") {
|
||||
version = docManager.countVersion(historyPath) + 1;
|
||||
}
|
||||
let path = docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
let user = users.getUser(req.query.userid);
|
||||
|
||||
let fileInfo = {
|
||||
"BaseFileName": wopi.id,
|
||||
"OwnerId": docManager.getFileData(wopi.id, userAddress)[1],
|
||||
"Size": fileSystem.statSync(path).size,
|
||||
"UserId": user.id,
|
||||
"UserFriendlyName": user.name,
|
||||
"Version": version,
|
||||
"UserCanWrite": true,
|
||||
"SupportsGetLock": true,
|
||||
"SupportsLocks": true,
|
||||
"SupportsUpdate": true,
|
||||
};
|
||||
res.status(200).send(fileInfo);
|
||||
}
|
||||
|
||||
function returnLockMismatch(res, lock, reason) {
|
||||
res.setHeader(reqConsts.requestHeaders.Lock, lock || "");
|
||||
if (reason) {
|
||||
res.setHeader(reqConsts.requestHeaders.LockFailureReason, reason);
|
||||
}
|
||||
res.sendStatus(409); // conflict
|
||||
}
|
||||
|
||||
exports.fileRequestHandler = (req, res) => {
|
||||
let userAddress = null;
|
||||
if (req.params['id'].includes("@")) {
|
||||
let split = req.params['id'].split("@");
|
||||
req.params['id'] = split[0];
|
||||
userAddress = split[1];
|
||||
}
|
||||
|
||||
let wopiData = parseWopiRequest(req);
|
||||
|
||||
if (wopiData.requestType == reqConsts.requestType.None) {
|
||||
res.status(500).send({ 'title': 'fileHandler', 'method': req.method, 'id': req.params['id'], 'error': "unknown" });
|
||||
return;
|
||||
}
|
||||
|
||||
let action = actionMapping[wopiData.requestType];
|
||||
if (!action) {
|
||||
res.status(501).send({ 'title': 'fileHandler', 'method': req.method, 'id': req.params['id'], 'error': "unsupported" });
|
||||
return;
|
||||
}
|
||||
|
||||
action(wopiData, req, res);
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var lockDict = {};
|
||||
|
||||
function getLockObject(filePath) {
|
||||
return lockDict[filePath];
|
||||
}
|
||||
|
||||
function clearLockTimeout(lockObject) {
|
||||
if (lockObject && lockObject.timeout) {
|
||||
clearTimeout(lockObject.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function getLockValue(filePath) {
|
||||
let lock = getLockObject(filePath);
|
||||
if (lock) return lock.value;
|
||||
return "";
|
||||
}
|
||||
|
||||
function hasLock(filePath) {
|
||||
return !!getLockObject(filePath);
|
||||
}
|
||||
|
||||
function lock(filePath, lockValue) {
|
||||
let oldLock = getLockObject(filePath);
|
||||
clearLockTimeout(oldLock);
|
||||
|
||||
lockDict[filePath] = {
|
||||
value: lockValue,
|
||||
timeout: setTimeout(unlock, 1000 * 60 * 30, filePath) // set lock for 30 minutes
|
||||
}
|
||||
}
|
||||
|
||||
function unlock(filePath) {
|
||||
let lock = getLockObject(filePath);
|
||||
clearLockTimeout(lock);
|
||||
delete lockDict[filePath];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasLock: hasLock,
|
||||
getLock: getLockValue,
|
||||
lock: lock,
|
||||
unlock: unlock
|
||||
}
|
||||
66
web/documentserver-example/nodejs/helpers/wopi/request.js
Normal file
66
web/documentserver-example/nodejs/helpers/wopi/request.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
const requestType = Object.freeze({
|
||||
"None": 0,
|
||||
|
||||
"CheckFileInfo": 1,
|
||||
"PutRelativeFile": 2,
|
||||
|
||||
"Lock": 3,
|
||||
"GetLock": 4,
|
||||
"Unlock": 5,
|
||||
"RefreshLock": 6,
|
||||
"UnlockAndRelock": 7,
|
||||
|
||||
"ExecuteCobaltRequest": 8,
|
||||
|
||||
"DeleteFile": 9,
|
||||
"ReadSecureStore": 10,
|
||||
"GetRestrictedLink": 11,
|
||||
"RevokeRestrictedLink": 12,
|
||||
|
||||
"CheckFolderInfo": 13,
|
||||
|
||||
"GetFile": 14,
|
||||
"PutFile": 16,
|
||||
|
||||
"EnumerateChildren": 16,
|
||||
|
||||
"RenameFile": 17,
|
||||
"PutUserInfo": 18,
|
||||
});
|
||||
|
||||
const requestHeaders = Object.freeze({
|
||||
"RequestType": "X-WOPI-Override",
|
||||
"ItemVersion": "X-WOPI-ItemVersion",
|
||||
|
||||
"Lock": "X-WOPI-Lock",
|
||||
"OldLock": "X-WOPI-OldLock",
|
||||
"LockFailureReason": "X-WOPI-LockFailureReason",
|
||||
"LockedByOtherInterface": "X-WOPI-LockedByOtherInterface",
|
||||
|
||||
"SuggestedTarget": "X-WOPI-SuggestedTarget",
|
||||
"RelativeTarget": "X-WOPI-RelativeTarget",
|
||||
"OverwriteRelativeTarget": "X-WOPI-OverwriteRelativeTarget",
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
requestType: requestType,
|
||||
requestHeaders: requestHeaders,
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
exports.isValidToken = (req, res, next) => {
|
||||
if (true) {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
115
web/documentserver-example/nodejs/helpers/wopi/utils.js
Normal file
115
web/documentserver-example/nodejs/helpers/wopi/utils.js
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
const config = require("config");
|
||||
const configServer = config.get("server");
|
||||
const siteUrl = configServer.get('siteUrl'); // the path to the editors installation
|
||||
const syncRequest = require("sync-request");
|
||||
const xmlParser = require("fast-xml-parser");
|
||||
const he = require("he");
|
||||
|
||||
var cache = null;
|
||||
|
||||
function getDiscoveryInfo(maxTry = 1) {
|
||||
let actions = [];
|
||||
|
||||
if (cache) return cache;
|
||||
|
||||
try {
|
||||
let response = syncRequest("GET", siteUrl + configServer.get("wopi.discovery"));
|
||||
let discovery = xmlParser.parse(response.getBody().toString(), {
|
||||
attributeNamePrefix: "",
|
||||
ignoreAttributes: false,
|
||||
parseAttributeValue: true,
|
||||
attrValueProcessor: (val, attrName) => he.decode(val, { isAttributeValue: true })
|
||||
});
|
||||
for (let app of discovery["wopi-discovery"]["net-zone"].app) {
|
||||
if (!Array.isArray(app.action)) { app.action = [app.action]; }
|
||||
for (let action of app.action) {
|
||||
actions.push({
|
||||
app: app.name,
|
||||
favIconUrl: app.favIconUrl,
|
||||
checkLicense: app.checkLicense == 'true',
|
||||
name: action.name,
|
||||
ext: action.ext || "",
|
||||
progid: action.progid || "",
|
||||
isDefault: action.default ? true : false,
|
||||
urlsrc: action.urlsrc,
|
||||
requires: action.requires || ""
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (--maxTry > 0) {
|
||||
setTimeout(getDiscoveryInfo, 1000, maxTry);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
cache = actions;
|
||||
setTimeout(() => cache = null, 1000 * 60 * 60); // 1 hour
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
function getActions(ext) {
|
||||
let actions = getDiscoveryInfo();
|
||||
let filtered = [];
|
||||
|
||||
for (let action of actions) {
|
||||
if (action.ext == ext) {
|
||||
filtered.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
function getAction(ext, name) {
|
||||
let actions = getDiscoveryInfo();
|
||||
|
||||
for (let action of actions) {
|
||||
if (action.ext == ext && action.name == name) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getDefaultAction(ext) {
|
||||
let actions = getDiscoveryInfo();
|
||||
|
||||
for (let action of actions) {
|
||||
if (action.ext == ext && action.isDefault) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getActionUrl(host, userAddress, action, filename) {
|
||||
return action.urlsrc.replace(/<.*&>/g, "") + "WOPISrc=" + host + "/wopi/files/" + filename + "@" + userAddress;
|
||||
}
|
||||
|
||||
exports.getDiscoveryInfo = getDiscoveryInfo;
|
||||
exports.getAction = getAction;
|
||||
exports.getActions = getActions;
|
||||
exports.getActionUrl = getActionUrl;
|
||||
exports.getDefaultAction = getDefaultAction;
|
||||
110
web/documentserver-example/nodejs/helpers/wopi/wopiRouting.js
Normal file
110
web/documentserver-example/nodejs/helpers/wopi/wopiRouting.js
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
const tokenValidator = require("./tokenValidator");
|
||||
const filesController = require("./filesController");
|
||||
const utils = require("./utils");
|
||||
const docManager = require("../docManager");
|
||||
const fileUtility = require("../fileUtility");
|
||||
const config = require('config');
|
||||
const configServer = config.get('server');
|
||||
const storageFolder = configServer.get("storageFolder");
|
||||
const users = require("../users");
|
||||
|
||||
exports.registerRoutes = function(app) {
|
||||
|
||||
app.get("/wopi", function(req, res) {
|
||||
|
||||
utils.getDiscoveryInfo(3);
|
||||
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
|
||||
let files = docManager.getStoredFiles();
|
||||
|
||||
for (var file of files) {
|
||||
let ext = fileUtility.getFileExtension(file.name, true);
|
||||
file.actions = utils.getActions(ext);
|
||||
file.defaultAction = utils.getDefaultAction(ext);
|
||||
}
|
||||
|
||||
res.render("wopiIndex", {
|
||||
storedFiles: files,
|
||||
params: docManager.getCustomParams(),
|
||||
users: users,
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
res.status(500);
|
||||
res.render("error", { message: "Server error" });
|
||||
return;
|
||||
}
|
||||
});
|
||||
app.get("/wopi-new", function(req, res) {
|
||||
var fileExt = req.query.fileExt;
|
||||
var user = users.getUser(req.query.userid);
|
||||
|
||||
if (fileExt != null) {
|
||||
var fileName = docManager.createDemo(!!req.query.sample, fileExt, user.id, user.name);
|
||||
var redirectPath = docManager.getServerUrl() + "/wopi-action/" + encodeURIComponent(fileName) + "?action=edit" + docManager.getCustomParams();
|
||||
res.redirect(redirectPath);
|
||||
return;
|
||||
}
|
||||
});
|
||||
app.get("/wopi-action/:id", function(req, res) {
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
|
||||
let action = utils.getAction(fileUtility.getFileExtension(req.params['id'], true), req.query["action"]);
|
||||
|
||||
res.render("wopiAction", {
|
||||
actionUrl: utils.getActionUrl(docManager.getServerUrl(), docManager.curUserHostAddress(), action, req.params['id']),
|
||||
token: "test",
|
||||
tokenTtl: Date.now() + 1000 * 60 * 60 * 10,
|
||||
params: docManager.getCustomParams(),
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
res.status(500);
|
||||
res.render("error", { message: "Server error" });
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
app.route('/wopi/files/:id')
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
|
||||
app.route('/wopi/files/:id/contents')
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
|
||||
app.route('/wopi/folders/:id')
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
|
||||
app.route('/wopi/folders/:id/contents')
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
};
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Amit Kumar Gupta
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
20
web/documentserver-example/nodejs/licenses/he.license
Normal file
20
web/documentserver-example/nodejs/licenses/he.license
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -594,6 +594,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"fast-xml-parser": {
|
||||
"version": "3.19.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz",
|
||||
"integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg=="
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
@ -758,6 +763,11 @@
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"http-basic": {
|
||||
"version": "8.1.3",
|
||||
"resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz",
|
||||
|
||||
@ -20,7 +20,9 @@
|
||||
"debug": "^4.2.0",
|
||||
"ejs": "^3.1.5",
|
||||
"express": "^4.17.1",
|
||||
"fast-xml-parser": "^3.19.0",
|
||||
"formidable": "^1.2.2",
|
||||
"he": "^1.2.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwa": "^2.0.0",
|
||||
"log4js": "^6.3.0",
|
||||
|
||||
Submodule web/documentserver-example/nodejs/public/assets updated: 4a1673c5ca...65addf50e4
@ -247,7 +247,8 @@ label .checkbox {
|
||||
width: 192px;
|
||||
}
|
||||
|
||||
.create-panel {
|
||||
.create-panel,
|
||||
.links-panel {
|
||||
float: left;
|
||||
padding: 16px 0;
|
||||
}
|
||||
@ -258,6 +259,12 @@ label .checkbox {
|
||||
border-bottom: 1px solid #D0D5DA;
|
||||
}
|
||||
|
||||
.links-panel-border {
|
||||
margin-top: 24px;
|
||||
width: 100%;
|
||||
border-top: 1px solid #D0D5DA;
|
||||
}
|
||||
|
||||
#mainProgress {
|
||||
color: #333333;
|
||||
display: none;
|
||||
@ -558,6 +565,15 @@ footer a:hover {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.contentCells-wopi {
|
||||
width: 16%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contentCells-wopi a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
"modifyFilter": <%- editor.modifyFilter %>,
|
||||
"modifyContentControl": <%- editor.modifyContentControl %>,
|
||||
"review": <%- editor.review %>,
|
||||
"reviewGroups": <%- editor.reviewGroups %>
|
||||
"reviewGroups": <%- editor.reviewGroups %>,
|
||||
"commentGroups": <%- editor.commentGroups %>
|
||||
}
|
||||
},
|
||||
"editorConfig": {
|
||||
@ -31,7 +32,8 @@
|
||||
"mode": "<%- editor.mode %>",
|
||||
"lang": "<%- editor.lang %>",
|
||||
"callbackUrl": "<%- editor.callbackUrl %>",
|
||||
"createUrl": "<%- editor.createUrl%>",
|
||||
"createUrl": <%- JSON.stringify(editor.createUrl) %>,
|
||||
"templates": <%- JSON.stringify(editor.templates) %>,
|
||||
"user": {
|
||||
"group": "<%- editor.userGroup %>",
|
||||
"id": "<%- editor.userid %>",
|
||||
|
||||
@ -132,29 +132,51 @@
|
||||
docEditor.setMailMergeRecipients(<%- JSON.stringify(dataMailMergeRecipients) %>); // insert recipient data for mail merge into the file
|
||||
};
|
||||
|
||||
var connectEditor = function () {
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", {<%- include("config") %>,
|
||||
events: {
|
||||
"onAppReady": onAppReady,
|
||||
"onDocumentStateChange": onDocumentStateChange,
|
||||
"onRequestEditRights": onRequestEditRights,
|
||||
"onError": onError,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose,
|
||||
"onOutdatedVersion": onOutdatedVersion,
|
||||
"onMakeActionLink": onMakeActionLink,
|
||||
"onMetaChange": onMetaChange,
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestCompareFile": onRequestCompareFile,
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
}
|
||||
var onRequestUsers = function () {
|
||||
docEditor.setUsers({
|
||||
"users": <%- JSON.stringify(usersForMentions) %>
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestSendNotify = function(event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
|
||||
var events = {
|
||||
"onAppReady": onAppReady,
|
||||
"onDocumentStateChange": onDocumentStateChange,
|
||||
"onRequestEditRights": onRequestEditRights,
|
||||
"onError": onError,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose,
|
||||
"onOutdatedVersion": onOutdatedVersion,
|
||||
"onMakeActionLink": onMakeActionLink,
|
||||
"onMetaChange": onMetaChange,
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestCompareFile": onRequestCompareFile,
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
};
|
||||
|
||||
var config = {<%- include("config") %>, events};
|
||||
|
||||
var connectEditor = function () {
|
||||
addMentions();
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
fixSize();
|
||||
};
|
||||
|
||||
var addMentions = function () {
|
||||
if (<%- JSON.stringify(usersForMentions) %> != null)
|
||||
{
|
||||
events.onRequestUsers = onRequestUsers;
|
||||
events.onRequestSendNotify = onRequestSendNotify;
|
||||
}
|
||||
};
|
||||
|
||||
// get the editor sizes
|
||||
var fixSize = function () {
|
||||
var wrapEl = document.getElementsByClassName("form");
|
||||
|
||||
@ -131,6 +131,10 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="links-panel links-panel-border clearFix">
|
||||
<a href="/wopi" class="">Go to WOPI page</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
77
web/documentserver-example/nodejs/views/wopiAction.ejs
Normal file
77
web/documentserver-example/nodejs/views/wopiAction.ejs
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<!--
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
-->
|
||||
<title>ONLYOFFICE Document Editors</title>
|
||||
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
-ms-content-zooming: none;
|
||||
}
|
||||
|
||||
#office_frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<form id="office_form" name="office_form" target="office_frame" action="<%= actionUrl %>" method="post">
|
||||
<input name="access_token" value="<%= token %><%= params %>" type="hidden" />
|
||||
<input name="access_token_ttl" value="<%= tokenTtl %>" type="hidden" />
|
||||
</form>
|
||||
|
||||
<span id="frameholder"></span>
|
||||
|
||||
<script type="text/javascript">
|
||||
var frameholder = document.getElementById('frameholder');
|
||||
var office_frame = document.createElement('iframe');
|
||||
office_frame.name = 'office_frame';
|
||||
office_frame.id = 'office_frame';
|
||||
|
||||
office_frame.title = 'Office Frame';
|
||||
office_frame.setAttribute('allowfullscreen', 'true');
|
||||
|
||||
office_frame.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation allow-popups-to-escape-sandbox');
|
||||
frameholder.appendChild(office_frame);
|
||||
|
||||
document.getElementById('office_form').submit();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
239
web/documentserver-example/nodejs/views/wopiIndex.ejs
Normal file
239
web/documentserver-example/nodejs/views/wopiIndex.ejs
Normal file
@ -0,0 +1,239 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<!--
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
-->
|
||||
<title>ONLYOFFICE Document Editors</title>
|
||||
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:900,800,700,600,500,400,300&subset=latin,cyrillic-ext,cyrillic,latin-ext" />
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" />
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/jquery-ui.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="center">
|
||||
<a href="">
|
||||
<img src="images/logo.svg" alt="ONLYOFFICE" />
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="center main">
|
||||
<table class="table-main">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="left-panel section">
|
||||
<div class="help-block">
|
||||
<span>Create new</span>
|
||||
<div class="clearFix">
|
||||
<div class="create-panel clearFix">
|
||||
<ul class="try-editor-list clearFix">
|
||||
<li>
|
||||
<a class="try-editor word reload-page" target="_blank" href="/wopi-new?fileExt=docx<%= params %>" title="Create new document">Document</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor cell reload-page" target="_blank" href="/wopi-new?fileExt=xlsx<%= params %>" title="Create new spreadsheet">Spreadsheet</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor slide reload-page" target="_blank" href="/wopi-new?fileExt=pptx<%= params %>" title="Create new presentation">Presentation</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
<input id="createSample" type="checkbox" class="checkbox" />With sample content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="user-block-table" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="middle">
|
||||
<span class="select-user">Username</span>
|
||||
<img class="info" data-id="user" data-tooltip="You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.
|
||||
</br>
|
||||
<% users.forEach(user => { %>
|
||||
<b><%= user.name == null ? 'Anonymous' : user.name %></b>
|
||||
<ul>
|
||||
<% user.descriptions.forEach(description => { %>
|
||||
<li><%= description %></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
<% }) %>"
|
||||
src="images/info.svg" />
|
||||
<select class="select-user" id="user">
|
||||
<% users.forEach(user => { %>
|
||||
<option value="<%= user.id %>"><%= user.name == null ? "Anonymous" : user.name %></option>
|
||||
<% }) %>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="middle">
|
||||
<span class="select-user">Language</span>
|
||||
<img class="info" data-id="language" data-tooltip="Choose the language for ONLYOFFICE editors interface" src="images/info.svg" />
|
||||
<select class="select-user" id="language">
|
||||
<option value="en">English</option>
|
||||
<option value="be">Belarusian</option>
|
||||
<option value="bg">Bulgarian</option>
|
||||
<option value="ca">Catalan</option>
|
||||
<option value="zh">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="da">Danish</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fi">Finnish</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="el">Greek</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="id">Indonesian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="lv">Latvian</option>
|
||||
<option value="lo">Lao</option>
|
||||
<option value="nb">Norwegian</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ro">Romanian</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="sk">Slovak</option>
|
||||
<option value="sl">Slovenian</option>
|
||||
<option value="sv">Swedish</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
<option value="uk">Ukrainian</option>
|
||||
<option value="vi">Vietnamese</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="links-panel links-panel-border clearFix">
|
||||
<a href="/" class="">Go to Index page</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="section">
|
||||
<div class="main-panel">
|
||||
<% if (storedFiles.length <= 0)
|
||||
{ %>
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
|
||||
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
|
||||
</span>
|
||||
<%} else
|
||||
{ %>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td class="tableHeaderCell tableHeaderCellEditors contentCells-shift"></td>
|
||||
<td class="tableHeaderCell tableHeaderCellViewers">WOPI Actions</td>
|
||||
<td class="tableHeaderCell tableHeaderCellDownload">Download</td>
|
||||
<td class="tableHeaderCell tableHeaderCellRemove">Remove</td>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div class="scroll-table-body">
|
||||
<table cellspacing="0" cellpadding="0" width="100%">
|
||||
<tbody>
|
||||
<% for (var i = 0; i < storedFiles.length; i++) { %>
|
||||
<tr class="tableRow" title="<%= storedFiles[i].name %> [<%= storedFiles[i].version %>]">
|
||||
<td class="contentCells">
|
||||
<% if (storedFiles[i].defaultAction) { %>
|
||||
<a class="stored-edit <%= storedFiles[i].documentType %>" href="wopi-action/<%= encodeURIComponent(storedFiles[i].name) %>?action=<%= storedFiles[i].defaultAction.name %><%= params %>">
|
||||
<%} else { %>
|
||||
<a class="stored-edit <%= storedFiles[i].documentType %>" href="#">
|
||||
<% } %>
|
||||
<span title="<%= storedFiles[i].name %> [<%= storedFiles[i].version %>]"><%= storedFiles[i].name %></span>
|
||||
</a>
|
||||
</td>
|
||||
<% if (storedFiles[i].actions && storedFiles[i].actions.length > 0) { %>
|
||||
<td class="contentCells contentCells-wopi contentCells-shift">
|
||||
<% for (var j = 0; j < storedFiles[i].actions.length; j++) { %>
|
||||
<a href="wopi-action/<%= encodeURIComponent(storedFiles[i].name) %>?action=<%= storedFiles[i].actions[j].name %><%= params %>" target="_blank">
|
||||
<% if (storedFiles[i].actions[j].name == "edit") { %>
|
||||
<img src="images/fill-forms-24.png" alt="<%= storedFiles[i].actions[j].name %>" title="<%= storedFiles[i].actions[j].name %>" />
|
||||
<%} else { %>
|
||||
<img src="images/desktop-24.png" alt="<%= storedFiles[i].actions[j].name %>" title="<%= storedFiles[i].actions[j].name %>" />
|
||||
<% } %>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<% } %>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<a href="wopi/files/<%= encodeURIComponent(storedFiles[i].name) %>/contents">
|
||||
<img class="icon-download" src="images/download-24.png" alt="Download" title="Download" /></a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<a class="delete-file" data="<%= encodeURIComponent(storedFiles[i].name) %>">
|
||||
<img class="icon-delete" src="images/delete-24.png" alt="Delete" title="Delete" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="center">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://api.onlyoffice.com/editors/howitworks" target="_blank">API Documentation</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="mailto:sales@onlyoffice.com">Submit your request</a>
|
||||
</td>
|
||||
<td class="copy">
|
||||
© Ascensio Systems SIA 2021. All rights reserved.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="text/javascript" src="javascripts/jquery-1.8.2.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery-ui.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery.blockUI.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery.iframe-transport.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery.fileupload.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery.dropdownToggle.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jscript.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -1,26 +1,22 @@
|
||||
# How to integrate online editors into your own web site on PHP
|
||||
## Overview
|
||||
|
||||
## Introduction
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in PHP.
|
||||
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **PHP** you need to download and install ONLYOFFICE editors on your local server and use the [PHP Example](https://api.onlyoffice.com/editors/demopreview) for their integration. We will show you how to run the PHP example on [Windows OS](#running-the-example-on-windows-os) and [Linux OS](#running-the-example-on-linux-os).
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
## For Windows
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
## Running the example on Windows OS
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_php_example).
|
||||
|
||||
## Step 2. Download the PHP code for the editors integration
|
||||
### Step 2. Download the PHP code
|
||||
|
||||
Download the [PHP example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
You need to connect the editors to your web site. For that specify the path to the editors installation in the *config.php* file:
|
||||
You need to connect the editors to your website. Specify the path to the editors installation in the *config.php* file:
|
||||
|
||||
```
|
||||
$GLOBALS['DOC_SERV_SITE_URL'] = "https://documentserver/";
|
||||
@ -30,15 +26,15 @@ where the **documentserver** is the name of the server with the ONLYOFFICE Docum
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *doceditor.php* file.
|
||||
|
||||
## Step 3. Install the prerequisites
|
||||
### Step 3. Install the prerequisites
|
||||
|
||||
You can use any web server capable of runnig PHP code to run the sample. We will demonstrate how to run the PHP sample using the **Internet Information Services (IIS)** web server. To set up and configure PHP on IIS, **PHP Manager for IIS** will be used.
|
||||
You can use any web server capable of runnig PHP code to run the example. We will demonstrate how to run the PHP example using the **Internet Information Services (IIS)** web server. To set up and configure PHP on IIS, **PHP Manager for IIS** will be used.
|
||||
|
||||
* **IIS: version 7** or later (refer to [Microsoft official website](https://www.iis.net/learn/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php) to learn how to install **IIS**);
|
||||
* **PHP** (download it from the [http://php.net](https://php.net/downloads.php) site);
|
||||
* **PHP Manager for IIS** (download it from the [Microsoft open source site](https://phpmanager.codeplex.com/releases/view/69115)).
|
||||
|
||||
## Step 4. IIS configuration
|
||||
### Step 4. IIS configuration
|
||||
|
||||
1. **PHP Manager for IIS** configuration.
|
||||
|
||||
@ -81,9 +77,9 @@ You can use any web server capable of runnig PHP code to run the sample. We will
|
||||
|
||||
After IIS manager configuration is complete, everything is ready for running the **PHP** example.
|
||||
|
||||
## Step 5. Running your web site with the editors
|
||||
### Step 5. Run your website with the editors
|
||||
|
||||
1. Add your web site in the IIS Manager.
|
||||
1. Add your website in the IIS Manager.
|
||||
|
||||
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
|
||||
|
||||
@ -97,25 +93,27 @@ You can use any web server capable of runnig PHP code to run the sample. We will
|
||||
|
||||

|
||||
|
||||
3. Browse your web site with the IIS manager:
|
||||
3. Browse your website with the IIS manager:
|
||||
|
||||
Right-click the site -> **Manage Website** -> **Browse**
|
||||
|
||||

|
||||
|
||||
## Step 6. Checking accessibility
|
||||
### Step 6. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
## Running the example on Linux OS
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
## For Linux
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_php_example).
|
||||
|
||||
## Step 2. Install the prerequisites and run the web site with the editors
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Apache** and **PHP**:
|
||||
|
||||
@ -175,8 +173,8 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
http://localhost/PHP%20Example/
|
||||
```
|
||||
|
||||
## Step 3. Checking accessibility
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
Submodule web/documentserver-example/php/assets updated: 4a1673c5ca...65addf50e4
@ -171,6 +171,17 @@ function getInternalExtension($filename) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// get image url for templates
|
||||
function getTemplateImageUrl($filename) {
|
||||
$ext = strtolower('.' . pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$path = serverPath(true) . "/css/images/";
|
||||
|
||||
if (in_array($ext, $GLOBALS['ExtsDocument'])) return $path . "file_docx.svg"; // for text document extensions
|
||||
if (in_array($ext, $GLOBALS['ExtsSpreadsheet'])) return $path . "file_xlsx.svg"; // for spreadsheet extensions
|
||||
if (in_array($ext, $GLOBALS['ExtsPresentation'])) return $path . "file_pptx.svg"; // for presentation extensions
|
||||
return $path . "file_docx.svg";
|
||||
}
|
||||
|
||||
// get the document type
|
||||
function getDocumentType($filename) {
|
||||
$ext = strtolower('.' . pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
@ -62,6 +62,21 @@
|
||||
$mode = $canEdit && $editorsMode != "view" ? "edit" : "view"; // define if the editing mode is edit or view
|
||||
$type = empty($_GET["type"]) ? "desktop" : $_GET["type"];
|
||||
|
||||
$templatesImageUrl = getTemplateImageUrl($filename); // templates image url in the "From Template" section
|
||||
$createUrl = getCreateUrl($filename, $user->id, $type);
|
||||
$templates = array(
|
||||
array (
|
||||
"image" => $templatesImageUrl,
|
||||
"title" => "Blank",
|
||||
"url" => $createUrl
|
||||
),
|
||||
array (
|
||||
"image" => $templatesImageUrl,
|
||||
"title" => "With sample content",
|
||||
"url" => $createUrl . "&sample=true"
|
||||
)
|
||||
);
|
||||
|
||||
// specify the document config
|
||||
$config = [
|
||||
"type" => $type,
|
||||
@ -86,7 +101,8 @@
|
||||
"modifyFilter" => $editorsMode != "filter",
|
||||
"modifyContentControl" => $editorsMode != "blockcontent",
|
||||
"review" => $canEdit && ($editorsMode == "edit" || $editorsMode == "review"),
|
||||
"reviewGroups" => $user->reviewGroups
|
||||
"reviewGroups" => $user->reviewGroups,
|
||||
"commentGroups" => $user->commentGroups
|
||||
]
|
||||
],
|
||||
"editorConfig" => [
|
||||
@ -94,7 +110,8 @@
|
||||
"mode" => $mode,
|
||||
"lang" => empty($_COOKIE["ulang"]) ? "en" : $_COOKIE["ulang"],
|
||||
"callbackUrl" => getCallbackUrl($filename), // absolute URL to the document storage service
|
||||
"createUrl" => getCreateUrl($filename, $user->id, $type),
|
||||
"createUrl" => $user->id != "uid-0" ? $createUrl : null,
|
||||
"templates" => $user->templates ? $templates : null,
|
||||
"user" => [ // the user currently viewing or editing the document
|
||||
"id" => $user->id,
|
||||
"name" => $user->name,
|
||||
@ -135,6 +152,9 @@
|
||||
"fileType" =>"csv",
|
||||
"url" => serverPath(true) . "/webeditor-ajax.php?type=csv"
|
||||
];
|
||||
|
||||
// users data for mentions
|
||||
$usersForMentions = $user->id != "uid-0" ? getUsersForMentions($user->id) : null;
|
||||
|
||||
// check if the secret key to generate token exists
|
||||
if (isJwtEnabled()) {
|
||||
@ -174,10 +194,10 @@
|
||||
function getCreateUrl($fileName, $uid, $type) {
|
||||
$ext = trim(getInternalExtension($fileName),'.');
|
||||
return serverPath(false) . '/'
|
||||
. "doceditor.php"
|
||||
. "?fileExt=" . $ext
|
||||
. "&user=" . $uid
|
||||
. "&type=" . $type;
|
||||
. "doceditor.php"
|
||||
. "?fileExt=" . $ext
|
||||
. "&user=" . $uid
|
||||
. "&type=" . $type;
|
||||
}
|
||||
|
||||
function getDownloadUrl($fileName) {
|
||||
@ -228,10 +248,10 @@
|
||||
$changes = json_decode(file_get_contents(getVersionDir($histDir, $i - 1) . DIRECTORY_SEPARATOR . "changes.json"), true); // get the path to the changes.json file
|
||||
$change = $changes["changes"][0];
|
||||
|
||||
$obj["changes"] = $changes["changes"]; // write information about changes to the object
|
||||
$obj["changes"] = $change ? $changes["changes"][0] : null; // write information about changes to the object
|
||||
$obj["serverVersion"] = $changes["serverVersion"];
|
||||
$obj["created"] = $change["created"];
|
||||
$obj["user"] = $change["user"];
|
||||
$obj["created"] = $change ? $change["created"] : null;
|
||||
$obj["user"] = $change ? $change["user"] : null;
|
||||
|
||||
$prev = $histData[$i - 2]; // get the history data from the previous file version
|
||||
$dataObj["previous"] = [ // write information about previous file version to the data object
|
||||
@ -441,6 +461,21 @@
|
||||
};
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($usersForMentions != null): ?>
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": <?php echo json_encode($usersForMentions) ?>
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
<?php endif; ?>
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -18,53 +18,80 @@
|
||||
*/
|
||||
|
||||
class User {
|
||||
function __construct($id, $name, $email, $group, $reviewGroups, $favorite, $deniedPermissions, $descriptions)
|
||||
function __construct($id, $name, $email, $group, $reviewGroups, $commentGroups, $favorite, $deniedPermissions, $descriptions, $templates)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->email = $email;
|
||||
$this->group = $group;
|
||||
$this->reviewGroups = $reviewGroups;
|
||||
$this->commentGroups = $commentGroups;
|
||||
$this->favorite = $favorite;
|
||||
$this->deniedPermissions = $deniedPermissions;
|
||||
$this->descriptions = $descriptions;
|
||||
$this->templates = $templates;
|
||||
}
|
||||
}
|
||||
|
||||
$descr_user_1 = [
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
];
|
||||
|
||||
$descr_user_2 = [
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
$descr_user_3 = [
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
$descr_user_0 = [
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
];
|
||||
|
||||
$users = [
|
||||
new User("uid-1", "John Smith", "smith@mial.ru", null, null, null, [], $descr_user_1),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mial.ru", "group-2", ["group-2", ""], true, [], $descr_user_2),
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mial.ru", "group-3", ["group-2"], false, ["copy", "download", "print"], $descr_user_3),
|
||||
new User("uid-0", null, null, null, null, null, [], $descr_user_0)
|
||||
new User("uid-1", "John Smith", "smith@mial.ru",
|
||||
null, null, [],
|
||||
null, [], $descr_user_1, true),
|
||||
new User("uid-2", "Mark Pottato", "pottato@mial.ru",
|
||||
"group-2", ["group-2", ""], [
|
||||
"view" => "",
|
||||
"edit" => ["group-2", ""],
|
||||
"remove" => ["group-2"]
|
||||
],
|
||||
true, [], $descr_user_2, false),
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@mial.ru",
|
||||
"group-3", ["group-2"], [
|
||||
"view" => ["group-3", "group-2"],
|
||||
"edit" => ["group-2"],
|
||||
"remove" => []
|
||||
],
|
||||
false, ["copy", "download", "print"], $descr_user_3, false),
|
||||
new User("uid-0", null, null,
|
||||
null, null, [],
|
||||
null, [], $descr_user_0, false)
|
||||
];
|
||||
|
||||
function getAllUsers() {
|
||||
@ -83,4 +110,17 @@ function getUser($id) {
|
||||
return $users[0];
|
||||
}
|
||||
|
||||
?>
|
||||
function getUsersForMentions($id) {
|
||||
global $users;
|
||||
$usersData = [];
|
||||
foreach ($users as $user) {
|
||||
if ($user->id != $id && $user->name != null && $user->email != null) {
|
||||
array_push($usersData,[
|
||||
"name" => $user->name,
|
||||
"email" => $user->email
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $usersData;
|
||||
}
|
||||
?>
|
||||
|
||||
Submodule web/documentserver-example/python/assets updated: 4a1673c5ca...65addf50e4
@ -1,24 +1,20 @@
|
||||
# How to integrate online editors into your own web site on Python
|
||||
## Overview
|
||||
|
||||
## Introduction
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in Python.
|
||||
|
||||
To integrate **ONLYOFFICE online editors** into your own web site on **Python** you need to download and install ONLYOFFICE editors on your local server and use the [Python Example](https://api.onlyoffice.com/editors/demopreview) for their integration. We will show how to run the Python example on Linux OS.
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
|
||||
First, download [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_python_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_python_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_python_example).
|
||||
|
||||
## Step 2. Install the prerequisites and run the web site with the editors
|
||||
## Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Python comes preinstalled on most Linux distributions, and is available as a package on all others. Python 3.9 is required. Please proceed to [official documentation](https://docs.python.org/3/using/unix.html) if you have any troubles.
|
||||
|
||||
2. Download the archive with the Python example and unpack the archive:
|
||||
2. Download the archive with the Python example and unpack it:
|
||||
|
||||
```
|
||||
wget "https://api.onlyoffice.com/app_data/editor/Python%20Example.zip"
|
||||
@ -71,8 +67,8 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
|
||||
http://localhost
|
||||
```
|
||||
|
||||
## Step 3. Checking accessibility
|
||||
## Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **exampleserver** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
@ -99,6 +99,17 @@ def getInternalExtension(fileType):
|
||||
|
||||
return mapping.get(fileType, '.docx') # the default file type is .docx
|
||||
|
||||
# get image url for templates
|
||||
def getTemplateImageUrl(fileType, request):
|
||||
path = getServerUrl(True, request) + '/static/images/'
|
||||
mapping = {
|
||||
'word': path + 'file_docx.svg',
|
||||
'cell': path + 'file_xlsx.svg',
|
||||
'slide': path + 'file_pptx.svg'
|
||||
}
|
||||
|
||||
return mapping.get(fileType, path + 'file_docx.svg') # the default file type
|
||||
|
||||
# get file name with an index if such a file name already exists
|
||||
def getCorrectName(filename, req):
|
||||
basename = fileUtils.getFileNameWithoutExt(filename)
|
||||
|
||||
@ -194,10 +194,10 @@ def getHistoryObject(storagePath, filename, docKey, docUrl, req):
|
||||
changes = json.loads(readFile(getChangesHistoryPath(prevVerDir))) # get the path to the changes.json file
|
||||
change = changes['changes'][0]
|
||||
|
||||
obj['changes'] = changes['changes'] # write information about changes to the object
|
||||
obj['changes'] = changes['changes'] if change else None # write information about changes to the object
|
||||
obj['serverVersion'] = changes['serverVersion']
|
||||
obj['created'] = change['created']
|
||||
obj['user'] = change['user']
|
||||
obj['created'] = change['created'] if change else None
|
||||
obj['user'] = change['user'] if change else None
|
||||
|
||||
prev = histData[str(i - 2)] # get the history data from the previous file version
|
||||
prevInfo = { # write key and url information about previous file version
|
||||
|
||||
@ -27,54 +27,85 @@
|
||||
from urllib.parse import unquote
|
||||
|
||||
class User:
|
||||
def __init__(self, id, name, email, group, reviewGroups, favorite, deniedPermissions, descriptions):
|
||||
def __init__(self, id, name, email, group, reviewGroups, commentGroups, favorite, deniedPermissions, descriptions, templates):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.email = email
|
||||
self.group = group
|
||||
self.reviewGroups = reviewGroups
|
||||
self.commentGroups = commentGroups
|
||||
self.favorite = favorite
|
||||
self.deniedPermissions = deniedPermissions
|
||||
self.descriptions = descriptions
|
||||
self.templates = templates
|
||||
|
||||
descr_user_1 = [
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
]
|
||||
|
||||
descr_user_2 = [
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
]
|
||||
|
||||
descr_user_3 = [
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
]
|
||||
|
||||
descr_user_0 = [
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
]
|
||||
|
||||
USERS = [
|
||||
User('uid-1', 'John Smith', 'smith@mail.ru', None, None, None, [], descr_user_1),
|
||||
User('uid-2', 'Mark Pottato', 'pottato@mail.ru', 'group-2', ['group-2', ''], True, [], descr_user_2),
|
||||
User('uid-3', 'Hamish Mitchell', 'mitchell@mail.ru', 'group-3', ['group-2'], False, ["copy", "download", "print"], descr_user_3),
|
||||
User('uid-0', None, None, None, None, None, [], descr_user_0)
|
||||
User('uid-1', 'John Smith', 'smith@mail.ru',
|
||||
None, None, {},
|
||||
None, [], descr_user_1, True),
|
||||
User('uid-2', 'Mark Pottato', 'pottato@mail.ru',
|
||||
'group-2', ['group-2', ''], {
|
||||
'view': "",
|
||||
'edit': ["group-2", ""],
|
||||
'remove': ["group-2"]
|
||||
},
|
||||
True, [], descr_user_2, False),
|
||||
User('uid-3', 'Hamish Mitchell', 'mitchell@mail.ru',
|
||||
'group-3', ['group-2'], {
|
||||
'view': ["group-3", "group-2"],
|
||||
'edit': ["group-2"],
|
||||
'remove': []
|
||||
},
|
||||
False, ["copy", "download", "print"], descr_user_3, False),
|
||||
User('uid-0', None, None,
|
||||
None, None, {},
|
||||
None, [], descr_user_0, False)
|
||||
]
|
||||
|
||||
DEFAULT_USER = USERS[0]
|
||||
|
||||
# get all users
|
||||
def getAllUsers():
|
||||
return USERS
|
||||
|
||||
# get user information from the request
|
||||
def getUserFromReq(req):
|
||||
uid = req.COOKIES.get('uid')
|
||||
@ -84,3 +115,11 @@ def getUserFromReq(req):
|
||||
return user
|
||||
|
||||
return DEFAULT_USER
|
||||
|
||||
# get users data for mentions
|
||||
def getUsersForMentions(uid):
|
||||
usersData = []
|
||||
for user in USERS:
|
||||
if(user.id != uid and user.name != None and user.email != None):
|
||||
usersData.append({'name':user.name, 'email':user.email})
|
||||
return usersData
|
||||
|
||||
@ -141,6 +141,21 @@ def edit(request):
|
||||
actionData = request.GET.get('actionLink') # get the action data that will be scrolled to (comment or bookmark)
|
||||
actionLink = json.loads(actionData) if actionData else None
|
||||
|
||||
templatesImageUrl = docManager.getTemplateImageUrl(fileType, request) # templates image url in the "From Template" section
|
||||
createUrl = docManager.getCreateUrl(edType, request)
|
||||
templates = [
|
||||
{
|
||||
'image': templatesImageUrl,
|
||||
'title': 'Blank',
|
||||
'url': createUrl
|
||||
},
|
||||
{
|
||||
'image': templatesImageUrl,
|
||||
'title': 'With sample content',
|
||||
'url': createUrl + '&sample=true'
|
||||
}
|
||||
]
|
||||
|
||||
if (meta): # if the document meta data exists,
|
||||
infObj = { # write author and creation time parameters to the information object
|
||||
'owner': meta['uname'],
|
||||
@ -172,7 +187,8 @@ def edit(request):
|
||||
'modifyFilter': edMode != 'filter',
|
||||
'modifyContentControl': edMode != "blockcontent",
|
||||
'review': canEdit & ((edMode == 'edit') | (edMode == 'review')),
|
||||
'reviewGroups': user.reviewGroups
|
||||
'reviewGroups': user.reviewGroups,
|
||||
'commentGroups': user.commentGroups
|
||||
}
|
||||
},
|
||||
'editorConfig': {
|
||||
@ -180,7 +196,8 @@ def edit(request):
|
||||
'mode': mode,
|
||||
'lang': lang,
|
||||
'callbackUrl': docManager.getCallbackUrl(filename, request), # absolute URL to the document storage service
|
||||
'createUrl': docManager.getCreateUrl(edType, request),
|
||||
'createUrl' : createUrl if user.id !='uid-0' else None,
|
||||
'templates' : templates if user.templates else None,
|
||||
'user': { # the user currently viewing or editing the document
|
||||
'id': user.id,
|
||||
'name': user.name,
|
||||
@ -222,6 +239,9 @@ def edit(request):
|
||||
'url': docManager.getServerUrl(True, request) + 'csv'
|
||||
}
|
||||
|
||||
# users data for mentions
|
||||
usersForMentions = users.getUsersForMentions(user.id)
|
||||
|
||||
if jwtManager.isEnabled(): # if the secret key to generate token exists
|
||||
edConfig['token'] = jwtManager.encode(edConfig) # encode the edConfig object into a token
|
||||
dataInsertImage['token'] = jwtManager.encode(dataInsertImage) # encode the dataInsertImage object into a token
|
||||
@ -238,7 +258,8 @@ def edit(request):
|
||||
'apiUrl': config.DOC_SERV_SITE_URL + config.DOC_SERV_API_URL, # the absolute URL to the api
|
||||
'dataInsertImage': json.dumps(dataInsertImage)[1 : len(json.dumps(dataInsertImage)) - 1], # the image which will be inserted into the document
|
||||
'dataCompareFile': dataCompareFile, # document which will be compared with the current document
|
||||
'dataMailMergeRecipients': json.dumps(dataMailMergeRecipients) # recipient data for mail merging
|
||||
'dataMailMergeRecipients': json.dumps(dataMailMergeRecipients), # recipient data for mail merging
|
||||
'usersForMentions': json.dumps(usersForMentions) if user.id !='uid-0' else None
|
||||
}
|
||||
return render(request, 'editor.html', context) # execute the "editor.html" template with context data
|
||||
|
||||
|
||||
@ -171,6 +171,23 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if usersForMentions %}
|
||||
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": {{ usersForMentions | safe }}
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
|
||||
{% endif %}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
|
||||
fixSize();
|
||||
|
||||
@ -1,20 +1,16 @@
|
||||
# How to integrate online editors into your own web site on Ruby
|
||||
## Overview
|
||||
|
||||
## Introduction
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written on Ruby.
|
||||
|
||||
To integrate **ONLYOFFICE online editors** into your own website on **Ruby** you need to download and install ONLYOFFICE editors on your local server and use the [Ruby Example](https://api.onlyoffice.com/editors/demopreview) for their integration. We will show how to run the Ruby example on Linux OS.
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
|
||||
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
This guide will show you the sequence of actions to integrate the editors successfully.
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
## Step 1. Download and Install Document Server
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx).
|
||||
|
||||
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_ruby_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_ruby_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_ruby_example).
|
||||
|
||||
## Step 2. Install the prerequisites and run the web site with the editors
|
||||
## Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Ruby Version Manager (RVM)** and the latest stable **Ruby** version:
|
||||
|
||||
@ -76,8 +72,8 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *views\home\editor.html.erb* file.
|
||||
|
||||
## Step 3. Checking accessibility
|
||||
## Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
@ -276,6 +276,23 @@ class DocumentHelper
|
||||
ext
|
||||
end
|
||||
|
||||
# get image url for templates
|
||||
def get_template_image_url(file_type)
|
||||
path = get_server_url(true) + "/assets/"
|
||||
case file_type
|
||||
when 'word' # for word type
|
||||
full_path = path + 'file_docx.svg'
|
||||
when 'cell' # .xlsx for cell type
|
||||
full_path = path + 'file_xlsx.svg'
|
||||
when 'slide' # .pptx for slide type
|
||||
full_path = path + 'file_pptx.svg'
|
||||
else
|
||||
full_path = path + 'file_docx.svg' # the default value is .docx
|
||||
end
|
||||
|
||||
full_path
|
||||
end
|
||||
|
||||
# get files information
|
||||
def get_files_info(file_id)
|
||||
result = [];
|
||||
|
||||
@ -84,6 +84,19 @@ class FileModel
|
||||
canEdit = DocumentHelper.edited_exts.include?(file_ext) # check if the document can be edited
|
||||
submitForm = canEdit && (editorsmode.eql?("edit") || editorsmode.eql?("fillForms")) # the Submit form button state
|
||||
mode = canEdit && !editorsmode.eql?("view") ? "edit" : "view"
|
||||
templatesImageUrl = DocumentHelper.get_template_image_url(document_type) # templates image url in the "From Template" section
|
||||
templates = [
|
||||
{
|
||||
:image => templatesImageUrl,
|
||||
:title => "Blank",
|
||||
:url => create_url
|
||||
},
|
||||
{
|
||||
:image => templatesImageUrl,
|
||||
:title => "With sample content",
|
||||
:url => create_url + "&sample=true"
|
||||
}
|
||||
]
|
||||
|
||||
config = {
|
||||
:type => type(),
|
||||
@ -108,7 +121,8 @@ class FileModel
|
||||
:modifyFilter => !editorsmode.eql?("filter"),
|
||||
:modifyContentControl => !editorsmode.eql?("blockcontent"),
|
||||
:review => canEdit && (editorsmode.eql?("edit") || editorsmode.eql?("review")),
|
||||
:reviewGroups => @user.reviewGroups
|
||||
:reviewGroups => @user.reviewGroups,
|
||||
:commentGroups => @user.commentGroups
|
||||
}
|
||||
},
|
||||
:editorConfig => {
|
||||
@ -116,7 +130,8 @@ class FileModel
|
||||
:mode => mode,
|
||||
:lang => @lang ? @lang : "en",
|
||||
:callbackUrl => callback_url, # absolute URL to the document storage service
|
||||
:createUrl => create_url,
|
||||
:createUrl => !@user.id.eql?("uid-0") ? create_url : nil,
|
||||
:templates => @user.templates ? templates : nil,
|
||||
:user => { # the user currently viewing or editing the document
|
||||
:id => @user.id,
|
||||
:name => @user.name,
|
||||
@ -193,6 +208,7 @@ class FileModel
|
||||
|
||||
if (i > 1) # check if the version number is greater than 1
|
||||
changes = nil
|
||||
change = nil
|
||||
File.open(File.join(DocumentHelper.version_dir(hist_dir, i - 1), "changes.json"), 'r') do |file| # get the path to the changes.json file
|
||||
changes = JSON.parse(file.read()) # and parse its content
|
||||
end
|
||||
@ -200,10 +216,10 @@ class FileModel
|
||||
change = changes["changes"][0]
|
||||
|
||||
# write information about changes to the object
|
||||
obj["changes"] = changes["changes"]
|
||||
obj["changes"] = change ? changes["changes"] : nil
|
||||
obj["serverVersion"] = changes["serverVersion"]
|
||||
obj["created"] = change["created"]
|
||||
obj["user"] = change["user"]
|
||||
obj["created"] = change ? change["created"] : nil
|
||||
obj["user"] = change ? change["user"] : nil
|
||||
|
||||
prev = histData[(i - 2).to_s] # get the history data from the previous file version
|
||||
dataObj["previous"] = { # write key and url information about previous file version
|
||||
@ -278,4 +294,9 @@ class FileModel
|
||||
return dataMailMergeRecipients
|
||||
end
|
||||
|
||||
# get users data for mentions
|
||||
def get_users_mentions
|
||||
return !@user.id.eql?("uid-0") ? Users.get_users_for_mentions(@user.id) : nil
|
||||
end
|
||||
|
||||
end
|
||||
@ -15,55 +15,82 @@
|
||||
#
|
||||
|
||||
class User
|
||||
attr_accessor :id, :name, :email, :group, :reviewGroups, :favorite, :deniedPermissions, :descriptions
|
||||
attr_accessor :id, :name, :email, :group, :reviewGroups, :commentGroups, :favorite, :deniedPermissions, :descriptions, :templates
|
||||
|
||||
def initialize (id, name, email, group, reviewGroups, favorite, deniedPermissions, descriptions)
|
||||
def initialize (id, name, email, group, reviewGroups, commentGroups, favorite, deniedPermissions, descriptions, templates)
|
||||
@id = id
|
||||
@name = name
|
||||
@email = email
|
||||
@group = group
|
||||
@reviewGroups = reviewGroups
|
||||
@commentGroups = commentGroups
|
||||
@favorite = favorite
|
||||
@deniedPermissions = deniedPermissions
|
||||
@descriptions = descriptions
|
||||
@templates = templates
|
||||
end
|
||||
end
|
||||
|
||||
class Users
|
||||
@@descr_user_1 = [
|
||||
"File author by default",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
];
|
||||
|
||||
@@descr_user_2 = [
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"This file is favorite"
|
||||
"Belongs to Group2",
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
@@descr_user_3 = [
|
||||
"He belongs to Group3",
|
||||
"He can review only the changes made by the users from Group2",
|
||||
"This file isn’t favorite",
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file"
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
];
|
||||
|
||||
@@descr_user_0 = [
|
||||
"The user without a name. The name is requested upon the editor opening",
|
||||
"He doesn’t belong to any of the groups",
|
||||
"He can review all the changes",
|
||||
"The file favorite state is undefined"
|
||||
"The name is requested when the editor is opened",
|
||||
"Doesn’t belong to any group",
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
];
|
||||
|
||||
@@users = [
|
||||
User.new("uid-1", "John Smith", "smith@mail.ru", nil, nil, nil, [], @@descr_user_1),
|
||||
User.new("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", ["group-2", ""], true, [], @@descr_user_2),
|
||||
User.new("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", ["group-2"], false, ["copy", "download", "print"], @@descr_user_3),
|
||||
User.new("uid-0", nil, nil, nil, nil, nil, [], @@descr_user_0)
|
||||
User.new("uid-1", "John Smith", "smith@mail.ru",
|
||||
nil, nil, {},
|
||||
nil, [], @@descr_user_1, true),
|
||||
User.new("uid-2", "Mark Pottato", "pottato@mail.ru",
|
||||
"group-2", ["group-2", ""], {
|
||||
:view => "",
|
||||
:edit => ["group-2", ""],
|
||||
:remove => ["group-2"]
|
||||
},
|
||||
true, [], @@descr_user_2, false),
|
||||
User.new("uid-3", "Hamish Mitchell", "mitchell@mail.ru",
|
||||
"group-3", ["group-2"], {
|
||||
:view => ["group-3", "group-2"],
|
||||
:edit => ["group-2"],
|
||||
:remove => []
|
||||
},
|
||||
false, ["copy", "download", "print"], @@descr_user_3, false),
|
||||
User.new("uid-0", nil, nil,
|
||||
nil, nil, {},
|
||||
nil, [], @@descr_user_0, false)
|
||||
]
|
||||
|
||||
class << self
|
||||
@ -79,6 +106,17 @@ class Users
|
||||
end
|
||||
return @@users[0]
|
||||
end
|
||||
|
||||
def get_users_for_mentions(id)
|
||||
usersData = []
|
||||
for user in @@users do
|
||||
if (!user.id.eql?(id) && user.name != nil && user.email != nil)
|
||||
usersData.push({:name => user.name, :email => user.email})
|
||||
end
|
||||
end
|
||||
return usersData
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -129,16 +129,16 @@
|
||||
};
|
||||
|
||||
<%
|
||||
h = @file.get_history
|
||||
if h %>
|
||||
history = @file.get_history
|
||||
if history %>
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= raw h[:hist].to_json %>); // show the document version history
|
||||
docEditor.refreshHistory(<%= raw history[:hist].to_json %>); // show the document version history
|
||||
};
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= raw h[:histData].to_json %>;
|
||||
var histData = <%= raw history[:histData].to_json %>;
|
||||
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
|
||||
};
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
@ -148,6 +148,24 @@
|
||||
<% end
|
||||
%>
|
||||
|
||||
<%
|
||||
usersMentions = @file.get_users_mentions
|
||||
if usersMentions %>
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({
|
||||
"users": <%= raw @file.get_users_mentions.to_json %>
|
||||
});
|
||||
};
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
var actionLink = JSON.stringify(event.data.actionLink);
|
||||
console.log("onRequestSendNotify:");
|
||||
console.log(event.data);
|
||||
console.log("Link to comment: " + replaceActionLink(location.href, actionLink));
|
||||
};
|
||||
<% end
|
||||
%>
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user