Compare commits
207 Commits
v8.1.0.172
...
feature/we
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ef1987010 | |||
| e9f298d073 | |||
| e89eee7e28 | |||
| 6a4b79fb54 | |||
| b1dd965590 | |||
| 208bf086d8 | |||
| ebb1179190 | |||
| 3375315cc0 | |||
| a070b6e82b | |||
| 43d260cd7a | |||
| 14bb9fc8a4 | |||
| 57ca15153f | |||
| bbde4dc87b | |||
| 5b46195f72 | |||
| 81c94c9fbd | |||
| cc3c640868 | |||
| 20e6664a6b | |||
| 61af52a534 | |||
| 6236f90a50 | |||
| 5118352714 | |||
| aa5a660001 | |||
| bf1f987333 | |||
| f1f834fb0c | |||
| 53c3e97b5c | |||
| eda1876f59 | |||
| 64eab6c4a2 | |||
| acb9a0e4c9 | |||
| 909f638a92 | |||
| 6d28e3f8d8 | |||
| 12ad0d9e7e | |||
| f3b35a878c | |||
| c712f596e1 | |||
| 7d2eb086ce | |||
| 0a61708f67 | |||
| 389198aec6 | |||
| 0d302ee8f6 | |||
| d3a548bf3f | |||
| fadae60e89 | |||
| 426b15b8f1 | |||
| 601146c847 | |||
| c4980c19e7 | |||
| 0bfb036be6 | |||
| 88b36049d2 | |||
| f1a1ec15ad | |||
| 683f1d33c4 | |||
| e8c98ba12a | |||
| e389cf41b8 | |||
| 80291baa40 | |||
| b9113f93f6 | |||
| af778a8636 | |||
| 47f4f022aa | |||
| b2202111ac | |||
| 1da215b1eb | |||
| 8c8d14b48c | |||
| 5217a64e83 | |||
| 456789191d | |||
| e1e9efa305 | |||
| a3016f3f96 | |||
| cee60a340a | |||
| 6c09b3f62a | |||
| 4b7ba35f83 | |||
| abab30176f | |||
| 1abcf78b85 | |||
| a952858ab8 | |||
| 5258fd0674 | |||
| ca274bc465 | |||
| b1d66e16a5 | |||
| 359cda0f67 | |||
| 24a3441b1e | |||
| a7fca1a53b | |||
| 5b6a2ba318 | |||
| bb4aed6efb | |||
| 01d8c0acde | |||
| 31cf6ca486 | |||
| fbe24234d2 | |||
| ac894171fb | |||
| 0f000c1457 | |||
| 1699dc22b5 | |||
| cc62ff8a61 | |||
| fd21292dbd | |||
| d43294bd8a | |||
| 81f5bdd528 | |||
| c1da8e14c3 | |||
| 767b5588ab | |||
| 8858c3c256 | |||
| 89f1c18d06 | |||
| 81ad7f7a64 | |||
| 23ba4ff5b3 | |||
| 423233e93f | |||
| 5f3eaa05f9 | |||
| 283d93667e | |||
| 158ac4161c | |||
| bf3df5c89d | |||
| d8251f3280 | |||
| e4db31fbd5 | |||
| b633f5ff19 | |||
| 0f0549c535 | |||
| e896f03acc | |||
| a74d6b8676 | |||
| 672aae3791 | |||
| 999e147539 | |||
| e57ad73d4f | |||
| 690ab5471b | |||
| 2460f2c7ac | |||
| e3342a030c | |||
| e7630f516d | |||
| 19a38df423 | |||
| 67a21fbe35 | |||
| 08dc8ae6a7 | |||
| dcf2fb43e0 | |||
| dca6f4173e | |||
| 9f2a72aafa | |||
| d8cb434ad2 | |||
| 96af86846b | |||
| fa5fb2f182 | |||
| f154ffc981 | |||
| 90142299e5 | |||
| 0f288d539e | |||
| 2ead6e1f7e | |||
| ea9ac4bb42 | |||
| 5775f44f27 | |||
| 4ce10d82a1 | |||
| 3e9e4281c5 | |||
| 3eac4912e1 | |||
| e8df1c2821 | |||
| da3224de7b | |||
| 819aa2b03f | |||
| f1aafa5fd6 | |||
| ff2bcd0ef6 | |||
| a17c349fb8 | |||
| 2268bd1cf4 | |||
| 605c21c0be | |||
| 3f0495321c | |||
| 18fd30700f | |||
| 9721187083 | |||
| bce5e3760a | |||
| e4d43eda2a | |||
| ac6632d25b | |||
| dab4841c1d | |||
| a7cf7ae378 | |||
| e85cb5137b | |||
| 163daa37c9 | |||
| 541a1e55b4 | |||
| d692abda4b | |||
| f0d7892526 | |||
| 3a2f30bfcd | |||
| 03cc008de8 | |||
| 5e76f08c83 | |||
| 4ca824f1d7 | |||
| ec268cacf7 | |||
| c683d17bda | |||
| 7918671725 | |||
| 408d80fff6 | |||
| 1b0e8df99f | |||
| 50104f1122 | |||
| b90f333fdd | |||
| 9e2aae1658 | |||
| 0168355600 | |||
| 480b8af172 | |||
| f5d767e59d | |||
| 62ad307327 | |||
| b3b605230f | |||
| ae2425f7e4 | |||
| 5849c9bb69 | |||
| 8ba1d5e8d7 | |||
| 91f3bda0b4 | |||
| 185605a1eb | |||
| 6563a26d2d | |||
| d9061c57a3 | |||
| b9c2c2e770 | |||
| a55d7b2d9d | |||
| e0489a6922 | |||
| dc14a9aa90 | |||
| 92206ed637 | |||
| 09f6ba00b2 | |||
| 43f1555c68 | |||
| 83535632bb | |||
| f1d41a4bf2 | |||
| f43e7414bb | |||
| 4455521e00 | |||
| 7b91694107 | |||
| 8edb65692a | |||
| a36f270829 | |||
| f726ae534c | |||
| 69b266489f | |||
| 7c18d08bc6 | |||
| 6717612fc1 | |||
| 7f678c9ed8 | |||
| ee951fbfbc | |||
| 91f32c1387 | |||
| 7051437928 | |||
| 0967c1c3ac | |||
| cf097501c6 | |||
| 0b0e0dad8c | |||
| d97291719a | |||
| 75ca703f8a | |||
| 01618fee17 | |||
| 78a8b56b48 | |||
| 3b9bad4a26 | |||
| 435b8013f6 | |||
| a9063af6e1 | |||
| bde236075c | |||
| f74f34504f | |||
| 3243a04a1b | |||
| 6598aa585a | |||
| e02744e56b | |||
| ec596753c6 |
@ -1,7 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
- fill permission in embedded mode
|
||||
- delete all files
|
||||
- handling conversion -9 error
|
||||
- nodejs: wopi formsubmit icon
|
||||
- nodejs: tabs menu
|
||||
- change insert image
|
||||
- different goback for users
|
||||
- nodejs: converting function on index page
|
||||
- nodejs: close editor
|
||||
|
||||
## 1.8.0
|
||||
@ -9,7 +15,7 @@
|
||||
- nodejs: filling pdf
|
||||
- version number to page meta
|
||||
- ar skin languages
|
||||
- sr-Latn-CS skin languages
|
||||
- sr-Latn-RS skin languages
|
||||
- getting history via api
|
||||
- using a repo with a list of formats
|
||||
- convert after uploading only tagged formats
|
||||
|
||||
10
Readme.md
@ -1,11 +1,11 @@
|
||||
## Integration examples
|
||||
|
||||
Test examples are simple document management systems that can be built into your application for testing.
|
||||
These test examples are simple document management systems that can be built into your application for testing.
|
||||
Do NOT use these integration examples on your own server without proper code modifications!
|
||||
In case you enabled any of the test examples, disable it before going for production.
|
||||
|
||||
These examples show the way to integrate [ONLYOFFICE Docs][2] into your own website or application using one of the programming languages.
|
||||
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Node.js, PHP and Ruby.
|
||||
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Java Spring, Node.js, PHP, Python and Ruby.
|
||||
|
||||
You should change `http://documentserver` to your server address in these files:
|
||||
* [.Net (C# MVC)](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/csharp-mvc) - `web/documentserver-example/csharp-mvc/web.appsettings.config`
|
||||
@ -13,9 +13,9 @@ You should change `http://documentserver` to your server address in these files:
|
||||
* [Java](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java) - `web/documentserver-example/java/src/main/resources/settings.properties`
|
||||
* [Java Spring](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java-spring) - `web/documentserver-example/java-spring/src/main/resources/application.properties`
|
||||
* [Node.js](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/nodejs) - `web/documentserver-example/nodejs/config/default.json`
|
||||
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/config.json`
|
||||
* [Python](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/python) - `web/documentserver-example/python/config.py`
|
||||
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/config/application.rb`
|
||||
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/src/configuration/ConfigurationManager.php`
|
||||
* [Python](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/python) - `web/documentserver-example/python/src/configuration/configuration.py`
|
||||
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/app/configuration/configuration.rb`
|
||||
|
||||
More information on how to use these examples can be found here: [http://api.onlyoffice.com/editors/demopreview](http://api.onlyoffice.com/editors/demopreview "http://api.onlyoffice.com/editors/demopreview")
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@ -502,6 +502,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -230,6 +230,33 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -592,6 +619,29 @@ footer table tr td:first-child {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -741,6 +791,16 @@ html {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
|
||||
@ -229,6 +229,10 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
|
||||
switch (errorCode)
|
||||
{
|
||||
case -9:
|
||||
// public const int c_nErrorConversionOutputFormatError = -9;
|
||||
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
|
||||
break;
|
||||
case -8:
|
||||
// public const int c_nErrorFileVKey = -8;
|
||||
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");
|
||||
|
||||
@ -59,7 +59,9 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about Group2 users",
|
||||
"Can’t submit forms"
|
||||
"Can’t submit forms",
|
||||
"Can't close history",
|
||||
"Can't restore the file version"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
@ -92,7 +94,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true,
|
||||
true
|
||||
true,
|
||||
new Goback(null, false)
|
||||
),
|
||||
new User(
|
||||
"uid-2",
|
||||
@ -111,7 +114,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
false,
|
||||
true
|
||||
true,
|
||||
new Goback("Go to Documents", null)
|
||||
),
|
||||
new User(
|
||||
"uid-3",
|
||||
@ -130,7 +134,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
null
|
||||
),
|
||||
new User(
|
||||
"uid-0",
|
||||
@ -144,7 +149,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
new List<string>() { "protect" },
|
||||
descr_user_0,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
null
|
||||
)
|
||||
};
|
||||
|
||||
@ -235,7 +241,9 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
public List<string> userInfoGroups;
|
||||
public bool avatar;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar)
|
||||
public Goback goback;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar, Goback goback)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@ -249,6 +257,21 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
this.templates = templates;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
this.avatar = avatar;
|
||||
this.goback = goback;
|
||||
}
|
||||
}
|
||||
|
||||
public class Goback
|
||||
{
|
||||
public string text;
|
||||
public bool? blank;
|
||||
|
||||
public Goback(){}
|
||||
|
||||
public Goback(string text, bool? blank)
|
||||
{
|
||||
this.text = text;
|
||||
this.blank = blank;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,10 +214,12 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
|
||||
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
|
||||
{
|
||||
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
|
||||
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
|
||||
{
|
||||
{ "url", DocManagerHelper.GetServerUrl(false) } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
|
||||
}
|
||||
{ "url", DocManagerHelper.GetServerUrl(false) }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
|
||||
{ "text", user.goback.text },
|
||||
{ "blank", user.goback.blank }
|
||||
} : new Dictionary<string, object>{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -289,20 +291,20 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "Content\\images\\logo.png"
|
||||
+ "Content\\images\\logo.svg"
|
||||
};
|
||||
|
||||
var directMailMergeUrl = new UriBuilder(DocManagerHelper.GetServerUrl(false))
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "Content\\images\\logo.png"
|
||||
+ "Content\\images\\logo.svg"
|
||||
};
|
||||
|
||||
// create a logo config
|
||||
var logoConfig = new Dictionary<string, object>
|
||||
{
|
||||
{ "fileType", "png"},
|
||||
{ "fileType", "svg"},
|
||||
{ "url", mailMergeUrl.ToString()}
|
||||
};
|
||||
|
||||
|
||||
@ -145,7 +145,6 @@
|
||||
<Content Include="Content\images\icon_xlsx.svg" />
|
||||
<Content Include="Content\images\info.svg" />
|
||||
<Content Include="Content\images\loader16.gif" />
|
||||
<Content Include="Content\images\logo.png" />
|
||||
<Content Include="Content\images\logo.svg" />
|
||||
<Content Include="Content\images\mobile-fill-forms.svg" />
|
||||
<Content Include="Content\images\mobile.svg" />
|
||||
|
||||
66
web/documentserver-example/csharp-mvc/Scripts/formats.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class Format {
|
||||
constructor(name, type, actions, convert, mime) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.actions = actions;
|
||||
this.convert = convert;
|
||||
this.mime = mime;
|
||||
}
|
||||
|
||||
isAutoConvertible() {
|
||||
return this.actions.includes('auto-convert');
|
||||
}
|
||||
|
||||
isEditable() {
|
||||
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
|
||||
}
|
||||
|
||||
isFillable() {
|
||||
return this.actions.includes('fill');
|
||||
}
|
||||
}
|
||||
|
||||
class FormatManager {
|
||||
formats = [];
|
||||
|
||||
constructor(formats) {
|
||||
if(Array.isArray(formats)) this.formats = formats;
|
||||
}
|
||||
|
||||
findByExtension(extension) {
|
||||
return this.formats.find(format => format.name == extension);
|
||||
}
|
||||
|
||||
isAutoConvertible(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isAutoConvertible();
|
||||
}
|
||||
|
||||
isEditable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isEditable();
|
||||
}
|
||||
|
||||
isFillable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isFillable();
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,27 @@
|
||||
*/
|
||||
|
||||
var directUrl;
|
||||
var formatManager;
|
||||
|
||||
window.onload = function () {
|
||||
fetch("webeditor.ashx?type=formats")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.formats) {
|
||||
let formats = [];
|
||||
data.formats.forEach(format => {
|
||||
formats.push(new Format(
|
||||
format.Name,
|
||||
format.Type,
|
||||
format.Actions,
|
||||
format.Convert,
|
||||
format.Mime
|
||||
));
|
||||
});
|
||||
formatManager = new FormatManager(formats);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof jQuery != "undefined") {
|
||||
jq = jQuery.noConflict();
|
||||
@ -87,7 +108,7 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
var checkConvert = function (filePass) {
|
||||
var checkConvert = function (filePass, fileType) {
|
||||
filePass = filePass ? filePass : null;
|
||||
if (timer != null) {
|
||||
clearTimeout(timer);
|
||||
@ -103,7 +124,7 @@ if (typeof jQuery != "undefined") {
|
||||
var posExt = fileName.lastIndexOf('.');
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (ConverExtList.indexOf(posExt) == -1) {
|
||||
if (!formatManager.isAutoConvertible(posExt)) {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
return;
|
||||
@ -116,7 +137,7 @@ if (typeof jQuery != "undefined") {
|
||||
contentType: "text/xml",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({ filename: fileName, filePass: filePass }),
|
||||
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
|
||||
url: UrlConverter,
|
||||
complete: function (data) {
|
||||
var responseText = data.responseText;
|
||||
@ -132,6 +153,12 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (response.error.includes("Error conversion output format")) {
|
||||
jq("#select-file-type").removeClass("invisible");
|
||||
jq("#step2").removeClass("current");
|
||||
jq("#hiddenFileName").attr("placeholder", filePass);
|
||||
return;
|
||||
}
|
||||
jq(".current").removeClass("current");
|
||||
jq(".step:not(.done)").addClass("error");
|
||||
jq("#mainProgress .error-message").show().find("span").text(response.error);
|
||||
@ -143,7 +170,7 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#hiddenFileName").val(response.filename);
|
||||
|
||||
if (response.step && response.step < 100) {
|
||||
checkConvert(filePass);
|
||||
checkConvert(filePass, fileType);
|
||||
} else {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
@ -178,10 +205,10 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#beginView, #beginEmbedded").removeClass("disable");
|
||||
|
||||
var fileName = jq("#hiddenFileName").val();
|
||||
var posExt = fileName.lastIndexOf('.');
|
||||
var posExt = fileName.lastIndexOf('.') + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (EditedExtList.indexOf(posExt) != -1 || FillExtList.indexOf(posExt) != -1) {
|
||||
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
@ -213,6 +240,15 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", ".file-type:not(.disable)", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileType = currentElement.attr("data");
|
||||
var filePass = jq("#hiddenFileName").attr("placeholder");
|
||||
jq('.file-type').addClass(["disable", "pale"]);
|
||||
currentElement.removeClass("pale");
|
||||
checkConvert(filePass, fileType);
|
||||
});
|
||||
|
||||
jq(document).on("click", "#enterPass", function () {
|
||||
var filePass = jq("#filePass").val();
|
||||
if (filePass) {
|
||||
@ -294,6 +330,23 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
});
|
||||
|
||||
jq(document).on("click", ".clear-all", function () {
|
||||
if (confirm("Delete all the files?")) {
|
||||
var requestAddress = "webeditor.ashx"
|
||||
+ "?type=remove";
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
if (JSON.parse(data.responseText).success) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showUserTooltip (isMobile) {
|
||||
if ( jq("div#portal-info").is(":hidden") ) {
|
||||
jq("div#portal-info").show();
|
||||
|
||||
@ -259,6 +259,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
<% string usersForMentions; %>
|
||||
<% Model.GetUsersMentions(Request, out usersForMentions); %>
|
||||
<% string usersInfo; %>
|
||||
<% Model.GetUsersInfo(Request, out usersInfo); %>
|
||||
<% string usersForProtect; %>
|
||||
<% Model.GetUsersProtect(Request, out usersForProtect); %>
|
||||
|
||||
var onRequestUsers = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%= usersInfo %>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%= usersForProtect %>;
|
||||
break;
|
||||
default:
|
||||
users = <%= usersForMentions %>;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestSendNotify = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
|
||||
config = <%= Model.GetDocConfig(Request, Url) %>;
|
||||
|
||||
config.width = "100%";
|
||||
@ -276,63 +318,27 @@
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
|
||||
};
|
||||
|
||||
<% string usersForMentions; %>
|
||||
<% Model.GetUsersMentions(Request, out usersForMentions); %>
|
||||
<% string usersInfo; %>
|
||||
<% Model.GetUsersInfo(Request, out usersInfo); %>
|
||||
<% string usersForProtect; %>
|
||||
<% Model.GetUsersProtect(Request, out usersForProtect); %>
|
||||
|
||||
if (config.editorConfig.user.id) {
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = onRequestHistory;
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = onRequestHistoryData;
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = onRequestRestore;
|
||||
if (config.editorConfig.user.id !== "uid-3") {
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = onRequestRestore;
|
||||
}
|
||||
|
||||
// add mentions for not anonymous users
|
||||
<% if (!string.IsNullOrEmpty(usersForMentions))
|
||||
{ %>
|
||||
config.events['onRequestUsers'] = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%= usersInfo %>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%= usersForProtect %>;
|
||||
break;
|
||||
default:
|
||||
users = <%= usersForMentions %>;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
config.events['onRequestUsers'] = onRequestUsers;
|
||||
<% } %>
|
||||
|
||||
// the user is mentioned in a comment
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
config.events['onRequestSendNotify'] = onRequestSendNotify;
|
||||
// prevent file renaming for anonymous users
|
||||
config.events['onRequestRename'] = onRequestRename;
|
||||
config.events['onRequestReferenceData'] = onRequestReferenceData;
|
||||
@ -346,12 +352,6 @@
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -151,7 +151,14 @@
|
||||
if (storedFiles.Any())
|
||||
{ %>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -295,6 +302,15 @@
|
||||
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
|
||||
<span id="step1" class="step">1. Loading the file.</span>
|
||||
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
|
||||
<div id="select-file-type" class="invisible">
|
||||
<br />
|
||||
<span class="step">Please select the current document type</span>
|
||||
<div class="buttonsMobile indent">
|
||||
<div class="button file-type document" data="docx">Document</div>
|
||||
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
|
||||
<div class="button file-type presentation" data="pptx">Presentation</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<span id="step2" class="step">2. Conversion.</span>
|
||||
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
|
||||
@ -357,9 +373,6 @@
|
||||
<%: Scripts.Render("~/bundles/jquery", "~/bundles/scripts") %>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
var FillExtList = '<%= string.Join(",", DocManagerHelper.FillFormExts.ToArray()) %>';
|
||||
var ConverExtList = '<%= string.Join(",", DocManagerHelper.ConvertExts.ToArray()) %>';
|
||||
var EditedExtList = '<%= string.Join(",", DocManagerHelper.EditedExts.ToArray()) %>';
|
||||
var UrlConverter = '<%= Url.Content("~/webeditor.ashx?type=convert") %>';
|
||||
var UrlEditor = '<%= Url.Action("editor", "Home") %>';
|
||||
</script>
|
||||
|
||||
@ -87,6 +87,9 @@ namespace OnlineEditorsExampleMVC
|
||||
case "reference":
|
||||
Reference(context);
|
||||
break;
|
||||
case "formats":
|
||||
Formats(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +243,13 @@ namespace OnlineEditorsExampleMVC
|
||||
var fileUri = DocManagerHelper.GetDownloadUrl(fileName);
|
||||
|
||||
var extension = (Path.GetExtension(fileName).ToLower() ?? "").Trim('.');
|
||||
var internalExtension = "ooxml";
|
||||
string conversionExtension = "ooxml";
|
||||
object fileExt;
|
||||
|
||||
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
|
||||
{
|
||||
conversionExtension = fileExt.ToString();
|
||||
}
|
||||
|
||||
// check if the file with such an extension can be converted
|
||||
if (DocManagerHelper.ConvertExts.Contains("." + extension))
|
||||
@ -258,7 +267,7 @@ namespace OnlineEditorsExampleMVC
|
||||
|
||||
// get the url and file type of the converted file
|
||||
Dictionary<string, string> newFileData;
|
||||
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, internalExtension, key, true, out newFileData, filePass, lang);
|
||||
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, conversionExtension, key, true, out newFileData, filePass, lang);
|
||||
if (result != 100)
|
||||
{
|
||||
context.Response.Write("{ \"step\" : \"" + result + "\", \"filename\" : \"" + fileName + "\"}");
|
||||
@ -393,8 +402,17 @@ namespace OnlineEditorsExampleMVC
|
||||
context.Response.ContentType = "text/plain";
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
Remove(fileName); // remove a file and its history if it exists
|
||||
string fileName = context.Request["fileName"];
|
||||
|
||||
if (!String.IsNullOrEmpty(fileName))
|
||||
{
|
||||
fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
Remove(fileName); // remove a file and its history if it exists
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveUserDirectory(); // remove the user's directory
|
||||
}
|
||||
|
||||
context.Response.Write("{ \"success\": true }");
|
||||
}
|
||||
@ -414,6 +432,14 @@ namespace OnlineEditorsExampleMVC
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
|
||||
}
|
||||
|
||||
// remove the user's directory
|
||||
private static void RemoveUserDirectory()
|
||||
{
|
||||
var path = DocManagerHelper.StoragePath("", null); // get the path to the user directory
|
||||
|
||||
if (Directory.Exists(path)) Directory.Delete(path, true);
|
||||
}
|
||||
|
||||
// get files information
|
||||
private static void Files(HttpContext context)
|
||||
{
|
||||
@ -951,6 +977,25 @@ namespace OnlineEditorsExampleMVC
|
||||
return history;
|
||||
}
|
||||
|
||||
// return all the supported formats
|
||||
private static void Formats(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<string, object> data = new Dictionary<string, object>
|
||||
{
|
||||
{ "formats", FormatManager.All() }
|
||||
};
|
||||
context.Response.ContentType = "application/json";
|
||||
var jss = new JavaScriptSerializer();
|
||||
|
||||
context.Response.Write(jss.Serialize(data));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
<add key="files.docservice.verify-peer-off" value="true"/>
|
||||
|
||||
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-CS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
|
||||
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
|
||||
|
||||
<add key="files.docservice.url.site" value="http://documentserver/"/>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@ -502,6 +502,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -230,6 +230,33 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -596,6 +623,29 @@ footer a:hover {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -745,6 +795,16 @@ html {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
|
||||
@ -153,7 +153,14 @@
|
||||
if (storedFiles.Any())
|
||||
{ %>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr >
|
||||
@ -297,6 +304,15 @@
|
||||
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
|
||||
<span id="step1" class="step">1. Loading the file.</span>
|
||||
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
|
||||
<div id="select-file-type" class="invisible">
|
||||
<br />
|
||||
<span class="step">Please select the current document type</span>
|
||||
<div class="buttonsMobile indent">
|
||||
<div class="button file-type document" data="docx">Document</div>
|
||||
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
|
||||
<div class="button file-type presentation" data="pptx">Presentation</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<span id="step2" class="step">2. Conversion.</span>
|
||||
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
|
||||
@ -364,12 +380,8 @@
|
||||
<script language="javascript" type="text/javascript" src="script/jquery.iframe-transport.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="script/jquery.fileupload.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="script/jquery.dropdownToggle.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="script/formats.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="script/jscript.js"></script>
|
||||
<script language="javascript" type="text/javascript">
|
||||
var FillFormExtList = '<%= string.Join(",", FillFormsExts.ToArray()) %>';
|
||||
var ConverExtList = '<%= string.Join(",", ConvertExts.ToArray()) %>';
|
||||
var EditedExtList = '<%= string.Join(",", EditedExts.ToArray()) %>';
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -437,7 +437,14 @@ namespace OnlineEditorsExample
|
||||
var lang = context.Request.Cookies.GetOrDefault("ulang", null);
|
||||
|
||||
var extension = (Path.GetExtension(_fileName).ToLower() ?? "").Trim('.');
|
||||
var internalExtension = "ooxml";
|
||||
string conversionExtension = "ooxml"; // set the default conversion extension as ooxml
|
||||
object fileExt;
|
||||
|
||||
// change the conversion extension if it was provided in the request body
|
||||
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
|
||||
{
|
||||
conversionExtension = fileExt.ToString();
|
||||
}
|
||||
|
||||
// check if the file with such an extension can be converted
|
||||
if (ConvertExts.Contains("." + extension))
|
||||
@ -454,7 +461,7 @@ namespace OnlineEditorsExample
|
||||
|
||||
// get the url and file type of the converted file
|
||||
Dictionary<string, string> newFileData;
|
||||
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, internalExtension, key, true, out newFileData, filePass, lang);
|
||||
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, conversionExtension, key, true, out newFileData, filePass, lang);
|
||||
if (result != 100)
|
||||
{
|
||||
return "{ \"step\" : \"" + result + "\", \"filename\" : \"" + _fileName + "\"}";
|
||||
|
||||
@ -233,6 +233,41 @@
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestUsers = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%= UsersInfo %>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%= UsersForProtect %>;
|
||||
break;
|
||||
default:
|
||||
users = <%= UsersForMentions %>;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestSendNotify = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
|
||||
config = <%= DocConfig %>;
|
||||
|
||||
config.width = "100%";
|
||||
@ -275,65 +310,36 @@
|
||||
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
|
||||
}
|
||||
};
|
||||
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = function (event) {
|
||||
var fileName = "<%= FileName %>";
|
||||
var version = event.data.version;
|
||||
var data = {
|
||||
fileName: fileName,
|
||||
version: version
|
||||
if (config.editorConfig.user.id !== "uid-3") {
|
||||
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = function (event) {
|
||||
var fileName = "<%= FileName %>";
|
||||
var version = event.data.version;
|
||||
var data = {
|
||||
fileName: fileName,
|
||||
version: version
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// add mentions for not anonymous users
|
||||
<% if (!string.IsNullOrEmpty(UsersForMentions))
|
||||
{ %>
|
||||
config.events['onRequestUsers'] = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%= UsersInfo %>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%= UsersForProtect %>;
|
||||
break;
|
||||
default:
|
||||
users = <%= UsersForMentions %>;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
config.events['onRequestUsers'] = onRequestUsers;
|
||||
<% } %>
|
||||
|
||||
// the user is mentioned in a comment
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
config.events['onRequestSendNotify'] = onRequestSendNotify;
|
||||
// prevent file renaming for anonymous users
|
||||
config.events['onRequestRename'] = onRequestRename;
|
||||
config.events['onRequestReferenceData'] = onRequestReferenceData;
|
||||
@ -347,12 +353,6 @@
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -282,10 +282,12 @@ namespace OnlineEditorsExample
|
||||
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
|
||||
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
|
||||
{
|
||||
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
|
||||
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
|
||||
{
|
||||
{ "url", _Default.GetServerUrl(false) + "default.aspx" } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
|
||||
}
|
||||
{ "url", _Default.GetServerUrl(false) + "default.aspx" }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
|
||||
{ "text", user.goback.text },
|
||||
{ "blank", user.goback.blank }
|
||||
} : new Dictionary<string, object>{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,17 +340,17 @@ namespace OnlineEditorsExample
|
||||
var InsertImageUrl = new UriBuilder(_Default.GetServerUrl(true));
|
||||
InsertImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "App_Themes\\images\\logo.png";
|
||||
+ "App_Themes\\images\\logo.svg";
|
||||
|
||||
var DirectImageUrl = new UriBuilder(_Default.GetServerUrl(false));
|
||||
DirectImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "App_Themes\\images\\logo.png";
|
||||
+ "App_Themes\\images\\logo.svg";
|
||||
|
||||
// create a logo config
|
||||
Dictionary<string, object> logoConfig = new Dictionary<string, object>
|
||||
{
|
||||
{ "fileType", "png"},
|
||||
{ "fileType", "svg"},
|
||||
{ "url", InsertImageUrl.ToString()}
|
||||
};
|
||||
|
||||
|
||||
@ -231,6 +231,10 @@ namespace ASC.Api.DocumentConverter
|
||||
|
||||
switch (errorCode)
|
||||
{
|
||||
case -9:
|
||||
// public const int c_nErrorConversionOutputFormatError = -9;
|
||||
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
|
||||
break;
|
||||
case -8:
|
||||
// public const int c_nErrorFileVKey = -8;
|
||||
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");
|
||||
|
||||
@ -145,7 +145,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App_Themes\images\loader16.gif" />
|
||||
<Content Include="App_Themes\images\logo.png" />
|
||||
<Content Include="App_Themes\jquery-ui.css" />
|
||||
<Content Include="App_Themes\stylesheet.css" />
|
||||
<Content Include="DocEditor.aspx" />
|
||||
|
||||
@ -58,7 +58,9 @@ namespace OnlineEditorsExample
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about Group2 users",
|
||||
"Can’t submit forms"
|
||||
"Can’t submit forms",
|
||||
"Can't close history",
|
||||
"Can't restore the file version"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
@ -91,7 +93,8 @@ namespace OnlineEditorsExample
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true,
|
||||
true
|
||||
true,
|
||||
new Goback(null, false)
|
||||
),
|
||||
new User(
|
||||
"uid-2",
|
||||
@ -110,7 +113,8 @@ namespace OnlineEditorsExample
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
false,
|
||||
true
|
||||
true,
|
||||
new Goback("Go to Documents",null)
|
||||
),
|
||||
new User(
|
||||
"uid-3",
|
||||
@ -129,7 +133,8 @@ namespace OnlineEditorsExample
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
null
|
||||
),
|
||||
new User(
|
||||
"uid-0",
|
||||
@ -143,7 +148,8 @@ namespace OnlineEditorsExample
|
||||
new List<string>() { "protect" },
|
||||
descr_user_0,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
null
|
||||
)
|
||||
};
|
||||
|
||||
@ -235,8 +241,9 @@ namespace OnlineEditorsExample
|
||||
public bool templates;
|
||||
public List<string> userInfoGroups;
|
||||
public bool avatar;
|
||||
public Goback goback;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar)
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar, Goback goback)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@ -250,6 +257,21 @@ namespace OnlineEditorsExample
|
||||
this.templates = templates;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
this.avatar = avatar;
|
||||
this.goback = goback;
|
||||
}
|
||||
}
|
||||
|
||||
public class Goback
|
||||
{
|
||||
public string text;
|
||||
public bool? blank;
|
||||
|
||||
public Goback(){}
|
||||
|
||||
public Goback(string text, bool? blank)
|
||||
{
|
||||
this.text = text;
|
||||
this.blank = blank;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,6 +87,9 @@ namespace OnlineEditorsExample
|
||||
case "reference":
|
||||
Reference(context);
|
||||
break;
|
||||
case "formats":
|
||||
Formats(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,12 +225,22 @@ namespace OnlineEditorsExample
|
||||
context.Response.ContentType = "text/plain";
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var path = _Default.StoragePath(fileName, HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)));
|
||||
var histDir = _Default.HistoryDir(path);
|
||||
string fileName = context.Request["fileName"];
|
||||
string userAddress = HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress));
|
||||
|
||||
if (File.Exists(path)) File.Delete(path); // delete file
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
|
||||
if (!String.IsNullOrEmpty(fileName))
|
||||
{
|
||||
fileName = Path.GetFileName(fileName);
|
||||
var path = _Default.StoragePath(fileName, userAddress);
|
||||
var histDir = _Default.HistoryDir(path);
|
||||
|
||||
if (File.Exists(path)) File.Delete(path); // delete file
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
|
||||
} else
|
||||
{
|
||||
string userDir = _Default.StoragePath("", userAddress);
|
||||
if (Directory.Exists(userDir)) Directory.Delete(userDir, true); // delete the user's directory
|
||||
}
|
||||
|
||||
context.Response.Write("{ \"success\": true }");
|
||||
}
|
||||
@ -778,5 +791,25 @@ namespace OnlineEditorsExample
|
||||
+ userAddress;
|
||||
return fileUrl.ToString();
|
||||
}
|
||||
|
||||
// return all the supported formats
|
||||
private static void Formats(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<string, object> data = new Dictionary<string, object>
|
||||
{
|
||||
{ "formats", FormatManager.All() }
|
||||
};
|
||||
context.Response.ContentType = "application/json";
|
||||
var jss = new JavaScriptSerializer();
|
||||
|
||||
context.Response.Write(jss.Serialize(data));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
web/documentserver-example/csharp/script/formats.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class Format {
|
||||
constructor(name, type, actions, convert, mime) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.actions = actions;
|
||||
this.convert = convert;
|
||||
this.mime = mime;
|
||||
}
|
||||
|
||||
isAutoConvertible() {
|
||||
return this.actions.includes('auto-convert');
|
||||
}
|
||||
|
||||
isEditable() {
|
||||
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
|
||||
}
|
||||
|
||||
isFillable() {
|
||||
return this.actions.includes('fill');
|
||||
}
|
||||
}
|
||||
|
||||
class FormatManager {
|
||||
formats = [];
|
||||
|
||||
constructor(formats) {
|
||||
if(Array.isArray(formats)) this.formats = formats;
|
||||
}
|
||||
|
||||
findByExtension(extension) {
|
||||
return this.formats.find(format => format.name == extension);
|
||||
}
|
||||
|
||||
isAutoConvertible(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isAutoConvertible();
|
||||
}
|
||||
|
||||
isEditable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isEditable();
|
||||
}
|
||||
|
||||
isFillable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isFillable();
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,27 @@
|
||||
*/
|
||||
|
||||
var directUrl;
|
||||
var formatManager;
|
||||
|
||||
window.onload = function () {
|
||||
fetch("webeditor.ashx?type=formats")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.formats) {
|
||||
let formats = [];
|
||||
data.formats.forEach(format => {
|
||||
formats.push(new Format(
|
||||
format.Name,
|
||||
format.Type,
|
||||
format.Actions,
|
||||
format.Convert,
|
||||
format.Mime
|
||||
));
|
||||
});
|
||||
formatManager = new FormatManager(formats);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof jQuery != "undefined") {
|
||||
jq = jQuery.noConflict();
|
||||
@ -87,7 +108,7 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
var checkConvert = function (filePass) {
|
||||
var checkConvert = function (filePass, fileType) {
|
||||
filePass = filePass ? filePass : null;
|
||||
if (timer != null) {
|
||||
clearTimeout(timer);
|
||||
@ -103,7 +124,7 @@ if (typeof jQuery != "undefined") {
|
||||
var posExt = fileName.lastIndexOf('.');
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (ConverExtList.indexOf(posExt) == -1) {
|
||||
if (!formatManager.isAutoConvertible(posExt)) {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
return;
|
||||
@ -116,7 +137,7 @@ if (typeof jQuery != "undefined") {
|
||||
contentType: "text/xml",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({ filename: fileName, filePass: filePass }),
|
||||
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
var responseText = data.responseText;
|
||||
@ -132,6 +153,12 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (response.error.includes("Error conversion output format")) {
|
||||
jq("#select-file-type").removeClass("invisible");
|
||||
jq("#step2").removeClass("current");
|
||||
jq("#hiddenFileName").attr("placeholder", filePass);
|
||||
return;
|
||||
}
|
||||
jq(".current").removeClass("current");
|
||||
jq(".step:not(.done)").addClass("error");
|
||||
jq("#mainProgress .error-message").show().find("span").text(response.error);
|
||||
@ -143,7 +170,7 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#hiddenFileName").val(response.filename);
|
||||
|
||||
if (response.step && response.step < 100) {
|
||||
checkConvert(filePass);
|
||||
checkConvert(filePass, fileType);
|
||||
} else {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
@ -178,10 +205,10 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#beginView, #beginEmbedded").removeClass("disable");
|
||||
|
||||
var fileName = jq("#hiddenFileName").val();
|
||||
var posExt = fileName.lastIndexOf('.');
|
||||
var posExt = fileName.lastIndexOf('.') + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (EditedExtList.indexOf(posExt) != -1 || FillFormExtList.indexOf(posExt) != -1) {
|
||||
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
@ -213,6 +240,15 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", ".file-type:not(.disable)", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileType = currentElement.attr("data");
|
||||
var filePass = jq("#hiddenFileName").attr("placeholder");
|
||||
jq('.file-type').addClass(["disable", "pale"]);
|
||||
currentElement.removeClass("pale");
|
||||
checkConvert(filePass, fileType);
|
||||
});
|
||||
|
||||
jq(document).on("click", "#enterPass", function () {
|
||||
var filePass = jq("#filePass").val();
|
||||
if (filePass) {
|
||||
@ -293,6 +329,24 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
});
|
||||
|
||||
jq(document).on("click", ".clear-all", function () {
|
||||
if (confirm("Delete all the files?")) {
|
||||
var requestAddress = "webeditor.ashx"
|
||||
+ "?type=remove";
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
if (JSON.parse(data.responseText).success) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showUserTooltip (isMobile) {
|
||||
if ( jq("div#portal-info").is(":hidden") ) {
|
||||
jq("div#portal-info").show();
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
<add key="files.docservice.token.useforrequest" value="true" />
|
||||
|
||||
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-CS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
|
||||
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
|
||||
|
||||
<add key="files.docservice.url.site" value="http://documentserver/"/>
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
package com.onlyoffice.integration;
|
||||
|
||||
import com.onlyoffice.integration.documentserver.serializers.FilterState;
|
||||
import com.onlyoffice.integration.entities.Goback;
|
||||
import com.onlyoffice.integration.services.UserServices;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -92,30 +93,32 @@ public class ExampleData {
|
||||
"Can create a file from an editor",
|
||||
"Can see the information about Group2 users",
|
||||
"Can view chat",
|
||||
"Can’t submit forms"
|
||||
"Can’t submit forms",
|
||||
"Can't close history",
|
||||
"Can't restore the file version"
|
||||
);
|
||||
|
||||
// create user 1 with the specified parameters
|
||||
userService.createUser("John Smith", "smith@example.com", descriptionUserFirst,
|
||||
"", List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), null, true, true, true);
|
||||
List.of(FilterState.NULL.toString()), null, true, true, true, new Goback(null, false));
|
||||
|
||||
// create user 2 with the specified parameters
|
||||
userService.createUser("Mark Pottato", "pottato@example.com", descriptionUserSecond,
|
||||
"group-2", List.of("", "group-2"), List.of(FilterState.NULL.toString()),
|
||||
List.of("group-2", ""), List.of("group-2"), List.of("group-2", ""), true, true,
|
||||
true, true);
|
||||
true, true, new Goback("Go to Documents", null));
|
||||
|
||||
// create user 3 with the specified parameters
|
||||
userService.createUser("Hamish Mitchell", null, descriptionUserThird,
|
||||
"group-3", List.of("group-2"), List.of("group-2", "group-3"), List.of("group-2"),
|
||||
new ArrayList<>(), List.of("group-2"), false, true, true, false);
|
||||
new ArrayList<>(), List.of("group-2"), false, true, true, false, null);
|
||||
|
||||
// create user 0 with the specified parameters
|
||||
userService.createUser("Anonymous", null, descriptionUserZero, "",
|
||||
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
new ArrayList<>(), null, false, false, false);
|
||||
new ArrayList<>(), null, false, false, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,11 +212,11 @@ public class EditorController {
|
||||
@SneakyThrows
|
||||
private String getInsertImage(final Boolean directUrl) { // get an image that will be inserted into the document
|
||||
Map<String, Object> dataInsertImage = new HashMap<>();
|
||||
dataInsertImage.put("fileType", "png");
|
||||
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.png");
|
||||
dataInsertImage.put("fileType", "svg");
|
||||
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.svg");
|
||||
if (directUrl) {
|
||||
dataInsertImage.put("directUrl", storagePathBuilder
|
||||
.getServerUrl(false) + "/css/img/logo.png");
|
||||
.getServerUrl(false) + "/css/img/logo.svg");
|
||||
}
|
||||
|
||||
// check if the document token is enabled
|
||||
|
||||
@ -248,15 +248,15 @@ public class FileController {
|
||||
// get document type (word, cell or slide)
|
||||
DocumentType type = fileUtility.getDocumentType(fileName);
|
||||
|
||||
// convert to .ooxml
|
||||
String internalFileExt = "ooxml";
|
||||
// get an auto-conversion extension from the request body or set it to the ooxml extension
|
||||
String conversionExtension = body.getFileExt() != null ? body.getFileExt() : "ooxml";
|
||||
|
||||
try {
|
||||
// check if the file with such an extension can be converted
|
||||
if (fileUtility.getConvertExts().contains(fileExt)) {
|
||||
String key = serviceConverter.generateRevisionId(fileUri); // generate document key
|
||||
ConvertedData response = serviceConverter // get the URL to the converted file
|
||||
.getConvertedData(fileUri, fileExt, internalFileExt, key, filePass, true, lang);
|
||||
.getConvertedData(fileUri, fileExt, conversionExtension, key, filePass, true, lang);
|
||||
|
||||
String newFileUri = response.getUri();
|
||||
String newFileType = "." + response.getFileType();
|
||||
@ -291,24 +291,33 @@ public class FileController {
|
||||
return createUserMetadata(uid, fileName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// if the operation of file converting is unsuccessful, an error occurs
|
||||
return "{ \"error\": \"" + e.getMessage() + "\"}";
|
||||
}
|
||||
// if the operation of file converting is unsuccessful, an error occurs
|
||||
return "{ \"error\": \"" + "The file can't be converted.\"}";
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ResponseBody
|
||||
public String delete(@RequestBody final Converter body) { // delete a file
|
||||
try {
|
||||
String fullFileName = fileUtility.getFileName(body.getFileName()); // get full file name
|
||||
String filename = body.getFileName();
|
||||
boolean success = false;
|
||||
|
||||
// delete a file from the storage and return the status of this operation (true or false)
|
||||
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
|
||||
if (filename != null) {
|
||||
String fullFileName = fileUtility.getFileName(filename); // get full file name
|
||||
|
||||
// delete file history and return the status of this operation (true or false)
|
||||
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
|
||||
// delete a file from the storage and return the status of this operation (true or false)
|
||||
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
|
||||
|
||||
return "{ \"success\": \"" + (fileSuccess && historySuccess) + "\"}";
|
||||
// delete file history and return the status of this operation (true or false)
|
||||
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
|
||||
success = fileSuccess && historySuccess;
|
||||
} else {
|
||||
// delete the user's folder and return the boolean status
|
||||
success = storageMutator.deleteUserFolder();
|
||||
}
|
||||
return "{ \"success\": \"" + (success) + "\"}";
|
||||
} catch (Exception e) {
|
||||
// if the operation of file deleting is unsuccessful, an error occurs
|
||||
return "{ \"error\": \"" + e.getMessage() + "\"}";
|
||||
|
||||
@ -22,8 +22,10 @@ import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
import com.onlyoffice.integration.documentserver.util.Misc;
|
||||
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
|
||||
import com.onlyoffice.integration.documentserver.util.service.FormatService;
|
||||
import com.onlyoffice.integration.entities.User;
|
||||
import com.onlyoffice.integration.services.UserServices;
|
||||
import com.onlyoffice.integration.dto.FormatsList;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -33,6 +35,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -61,6 +64,9 @@ public class IndexController {
|
||||
@Autowired
|
||||
private UserServices userService;
|
||||
|
||||
@Autowired
|
||||
private FormatService formatService;
|
||||
|
||||
@Value("${files.docservice.url.site}")
|
||||
private String docserviceSite;
|
||||
|
||||
@ -136,16 +142,16 @@ public class IndexController {
|
||||
@ResponseBody
|
||||
public HashMap<String, String> configParameters() { // get configuration parameters
|
||||
HashMap<String, String> configuration = new HashMap<>();
|
||||
|
||||
configuration.put("FillExtList", String.join(",", fileUtility
|
||||
.getFillExts())); // put a list of the extensions that can be filled to config
|
||||
configuration.put("ConverExtList", String.join(",", fileUtility
|
||||
.getConvertExts())); // put a list of the extensions that can be converted to config
|
||||
configuration.put("EditedExtList", String.join(",", fileUtility
|
||||
.getEditedExts())); // put a list of the extensions that can be edited to config
|
||||
configuration.put("UrlConverter", urlConverter);
|
||||
configuration.put("UrlEditor", urlEditor);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@GetMapping("/formats")
|
||||
@ResponseBody
|
||||
public ResponseEntity<FormatsList> formats() { // return all the supported formats
|
||||
FormatsList list = new FormatsList(formatService.getFormats());
|
||||
return ResponseEntity.ok(list);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ package com.onlyoffice.integration.documentserver.models.configurations;
|
||||
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@ -38,9 +39,18 @@ public class Goback { // the settings for the Open file location menu button an
|
||||
private String indexMapping;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String url; /* the absolute URL to the website address which will be opened
|
||||
when clicking the Open file location menu button */
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String text;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Boolean blank;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
this.url = storagePathBuilder.getServerUrl(false) + indexMapping;
|
||||
|
||||
@ -27,7 +27,8 @@ public enum ConvertErrorType {
|
||||
UNEXPECTED_GUID_ERROR(-5, "Error unexpected guid"),
|
||||
DATABASE_ERROR(-6, "Error database"),
|
||||
DOCUMENT_REQUEST_ERROR(-7, "Error document request"),
|
||||
DOCUMENT_VKEY_ERROR(-8, "Error document VKey");
|
||||
DOCUMENT_VKEY_ERROR(-8, "Error document VKey"),
|
||||
DOCUMENT_CONVERSION_OUTPUT_ERROR(-9, "Error conversion output format");
|
||||
|
||||
private final int code;
|
||||
private final String label;
|
||||
|
||||
@ -31,6 +31,7 @@ public interface FileStorageMutator {
|
||||
boolean createFile(Path path, InputStream stream); // create a new file if it does not exist
|
||||
boolean deleteFile(String fileName); // delete a file
|
||||
boolean deleteFileHistory(String fileName); // delete file history
|
||||
boolean deleteUserFolder(); // delete the user's folder recursively
|
||||
String updateFile(String fileName, byte[] bytes); // update a file
|
||||
boolean writeToFile(String pathName, String payload); // write the payload to the file
|
||||
boolean moveFile(Path source, Path destination); // move a file to the specified destination
|
||||
|
||||
@ -202,6 +202,11 @@ public class LocalFileStorage implements FileStorageMutator, FileStoragePathBuil
|
||||
return historyDeleted || historyWithoutExtDeleted;
|
||||
}
|
||||
|
||||
// delete the user's folder recursively
|
||||
public boolean deleteUserFolder() {
|
||||
return FileSystemUtils.deleteRecursively(new File(getStorageLocation()));
|
||||
}
|
||||
|
||||
// update a file
|
||||
public String updateFile(final String fileName, final byte[] bytes) {
|
||||
Path path = fileUtility
|
||||
|
||||
@ -31,6 +31,8 @@ public class Converter {
|
||||
private String fileName;
|
||||
@JsonProperty("filePass")
|
||||
private String filePass;
|
||||
@JsonProperty("fileExt")
|
||||
private String fileExt;
|
||||
@JsonProperty("lang")
|
||||
private String lang;
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.onlyoffice.integration.documentserver.models.Format;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class FormatsList {
|
||||
private List<Format> formats;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.entities;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "`goback`")
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Goback extends AbstractEntity {
|
||||
private String text;
|
||||
private Boolean blank;
|
||||
}
|
||||
@ -47,4 +47,5 @@ public class User extends AbstractEntity {
|
||||
private List<String> descriptions;
|
||||
private Boolean avatar;
|
||||
private String image;
|
||||
private Goback goback;
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
package com.onlyoffice.integration.services;
|
||||
|
||||
import com.onlyoffice.integration.entities.Goback;
|
||||
import com.onlyoffice.integration.entities.Group;
|
||||
import com.onlyoffice.integration.entities.Permission;
|
||||
import com.onlyoffice.integration.entities.User;
|
||||
@ -59,7 +60,8 @@ public class UserServices {
|
||||
final List<String> userInfoGroups, final Boolean favoriteDoc,
|
||||
final Boolean chat,
|
||||
final Boolean protect,
|
||||
final Boolean avatar) {
|
||||
final Boolean avatar,
|
||||
final Goback goback) {
|
||||
User newUser = new User();
|
||||
newUser.setName(name); // set the user name
|
||||
newUser.setEmail(email); // set the user email
|
||||
@ -88,6 +90,8 @@ public class UserServices {
|
||||
protect); // specify permissions for the current user
|
||||
newUser.setPermissions(permission);
|
||||
|
||||
newUser.setGoback(goback);
|
||||
|
||||
userRepository.save(newUser); // save a new user
|
||||
|
||||
return newUser;
|
||||
|
||||
@ -34,5 +34,11 @@ public class DefaultCustomizationConfigurer implements CustomizationConfigurer<D
|
||||
public void configure(final Customization customization, final DefaultCustomizationWrapper wrapper) {
|
||||
Action action = wrapper.getAction(); // get the action parameter from the customization wrapper
|
||||
User user = wrapper.getUser();
|
||||
if (user != null && user.getGoback() != null) {
|
||||
customization.getGoback().setText(user.getGoback().getText());
|
||||
customization.getGoback().setBlank(user.getGoback().getBlank());
|
||||
} else {
|
||||
customization.getGoback().setUrl("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ files.docservice.token-use-for-request=true
|
||||
|
||||
files.docservice.verify-peer-off=true
|
||||
|
||||
files.docservice.languages=en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-CS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
|
||||
files.docservice.languages=en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
|
||||
|
||||
spring.datasource.url=jdbc:h2:mem:usersdb
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@ -489,6 +489,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -230,6 +230,33 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -595,6 +622,29 @@ footer table tr td:first-child {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -752,6 +802,16 @@ html {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
|
||||
@ -16,18 +16,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
var ConverExtList;
|
||||
var EditedExtList;
|
||||
var UrlConverter;
|
||||
var UrlEditor;
|
||||
var FillExtList;
|
||||
|
||||
if (typeof jQuery !== "undefined") {
|
||||
jQuery.post('/config',
|
||||
function(data) {
|
||||
FillExtList = data.FillExtList.split(',');
|
||||
ConverExtList = data.ConverExtList.split(',');
|
||||
EditedExtList = data.EditedExtList.split(',');
|
||||
UrlConverter = data.UrlConverter;
|
||||
UrlEditor = data.UrlEditor;
|
||||
});
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class Format {
|
||||
constructor(name, type, actions, convert, mime) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.actions = actions;
|
||||
this.convert = convert;
|
||||
this.mime = mime;
|
||||
}
|
||||
|
||||
isAutoConvertible() {
|
||||
return this.actions.includes('auto-convert');
|
||||
}
|
||||
|
||||
isEditable() {
|
||||
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
|
||||
}
|
||||
|
||||
isFillable() {
|
||||
return this.actions.includes('fill');
|
||||
}
|
||||
}
|
||||
|
||||
class FormatManager {
|
||||
formats = [];
|
||||
|
||||
constructor(formats) {
|
||||
if(Array.isArray(formats)) this.formats = formats;
|
||||
}
|
||||
|
||||
findByExtension(extension) {
|
||||
return this.formats.find(format => format.name == extension);
|
||||
}
|
||||
|
||||
isAutoConvertible(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isAutoConvertible();
|
||||
}
|
||||
|
||||
isEditable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isEditable();
|
||||
}
|
||||
|
||||
isFillable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isFillable();
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,27 @@
|
||||
*/
|
||||
|
||||
var directUrl;
|
||||
var formatManager;
|
||||
|
||||
window.onload = function () {
|
||||
fetch('/formats')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.formats) {
|
||||
let formats = [];
|
||||
data.formats.forEach(format => {
|
||||
formats.push(new Format(
|
||||
format.name,
|
||||
format.type,
|
||||
format.actions,
|
||||
format.convert,
|
||||
format.mime
|
||||
));
|
||||
});
|
||||
formatManager = new FormatManager(formats);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof jQuery !== "undefined") {
|
||||
jq = jQuery.noConflict();
|
||||
@ -87,7 +108,7 @@ if (typeof jQuery !== "undefined") {
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
var checkConvert = function (filePass) {
|
||||
var checkConvert = function (filePass, fileType) {
|
||||
filePass = filePass ? filePass : null;
|
||||
if (timer !== null) {
|
||||
clearTimeout(timer);
|
||||
@ -103,7 +124,7 @@ if (typeof jQuery !== "undefined") {
|
||||
var posExt = fileName.lastIndexOf(".") + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : "";
|
||||
|
||||
if (ConverExtList.includes(posExt) === -1) {
|
||||
if (!formatManager.isAutoConvertible(posExt)) {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
return;
|
||||
@ -115,7 +136,7 @@ if (typeof jQuery !== "undefined") {
|
||||
contentType: "application/json",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({filename: fileName, filePass: filePass}),
|
||||
data: JSON.stringify({filename: fileName, filePass: filePass, fileExt: fileType}),
|
||||
url: UrlConverter,
|
||||
complete: function (data) {
|
||||
var responseText = data.responseText;
|
||||
@ -131,6 +152,12 @@ if (typeof jQuery !== "undefined") {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (response.error.includes("Error conversion output format")){
|
||||
jq("#select-file-type").removeClass("invisible");
|
||||
jq("#step2").removeClass("current");
|
||||
jq("#hiddenFileName").attr("placeholder",filePass);
|
||||
return;
|
||||
}
|
||||
jq(".current").removeClass("current");
|
||||
jq(".step:not(.done)").addClass("error");
|
||||
jq("#mainProgress .error-message").show().find("span").text(response.error);
|
||||
@ -142,7 +169,7 @@ if (typeof jQuery !== "undefined") {
|
||||
jq("#hiddenFileName").val(response.filename);
|
||||
|
||||
if (response.step && response.step < 100) {
|
||||
checkConvert(filePass);
|
||||
checkConvert(filePass, fileType);
|
||||
} else {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
@ -180,7 +207,7 @@ if (typeof jQuery !== "undefined") {
|
||||
var posExt = fileName.lastIndexOf(".") + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : "";
|
||||
|
||||
if (EditedExtList.includes(posExt) !== -1 || FillExtList.includes(posExt) !== -1) {
|
||||
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
@ -218,6 +245,15 @@ if (typeof jQuery !== "undefined") {
|
||||
}
|
||||
};
|
||||
|
||||
jq(document).on("click", ".file-type:not(.disable)", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileType = currentElement.attr("data");
|
||||
var filePass = jq("#hiddenFileName").attr("placeholder");
|
||||
jq('.file-type').addClass(["disable", "pale"]);
|
||||
currentElement.removeClass("pale");
|
||||
checkConvert(filePass, fileType);
|
||||
});
|
||||
|
||||
jq(document).on("click", "#enterPass", function () {
|
||||
var pass = jq("#filePass").val();
|
||||
if (pass) {
|
||||
@ -299,6 +335,24 @@ if (typeof jQuery !== "undefined") {
|
||||
});
|
||||
});
|
||||
|
||||
jq(document).on("click", ".clear-all", function () {
|
||||
if (confirm("Delete all the files?")) {
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "application/json",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({filename: null, filePass: null}),
|
||||
url: "/delete",
|
||||
complete: function (data) {
|
||||
if (JSON.parse(data.responseText).success) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showUserTooltip (isMobile) {
|
||||
if ( jq("div#portal-info").is(":hidden") ) {
|
||||
jq("div#portal-info").show();
|
||||
|
||||
@ -262,7 +262,44 @@
|
||||
innerAlert(response.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestUsers = function (event) {
|
||||
if (event && event.data) {
|
||||
var c = event.data.c;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = [[${usersInfo}]];
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = [[${usersForProtect}]];
|
||||
break;
|
||||
default:
|
||||
users = [[${usersForMentions}]];
|
||||
}
|
||||
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestSendNotify = function(event) { // the user is mentioned in a comment
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
@ -275,59 +312,26 @@
|
||||
"onMetaChange": onMetaChange,
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestSelectDocument": onRequestSelectDocument,
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
|
||||
"onRequestRestore": onRequestRestore,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet
|
||||
};
|
||||
|
||||
var usersForMentions = [[${usersForMentions}]];
|
||||
var usersInfo = [[${usersInfo}]];
|
||||
var usersForProtect = [[${usersForProtect}]];
|
||||
|
||||
|
||||
if (config.editorConfig.user.id != 4) {
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = usersInfo;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = usersForProtect;
|
||||
break;
|
||||
default:
|
||||
users = usersForMentions;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
config.events['onRequestUsers'] = onRequestUsers;
|
||||
// the user is mentioned in a comment
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
config.events['onRequestSendNotify'] = onRequestSendNotify;
|
||||
// prevent file renaming for anonymous users
|
||||
config.events['onRequestRename'] = onRequestRename;
|
||||
config.events['onRequestReferenceData'] = onRequestReferenceData;
|
||||
// prevent switch the document from the viewing into the editing mode for anonymous users
|
||||
config.events['onRequestEditRights'] = onRequestEditRights;
|
||||
config.events['onRequestOpen'] = onRequestOpen;
|
||||
config.events['onRequestHistory'] = onRequestHistory;
|
||||
config.events['onRequestHistoryData'] = onRequestHistoryData;
|
||||
if (config.editorConfig.user.id != 3) {
|
||||
config.events['onRequestHistoryClose'] = onRequestHistoryClose;
|
||||
config.events['onRequestRestore'] = onRequestRestore;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.editorConfig.createUrl) {
|
||||
@ -335,12 +339,6 @@
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -123,7 +123,14 @@
|
||||
</div>
|
||||
<th:block th:if="${not #lists.isEmpty(files)}">
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -275,6 +282,15 @@
|
||||
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
|
||||
<span id="step1" class="step">1. Loading the file.</span>
|
||||
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
|
||||
<div id="select-file-type" class="invisible">
|
||||
<br />
|
||||
<span class="step">Please select the current document type</span>
|
||||
<div class="buttonsMobile indent">
|
||||
<div class="button file-type document" data="docx">Document</div>
|
||||
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
|
||||
<div class="button file-type presentation" data="pptx">Presentation</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<span id="step2" class="step">2. Conversion.</span>
|
||||
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
|
||||
@ -341,6 +357,7 @@
|
||||
<script type="text/javascript" src="scripts/jquery.iframe-transport.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery.fileupload.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery.dropdownToggle.js"></script>
|
||||
<script type="text/javascript" src="scripts/formats.js"></script>
|
||||
<script type="text/javascript" src="scripts/jscript.js"></script>
|
||||
<script type="text/javascript" src="scripts/converter.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
@ -78,10 +78,10 @@ public class EditorServlet extends HttpServlet {
|
||||
|
||||
// an image that will be inserted into the document
|
||||
Map<String, Object> dataInsertImage = new HashMap<>();
|
||||
dataInsertImage.put("fileType", "png");
|
||||
dataInsertImage.put("url", DocumentManager.getServerUrl(true) + "/css/img/logo.png");
|
||||
dataInsertImage.put("fileType", "svg");
|
||||
dataInsertImage.put("url", DocumentManager.getServerUrl(true) + "/css/img/logo.svg");
|
||||
if (isEnableDirectUrl) {
|
||||
dataInsertImage.put("directUrl", DocumentManager.getServerUrl(false) + "/css/img/logo.png");
|
||||
dataInsertImage.put("directUrl", DocumentManager.getServerUrl(false) + "/css/img/logo.svg");
|
||||
}
|
||||
|
||||
// a document that will be compared with the current document
|
||||
|
||||
@ -29,6 +29,7 @@ import helpers.FileUtility;
|
||||
import helpers.ServiceConverter;
|
||||
import helpers.TrackManager;
|
||||
import helpers.Users;
|
||||
import format.FormatManager;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
@ -139,6 +140,9 @@ public class IndexServlet extends HttpServlet {
|
||||
case "historydata":
|
||||
historyData(request, response, writer);
|
||||
break;
|
||||
case "formats":
|
||||
formats(request, response, writer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -283,7 +287,8 @@ public class IndexServlet extends HttpServlet {
|
||||
String fileUri = DocumentManager.getDownloadUrl(fileName, true);
|
||||
String fileExt = FileUtility.getFileExtension(fileName);
|
||||
FileType fileType = FileUtility.getFileType(fileName);
|
||||
String internalFileExt = "ooxml";
|
||||
// get an auto-conversion extension from the request body or set it to the ooxml extension
|
||||
String conversionExtension = body.get("fileExt") != null ? (String) body.get("fileExt") : "ooxml";
|
||||
|
||||
// check if the file with such an extension can be converted
|
||||
if (DocumentManager.getConvertExts().contains(fileExt)) {
|
||||
@ -292,7 +297,7 @@ public class IndexServlet extends HttpServlet {
|
||||
|
||||
// get the url and file type to the converted file
|
||||
Map<String, String> newFileData = ServiceConverter
|
||||
.getConvertedData(fileUri, fileExt, internalFileExt, key, filePass, true, lang);
|
||||
.getConvertedData(fileUri, fileExt, conversionExtension, key, filePass, true, lang);
|
||||
String newFileUri = newFileData.get("fileUrl");
|
||||
String newFileType = "." + newFileData.get("fileType");
|
||||
|
||||
@ -416,17 +421,23 @@ public class IndexServlet extends HttpServlet {
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
try {
|
||||
String fileName = FileUtility.getFileName(request.getParameter("filename"));
|
||||
String path = DocumentManager.storagePath(fileName, null);
|
||||
String fileName = request.getParameter("filename");
|
||||
if (fileName != null && !fileName.isEmpty()) {
|
||||
fileName = FileUtility.getFileName(fileName);
|
||||
String path = DocumentManager.storagePath(fileName, null);
|
||||
|
||||
// delete file
|
||||
File f = new File(path);
|
||||
delete(f);
|
||||
|
||||
// delete file history
|
||||
File hist = new File(DocumentManager.historyDir(path));
|
||||
delete(hist);
|
||||
// delete file
|
||||
File f = new File(path);
|
||||
delete(f);
|
||||
|
||||
// delete file history
|
||||
File hist = new File(DocumentManager.historyDir(path));
|
||||
delete(hist);
|
||||
} else {
|
||||
// delete the user's folder and all the containing files
|
||||
File userFolder = new File(DocumentManager.storagePath(null, null));
|
||||
delete(userFolder);
|
||||
}
|
||||
writer.write("{ \"success\": true }");
|
||||
} catch (Exception e) {
|
||||
writer.write("{ \"error\": \"" + e.getMessage() + "\"}");
|
||||
@ -1039,6 +1050,16 @@ public class IndexServlet extends HttpServlet {
|
||||
writer.write("{}");
|
||||
}
|
||||
|
||||
private static void formats(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("formats", (new FormatManager()).getFormats());
|
||||
response.setContentType("application/json");
|
||||
Gson gson = new Gson();
|
||||
writer.write(gson.toJson(data));
|
||||
}
|
||||
|
||||
// process get request
|
||||
@Override
|
||||
protected void doGet(final HttpServletRequest request,
|
||||
|
||||
@ -114,9 +114,15 @@ public class FileModel {
|
||||
editorConfig.getUser().setImage(user.getAvatar() ? DocumentManager.getServerUrl(false)
|
||||
+ "/css/img/" + user.getId() + ".png" : null);
|
||||
|
||||
// write the absolute URL to the file location
|
||||
editorConfig.getCustomization().getGoback()
|
||||
if (user.getGoback() != null) {
|
||||
// write the absolute URL to the file location
|
||||
editorConfig.getCustomization().getGoback()
|
||||
.setUrl(DocumentManager.getServerUrl(false) + "/IndexServlet");
|
||||
editorConfig.getCustomization().getGoback()
|
||||
.setText(user.getGoback().getText());
|
||||
editorConfig.getCustomization().getGoback()
|
||||
.setBlank(user.getGoback().getBlank());
|
||||
}
|
||||
|
||||
changeType(mode, type, user, fileName);
|
||||
}
|
||||
@ -601,6 +607,8 @@ public class FileModel {
|
||||
|
||||
public class Goback {
|
||||
private String url;
|
||||
private String text;
|
||||
private Boolean blank;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
@ -609,6 +617,22 @@ public class FileModel {
|
||||
public void setUrl(final String urlParam) {
|
||||
this.url = urlParam;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(final String textParam) {
|
||||
this.text = textParam;
|
||||
}
|
||||
|
||||
public Boolean getBlank() {
|
||||
return blank;
|
||||
}
|
||||
|
||||
public void setBlank(final Boolean blankParam) {
|
||||
this.blank = blankParam;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package entities;
|
||||
|
||||
public class Goback {
|
||||
private String text;
|
||||
private Boolean blank;
|
||||
|
||||
public Goback() { }
|
||||
|
||||
public Goback(final String textParam, final Boolean blankParam) {
|
||||
this.text = textParam;
|
||||
this.blank = blankParam;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public Boolean getBlank() {
|
||||
return blank;
|
||||
}
|
||||
}
|
||||
@ -33,12 +33,13 @@ public class User {
|
||||
private final Boolean templates;
|
||||
private final List<String> userInfoGroups;
|
||||
private final Boolean avatar;
|
||||
private final Goback goback;
|
||||
|
||||
public User(final String idParam, final String nameParam, final String emailParam, final String groupParam,
|
||||
final List<String> reviewGroupsParam, final CommentGroups commentGroupsParam,
|
||||
final List<String> userInfoGroupsParam, final Boolean favoriteParam,
|
||||
final List<String> deniedPermissionsParam, final List<String> descriptionsParam,
|
||||
final Boolean templatesParam, final Boolean avatarParam) {
|
||||
final Boolean templatesParam, final Boolean avatarParam, final Goback gobackParam) {
|
||||
this.id = idParam;
|
||||
this.name = nameParam;
|
||||
this.email = emailParam;
|
||||
@ -51,6 +52,7 @@ public class User {
|
||||
this.templates = templatesParam;
|
||||
this.userInfoGroups = userInfoGroupsParam;
|
||||
this.avatar = avatarParam;
|
||||
this.goback = gobackParam;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
@ -100,4 +102,8 @@ public class User {
|
||||
public Boolean getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public Goback getGoback() {
|
||||
return goback;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
package helpers;
|
||||
|
||||
import entities.CommentGroups;
|
||||
import entities.Goback;
|
||||
import entities.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -64,6 +65,8 @@ public final class Users {
|
||||
add("Can create new files from the editor");
|
||||
add("Can see the information about Group2 users");
|
||||
add("Can’t submit forms");
|
||||
add("Can't close history");
|
||||
add("Can't restore the file version");
|
||||
}};
|
||||
|
||||
private static List<String> descriptionUserZero = new ArrayList<String>() {{
|
||||
@ -85,19 +88,20 @@ public final class Users {
|
||||
private static List<User> users = new ArrayList<User>() {{
|
||||
add(new User("uid-1", "John Smith", "smith@example.com",
|
||||
"", null, new CommentGroups(), null,
|
||||
null, new ArrayList<String>(), descriptionUserFirst, true, true));
|
||||
null, new ArrayList<String>(), descriptionUserFirst, true, true, new Goback(null, false)));
|
||||
add(new User("uid-2", "Mark Pottato", "pottato@example.com",
|
||||
"group-2", Arrays.asList("group-2", ""), new CommentGroups(null,
|
||||
Arrays.asList("group-2", ""), Arrays.asList("group-2")), Arrays.asList("group-2", ""),
|
||||
true, new ArrayList<String>(), descriptionUserSecond, false, true));
|
||||
true, new ArrayList<String>(), descriptionUserSecond, false, true,
|
||||
new Goback("Go to Documents", null)));
|
||||
add(new User("uid-3", "Hamish Mitchell", null,
|
||||
"group-3", Arrays.asList("group-2"), new CommentGroups(Arrays.asList("group-3", "group-2"),
|
||||
Arrays.asList("group-2"), null), Arrays.asList("group-2"),
|
||||
false, Arrays.asList("copy", "download", "print"),
|
||||
descriptionUserThird, false, false));
|
||||
descriptionUserThird, false, false, null));
|
||||
add(new User("uid-0", null, null,
|
||||
"", null, null, null,
|
||||
null, Arrays.asList("protect"), descriptionUserZero, false, false));
|
||||
null, Arrays.asList("protect"), descriptionUserZero, false, false, null));
|
||||
}};
|
||||
|
||||
private Users() { }
|
||||
|
||||
@ -27,7 +27,8 @@ public enum ConvertErrorType {
|
||||
UNEXPECTED_GUID_ERROR(-5, "Error unexpected guid"),
|
||||
DATABASE_ERROR(-6, "Error database"),
|
||||
DOCUMENT_REQUEST_ERROR(-7, "Error document request"),
|
||||
DOCUMENT_VKEY_ERROR(-8, "Error document VKey");
|
||||
DOCUMENT_VKEY_ERROR(-8, "Error document VKey"),
|
||||
CONVERSION_OUTPUT_FORMAT_ERROR(-9, "Error conversion output format");
|
||||
|
||||
private final int code;
|
||||
private final String label;
|
||||
|
||||
@ -13,7 +13,7 @@ files.docservice.url.api=web-apps/apps/api/documents/api.js
|
||||
files.docservice.url.preloader=web-apps/apps/api/documents/cache-scripts.html
|
||||
files.docservice.url.example=
|
||||
|
||||
files.docservice.languages=en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-CS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
|
||||
files.docservice.languages=en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
|
||||
|
||||
files.docservice.secret=
|
||||
files.docservice.header=Authorization
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@ -488,6 +488,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -230,6 +230,33 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -595,6 +622,29 @@ footer table tr td:first-child {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -748,6 +798,16 @@ html {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
|
||||
@ -262,6 +262,43 @@
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
var onRequestUsers = function (event) {
|
||||
if (event && event.data) {
|
||||
var c = event.data.c;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%=(String) request.getAttribute("usersInfo")%>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%=(String) request.getAttribute("usersForProtect")%>;
|
||||
break;
|
||||
default:
|
||||
users = <%=(String) request.getAttribute("usersForMentions")%>;
|
||||
}
|
||||
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestSendNotify = function(event) { // the user is mentioned in a comment
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
|
||||
config = JSON.parse('<%= FileModel.serialize(Model) %>');
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
@ -274,61 +311,26 @@
|
||||
"onMetaChange": onMetaChange,
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestSelectDocument": onRequestSelectDocument,
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
|
||||
"onRequestRestore": onRequestRestore,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet
|
||||
};
|
||||
|
||||
<%
|
||||
String usersForMentions = (String) request.getAttribute("usersForMentions");
|
||||
String usersInfo = (String) request.getAttribute("usersInfo");
|
||||
String usersForProtect = (String) request.getAttribute("usersForProtect");
|
||||
%>
|
||||
|
||||
if (config.editorConfig.user.id) {
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function (event) {
|
||||
if (event && event.data){
|
||||
var c = event.data.c;
|
||||
}
|
||||
switch (c) {
|
||||
case "info":
|
||||
users = [];
|
||||
var allUsers = <%=usersInfo%>;
|
||||
for (var i = 0; i < event.data.id.length; i++) {
|
||||
for (var j = 0; j < allUsers.length; j++) {
|
||||
if (allUsers[j].id == event.data.id[i]) {
|
||||
users.push(allUsers[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "protect":
|
||||
var users = <%=usersForProtect%>;
|
||||
break;
|
||||
default:
|
||||
users = <%=usersForMentions%>;
|
||||
}
|
||||
docEditor.setUsers({
|
||||
"c": c,
|
||||
"users": users,
|
||||
});
|
||||
};
|
||||
config.events['onRequestUsers'] = onRequestUsers;
|
||||
// the user is mentioned in a comment
|
||||
config.events['onRequestSendNotify'] = function (event) {
|
||||
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
|
||||
var data = JSON.stringify(event.data);
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
config.events['onRequestSendNotify'] = onRequestSendNotify;
|
||||
// prevent file renaming for anonymous users
|
||||
config.events['onRequestRename'] = onRequestRename;
|
||||
config.events['onRequestReferenceData'] = onRequestReferenceData;
|
||||
// prevent switch the document from the viewing into the editing mode for anonymous users
|
||||
config.events['onRequestEditRights'] = onRequestEditRights;
|
||||
config.events['onRequestOpen'] = onRequestOpen;
|
||||
config.events['onRequestHistory'] = onRequestHistory;
|
||||
config.events['onRequestHistoryData'] = onRequestHistoryData;
|
||||
if (config.editorConfig.user.id != "uid-3") {
|
||||
config.events['onRequestHistoryClose'] = onRequestHistoryClose;
|
||||
config.events['onRequestRestore'] = onRequestRestore;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.editorConfig.createUrl) {
|
||||
@ -336,12 +338,6 @@
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -146,7 +146,14 @@
|
||||
</div>
|
||||
<% if (files.length > 0) { %>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -299,6 +306,15 @@
|
||||
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
|
||||
<span id="step1" class="step">1. Loading the file.</span>
|
||||
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
|
||||
<div id="select-file-type" class="invisible">
|
||||
<br />
|
||||
<span class="step">Please select the current document type</span>
|
||||
<div class="buttonsMobile indent">
|
||||
<div class="button file-type document" data="docx">Document</div>
|
||||
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
|
||||
<div class="button file-type presentation" data="pptx">Presentation</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<span id="step2" class="step">2. Conversion.</span>
|
||||
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
|
||||
@ -365,12 +381,10 @@
|
||||
<script type="text/javascript" src="scripts/jquery.iframe-transport.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery.fileupload.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery.dropdownToggle.js"></script>
|
||||
<script type="text/javascript" src="scripts/formats.js"></script>
|
||||
<script type="text/javascript" src="scripts/jscript.js"></script>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
var FillExtList = "<%= String.join(",", DocumentManager.getFillExts()) %>".split(",");
|
||||
var ConverExtList = "<%= String.join(",", DocumentManager.getConvertExts()) %>".split(",");
|
||||
var EditedExtList = "<%= String.join(",", DocumentManager.getEditedExts()) %>".split(",");
|
||||
var UrlConverter = "IndexServlet?type=convert";
|
||||
var UrlEditor = "EditorServlet";
|
||||
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class Format {
|
||||
constructor(name, type, actions, convert, mime) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.actions = actions;
|
||||
this.convert = convert;
|
||||
this.mime = mime;
|
||||
}
|
||||
|
||||
isAutoConvertible() {
|
||||
return this.actions.includes('auto-convert');
|
||||
}
|
||||
|
||||
isEditable() {
|
||||
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
|
||||
}
|
||||
|
||||
isFillable() {
|
||||
return this.actions.includes('fill');
|
||||
}
|
||||
}
|
||||
|
||||
class FormatManager {
|
||||
formats = [];
|
||||
|
||||
constructor(formats) {
|
||||
if(Array.isArray(formats)) this.formats = formats;
|
||||
}
|
||||
|
||||
findByExtension(extension) {
|
||||
return this.formats.find(format => format.name == extension);
|
||||
}
|
||||
|
||||
isAutoConvertible(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isAutoConvertible();
|
||||
}
|
||||
|
||||
isEditable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isEditable();
|
||||
}
|
||||
|
||||
isFillable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isFillable();
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,27 @@
|
||||
*/
|
||||
|
||||
var directUrl;
|
||||
var formatManager;
|
||||
|
||||
window.onload = function () {
|
||||
fetch('IndexServlet?type=formats')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.formats) {
|
||||
let formats = [];
|
||||
data.formats.forEach(format => {
|
||||
formats.push(new Format(
|
||||
format.name,
|
||||
format.type,
|
||||
format.actions,
|
||||
format.convert,
|
||||
format.mime
|
||||
));
|
||||
});
|
||||
formatManager = new FormatManager(formats);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof jQuery !== "undefined") {
|
||||
jq = jQuery.noConflict();
|
||||
@ -87,7 +108,7 @@ if (typeof jQuery !== "undefined") {
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
var checkConvert = function (filePass) {
|
||||
var checkConvert = function (filePass, fileType) {
|
||||
filePass = filePass ? filePass : null;
|
||||
if (timer !== null) {
|
||||
clearTimeout(timer);
|
||||
@ -103,7 +124,7 @@ if (typeof jQuery !== "undefined") {
|
||||
var posExt = fileName.lastIndexOf(".") + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : "";
|
||||
|
||||
if (!ConverExtList.includes(posExt)) {
|
||||
if (!formatManager.isAutoConvertible(posExt)) {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
return;
|
||||
@ -115,7 +136,7 @@ if (typeof jQuery !== "undefined") {
|
||||
contentType: "text/xml",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({filename: fileName, filePass: filePass}),
|
||||
data: JSON.stringify({filename: fileName, filePass: filePass, fileExt: fileType}),
|
||||
url: UrlConverter,
|
||||
complete: function (data) {
|
||||
var responseText = data.responseText;
|
||||
@ -131,6 +152,12 @@ if (typeof jQuery !== "undefined") {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (response.error.includes("Error conversion output format")){
|
||||
jq("#select-file-type").removeClass("invisible");
|
||||
jq("#step2").removeClass("current");
|
||||
jq("#hiddenFileName").attr("placeholder",filePass);
|
||||
return;
|
||||
}
|
||||
jq(".current").removeClass("current");
|
||||
jq(".step:not(.done)").addClass("error");
|
||||
jq("#mainProgress .error-message").show().find("span").text(response.error);
|
||||
@ -142,7 +169,7 @@ if (typeof jQuery !== "undefined") {
|
||||
jq("#hiddenFileName").val(response.filename);
|
||||
|
||||
if (response.step && response.step < 100) {
|
||||
checkConvert(filePass);
|
||||
checkConvert(filePass, fileType);
|
||||
} else {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
@ -180,7 +207,7 @@ if (typeof jQuery !== "undefined") {
|
||||
var posExt = fileName.lastIndexOf(".") + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : "";
|
||||
|
||||
if (EditedExtList.includes(posExt) || FillExtList.includes(posExt)) {
|
||||
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
@ -212,6 +239,15 @@ if (typeof jQuery !== "undefined") {
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", ".file-type:not(.disable)", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileType = currentElement.attr("data");
|
||||
var filePass = jq("#hiddenFileName").attr("placeholder");
|
||||
jq('.file-type').addClass(["disable", "pale"]);
|
||||
currentElement.removeClass("pale");
|
||||
checkConvert(filePass, fileType);
|
||||
});
|
||||
|
||||
jq(document).on("click", "#enterPass", function () {
|
||||
var pass = jq("#filePass").val();
|
||||
if (pass) {
|
||||
@ -290,6 +326,21 @@ if (typeof jQuery !== "undefined") {
|
||||
});
|
||||
});
|
||||
|
||||
jq(document).on("click", ".clear-all", function () {
|
||||
if (confirm("Delete all the files?")) {
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: "IndexServlet?type=remove",
|
||||
complete: function (data) {
|
||||
if (JSON.parse(data.responseText).success) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showUserTooltip (isMobile) {
|
||||
if ( jq("div#portal-info").is(":hidden") ) {
|
||||
jq("div#portal-info").show();
|
||||
|
||||
@ -93,8 +93,6 @@ app.get('/', (req, res) => { // define a handler for default page
|
||||
|
||||
res.render('index', { // render index template with the parameters specified
|
||||
preloaderUrl: siteUrl + configServer.get('preloaderUrl'),
|
||||
convertExts: fileUtility.getConvertExtensions(),
|
||||
editedExts: fileUtility.getEditExtensions(),
|
||||
fillExts: fileUtility.getFillExtensions(),
|
||||
storedFiles: req.DocManager.getStoredFiles(),
|
||||
params: req.DocManager.getCustomParams(),
|
||||
@ -333,6 +331,8 @@ app.post('/convert', (req, res) => { // define a handler for converting files
|
||||
const fileUri = req.DocManager.getDownloadUrl(fileName, true);
|
||||
const fileExt = fileUtility.getFileExtension(fileName, true);
|
||||
const internalFileExt = 'ooxml';
|
||||
const convExt = req.body.fileExt ? req.body.fileExt : internalFileExt;
|
||||
const { keepOriginal } = req.body;
|
||||
const response = res;
|
||||
|
||||
const writeResult = function writeResult(filename, step, error) {
|
||||
@ -380,38 +380,50 @@ app.post('/convert', (req, res) => { // define a handler for converting files
|
||||
if (status !== 200) throw new Error(`Conversion service returned status: ${status}`);
|
||||
|
||||
// write a file with a new extension, but with the content from the origin file
|
||||
fileSystem.writeFileSync(req.DocManager.storagePath(correctName), data);
|
||||
fileSystem.unlinkSync(req.DocManager.storagePath(fileName)); // remove file with the origin extension
|
||||
if (fileUtility.getFileType(correctName) !== null) {
|
||||
fileSystem.writeFileSync(req.DocManager.storagePath(correctName), data);
|
||||
} else {
|
||||
writeResult(newFileUri, result, 'FileTypeIsNotSupported');
|
||||
return;
|
||||
}
|
||||
// remove file with the origin extension
|
||||
if (!keepOriginal) fileSystem.unlinkSync(req.DocManager.storagePath(fileName));
|
||||
|
||||
const userAddress = req.DocManager.curUserHostAddress();
|
||||
const historyPath = req.DocManager.historyPath(fileName, userAddress, true);
|
||||
// get the history path to the file with a new extension
|
||||
const correctHistoryPath = req.DocManager.historyPath(correctName, userAddress, true);
|
||||
|
||||
fileSystem.renameSync(historyPath, correctHistoryPath); // change the previous history path
|
||||
if (!keepOriginal) {
|
||||
fileSystem.renameSync(historyPath, correctHistoryPath); // change the previous history path
|
||||
|
||||
fileSystem.renameSync(
|
||||
path.join(correctHistoryPath, `${fileName}.txt`),
|
||||
path.join(correctHistoryPath, `${correctName}.txt`),
|
||||
); // change the name of the .txt file with document information
|
||||
fileSystem.renameSync(
|
||||
path.join(correctHistoryPath, `${fileName}.txt`),
|
||||
path.join(correctHistoryPath, `${correctName}.txt`),
|
||||
); // change the name of the .txt file with document information
|
||||
} else if (newFileType !== null) {
|
||||
const user = users.getUser(req.query.userid);
|
||||
|
||||
req.DocManager.saveFileData(correctName, user.id, user.name);
|
||||
}
|
||||
|
||||
writeResult(correctName, result, null); // write a file with a new name to the result object
|
||||
} catch (e) {
|
||||
console.log(e); // display error message in the console
|
||||
if (!e.message.includes('-9')) console.log(e); // display error message in the console
|
||||
writeResult(null, null, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
// check if the file with such an extension can be converted
|
||||
if (fileUtility.getConvertExtensions().indexOf(fileExt) !== -1) {
|
||||
if ((fileUtility.getConvertExtensions().indexOf(fileExt) !== -1) || ('fileExt' in req.body)) {
|
||||
const storagePath = req.DocManager.storagePath(fileName);
|
||||
const stat = fileSystem.statSync(storagePath);
|
||||
let key = fileUri + stat.mtime.getTime();
|
||||
|
||||
key = documentService.generateRevisionId(key); // get document key
|
||||
// get the url to the converted file
|
||||
documentService.getConvertedUri(fileUri, fileExt, internalFileExt, key, true, callback, filePass, lang);
|
||||
documentService.getConvertedUri(fileUri, fileExt, convExt, key, true, callback, filePass, lang);
|
||||
} else {
|
||||
// if the file with such an extension can't be converted, write the origin file to the result object
|
||||
writeResult(fileName, null, null);
|
||||
@ -643,7 +655,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
const zip = await urllib.request(downloadZip, { method: 'GET' });
|
||||
const statusZip = zip.status;
|
||||
const dataZip = zip.data;
|
||||
if (status === 200) {
|
||||
if (statusZip === 200) {
|
||||
fileSystem.writeFileSync(pathChanges, dataZip); // write the document version differences to the archive
|
||||
} else {
|
||||
emitWarning(`Document editing service returned status: ${statusZip}`);
|
||||
@ -674,7 +686,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
response.write('{"error":1}');
|
||||
response.write(`{"error":1,"message":${JSON.stringify(ex)}}`);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
@ -686,7 +698,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
// file saving process
|
||||
const processSave = async function processSave(downloadUri, body, fileName, userAddress) {
|
||||
if (!downloadUri) {
|
||||
response.write('{"error":1}');
|
||||
response.write('{"error":1,"message":"save uri is empty"}');
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
@ -797,7 +809,8 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
response.write('{"error":1}');
|
||||
console.log(ex);
|
||||
response.write(`{"error":1,"message":${JSON.stringify(ex)}}`);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
@ -809,7 +822,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
// file force saving process
|
||||
const processForceSave = async function processForceSave(downloadUri, body, fileName, userAddress) {
|
||||
if (!downloadUri) {
|
||||
response.write('{"error":1}');
|
||||
response.write('{"error":1,"message":"forcesave uri is empty"}');
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
@ -901,7 +914,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
}
|
||||
}
|
||||
if (!body) {
|
||||
res.write('{"error":1}');
|
||||
res.write('{"error":1,"message":"body is empty"}');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
@ -920,15 +933,27 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
try {
|
||||
req.DocManager = new DocManager(req, res);
|
||||
|
||||
const fileName = fileUtility.getFileName(req.query.fileName);
|
||||
let { fileExt } = req.query;
|
||||
const lang = req.DocManager.getLang();
|
||||
const user = users.getUser(req.query.userid);
|
||||
const userDirectUrl = req.query.directUrl === 'true';
|
||||
|
||||
const userid = user.id;
|
||||
const { name } = user;
|
||||
|
||||
if (fileExt) {
|
||||
fileExt = fileUtility.getFileExtension(fileUtility.getFileName(fileExt), true);
|
||||
// create demo document of a given extension
|
||||
const fName = req.DocManager.createDemo(!!req.query.sample, fileExt, userid, name, false);
|
||||
|
||||
// get the redirect path
|
||||
const redirectPath = `${req.DocManager.getServerUrl()}/editor?fileName=`
|
||||
+ `${encodeURIComponent(fName)}${req.DocManager.getCustomParams()}`;
|
||||
res.redirect(redirectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileName = fileUtility.getFileName(req.query.fileName);
|
||||
const lang = req.DocManager.getLang();
|
||||
const userDirectUrl = req.query.directUrl === 'true';
|
||||
|
||||
let actionData = 'null';
|
||||
if (req.query.action) {
|
||||
try {
|
||||
@ -970,25 +995,21 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
const { userInfoGroups } = user;
|
||||
|
||||
const usersInfo = [];
|
||||
const usersForProtect = [];
|
||||
if (user.id !== 'uid-0') {
|
||||
users.getAllUsers().forEach((userInfo) => {
|
||||
const u = userInfo;
|
||||
u.image = userInfo.avatar ? `${req.DocManager.getServerUrl()}/images/${userInfo.id}.png` : null;
|
||||
usersInfo.push(u);
|
||||
}, usersInfo);
|
||||
|
||||
users.getUsersForProtect(user.id).forEach((userInfo) => {
|
||||
const u = userInfo;
|
||||
u.image = userInfo.avatar ? `${req.DocManager.getServerUrl()}/images/${userInfo.id}.png` : null;
|
||||
usersForProtect.push(u);
|
||||
}, usersForProtect);
|
||||
}
|
||||
|
||||
if (fileExt) {
|
||||
fileExt = fileUtility.getFileExtension(fileUtility.getFileName(fileExt), true);
|
||||
// create demo document of a given extension
|
||||
const fName = req.DocManager.createDemo(!!req.query.sample, fileExt, userid, name, false);
|
||||
|
||||
// get the redirect path
|
||||
const redirectPath = `${req.DocManager.getServerUrl()}/editor?fileName=`
|
||||
+ `${encodeURIComponent(fName)}${req.DocManager.getCustomParams()}`;
|
||||
res.redirect(redirectPath);
|
||||
return;
|
||||
}
|
||||
fileExt = fileUtility.getFileExtension(fileName);
|
||||
|
||||
const userAddress = req.DocManager.curUserHostAddress();
|
||||
@ -1016,6 +1037,10 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
submitForm = userid === 'uid-1';
|
||||
}
|
||||
|
||||
if (user.goback != null) {
|
||||
user.goback.url = `${req.DocManager.getServerUrl()}`;
|
||||
}
|
||||
|
||||
// file config data
|
||||
const argss = {
|
||||
apiUrl: siteUrl + configServer.get('apiUrl'),
|
||||
@ -1049,7 +1074,6 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
print: !user.deniedPermissions.includes('print'),
|
||||
mode: mode !== 'view' ? 'edit' : 'view',
|
||||
canBackToFolder: type !== 'embedded',
|
||||
backUrl: `${req.DocManager.getServerUrl()}/`,
|
||||
curUserHostAddress: req.DocManager.curUserHostAddress(),
|
||||
lang,
|
||||
userid: userid !== 'uid-0' ? userid : null,
|
||||
@ -1067,12 +1091,13 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
? JSON.stringify({ fileName, userAddress: req.DocManager.curUserHostAddress() }) : null,
|
||||
instanceId: userid !== 'uid-0' ? req.DocManager.getInstanceId() : null,
|
||||
protect: !user.deniedPermissions.includes('protect'),
|
||||
goback: user.goback != null ? user.goback : '',
|
||||
close: user.close,
|
||||
},
|
||||
dataInsertImage: {
|
||||
fileType: 'png',
|
||||
url: `${req.DocManager.getServerUrl(true)}/images/logo.png`,
|
||||
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/images/logo.png`,
|
||||
fileType: 'svg',
|
||||
url: `${req.DocManager.getServerUrl(true)}/images/logo.svg`,
|
||||
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/images/logo.svg`,
|
||||
},
|
||||
dataDocument: {
|
||||
fileType: 'docx',
|
||||
@ -1087,7 +1112,7 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/csv`,
|
||||
},
|
||||
usersForMentions: user.id !== 'uid-0' ? users.getUsersForMentions(user.id) : null,
|
||||
usersForProtect: user.id !== 'uid-0' ? users.getUsersForProtect(user.id) : null,
|
||||
usersForProtect,
|
||||
usersInfo,
|
||||
};
|
||||
|
||||
@ -1171,6 +1196,19 @@ app.post('/historyObj', (req, res) => {
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.get('/formats', (req, res) => {
|
||||
try {
|
||||
const formats = fileUtility.getFormats();
|
||||
res.json({
|
||||
formats,
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex); // display error message in the console
|
||||
res.status(500); // write status parameter to the response
|
||||
res.render('error', { message: 'Server error' }); // render error template with the message parameter specified
|
||||
}
|
||||
});
|
||||
|
||||
wopiApp.registerRoutes(app);
|
||||
|
||||
// "Not found" error with 404 status
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
"pt-PT": "Portuguese (Portugal)",
|
||||
"ro": "Romanian",
|
||||
"ru": "Russian",
|
||||
"sr-Latn-CS": "Serbian",
|
||||
"sr-Latn-RS": "Serbian",
|
||||
"si": "Sinhala (Sri Lanka)",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
|
||||
@ -51,7 +51,7 @@ DocManager.prototype.createDirectory = function createDirectory(directory) {
|
||||
|
||||
// get the language from the request
|
||||
DocManager.prototype.getLang = function getLang() {
|
||||
if (/^[a-z]{2}(-[A-z]{4})?(-[A-Z]{2})?$/.test(this.req.query.lang)) {
|
||||
if (/^[a-z]{2}(-[a-zA-z]{4})?(-[A-Z]{2})?$/.test(this.req.query.lang)) {
|
||||
return this.req.query.lang;
|
||||
} // the default language value is English
|
||||
return 'en';
|
||||
|
||||
@ -20,6 +20,10 @@ const supportedFormats = require('../public/assets/document-formats/onlyoffice-d
|
||||
|
||||
const fileUtility = {};
|
||||
|
||||
fileUtility.getFormats = function getFormats() {
|
||||
return supportedFormats;
|
||||
};
|
||||
|
||||
// get file name from the given url
|
||||
fileUtility.getFileName = function getFileName(url, withoutExtension) {
|
||||
if (!url) return '';
|
||||
@ -54,10 +58,10 @@ fileUtility.getFileType = function getFileType(url) {
|
||||
const ext = fileUtility.getFileExtension(url, true); // get the file extension from the given url
|
||||
|
||||
for (let i = 0; i < supportedFormats.length; i++) {
|
||||
if (supportedFormats[i].name === ext) return supportedFormats[i].type;
|
||||
if (supportedFormats[i].name === ext && supportedFormats[i].type !== '') return supportedFormats[i].type;
|
||||
}
|
||||
|
||||
return fileUtility.fileType.word; // the default file type is word
|
||||
return null; // the default file type is null
|
||||
};
|
||||
|
||||
fileUtility.fileType = {
|
||||
|
||||
@ -30,6 +30,7 @@ class User {
|
||||
descriptions,
|
||||
templates,
|
||||
avatar,
|
||||
goback,
|
||||
close,
|
||||
) {
|
||||
this.id = id;
|
||||
@ -44,6 +45,7 @@ class User {
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
this.avatar = avatar;
|
||||
this.goback = goback;
|
||||
this.close = close;
|
||||
}
|
||||
}
|
||||
@ -82,6 +84,8 @@ const descrUser3 = [
|
||||
'Can create new files from the editor',
|
||||
'Can see the information about Group2 users',
|
||||
'Can’t submit forms',
|
||||
'Can’t close history',
|
||||
'Can’t restore the file version',
|
||||
];
|
||||
|
||||
const descrUser0 = [
|
||||
@ -114,6 +118,7 @@ const users = [
|
||||
descrUser1,
|
||||
true,
|
||||
true,
|
||||
{ blank: false },
|
||||
{ visible: false },
|
||||
),
|
||||
new User(
|
||||
@ -133,6 +138,7 @@ const users = [
|
||||
descrUser2,
|
||||
false,
|
||||
true,
|
||||
{ text: 'Go to Documents' },
|
||||
{},
|
||||
),
|
||||
new User(
|
||||
@ -152,9 +158,10 @@ const users = [
|
||||
descrUser3,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
{},
|
||||
),
|
||||
new User('uid-0', null, null, null, null, {}, [], null, ['protect'], descrUser0, false, false, null),
|
||||
new User('uid-0', null, null, null, null, {}, [], null, ['protect'], descrUser0, false, false, null, null),
|
||||
];
|
||||
|
||||
// get a list of all the users
|
||||
@ -192,10 +199,7 @@ users.getUsersForProtect = function getUsersForProtect(id) {
|
||||
const result = [];
|
||||
this.forEach((user) => {
|
||||
if (user.id !== id && user.name != null) {
|
||||
result.push({
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
});
|
||||
result.push(user);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
|
||||
@ -187,13 +187,12 @@ const putFile = function putFile(wopi, req, res, userHost) {
|
||||
|
||||
const userAddress = req.DocManager.curUserHostAddress(userHost);
|
||||
const storagePath = req.DocManager.storagePath(wopi.id, userAddress);
|
||||
const fileSize = fileSystem.statSync(storagePath).size;
|
||||
|
||||
if (!lockManager.hasLock(storagePath)) {
|
||||
// ToDo: if body length is 0 bytes => handle document creation
|
||||
|
||||
if (!lockManager.hasLock(storagePath) && fileSize !== 0) {
|
||||
// file isn't locked => mismatch
|
||||
returnLockMismatch(res, '', 'File isn\'t locked');
|
||||
} else if (lockManager.getLock(storagePath) === requestLock) {
|
||||
} else if (lockManager.getLock(storagePath) === requestLock || fileSize === 0) {
|
||||
// lock matches current lock => put file
|
||||
saveFileFromBody(req, wopi.id, userAddress, true, (err, version) => {
|
||||
if (!err) {
|
||||
|
||||
@ -27,57 +27,72 @@ const siteUrl = configServer.get('siteUrl'); // the path to the editors installa
|
||||
|
||||
let cache = null;
|
||||
|
||||
const requestDiscovery = async function requestDiscovery(url) {
|
||||
const requestDiscovery = async function requestDiscovery(DocManager) {
|
||||
let absSiteUrl = siteUrl;
|
||||
if (absSiteUrl.indexOf('/') === 0) {
|
||||
absSiteUrl = DocManager.getServerHost() + siteUrl;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return new Promise((resolve, reject) => {
|
||||
const uri = absSiteUrl + configServer.get('wopi.discovery');
|
||||
const actions = [];
|
||||
urllib.request(urlModule.parse(url + configServer.get('wopi.discovery')), { method: 'GET' }, (err, data) => {
|
||||
if (data) {
|
||||
// create the discovery XML file with the parameters from the response
|
||||
const xmlParseOptions = {
|
||||
attributeNamePrefix: '',
|
||||
ignoreAttributes: false,
|
||||
parseAttributeValue: true,
|
||||
attrValueProcessor: (val) => he.decode(val, { isAttributeValue: true }),
|
||||
};
|
||||
const parser = new xmlParser.XMLParser(xmlParseOptions);
|
||||
// create the discovery XML file with the parameters from the response
|
||||
const discovery = parser.parse(data.toString());
|
||||
if (discovery['wopi-discovery']) {
|
||||
discovery['wopi-discovery']['net-zone'].app.forEach((app) => {
|
||||
let appAction = app.action;
|
||||
if (!Array.isArray(appAction)) {
|
||||
appAction = [appAction];
|
||||
}
|
||||
appAction.forEach((action) => {
|
||||
actions.push({ // write all the parameters to the actions element
|
||||
app: app.name,
|
||||
favIconUrl: app.favIconUrl,
|
||||
checkLicense: app.checkLicense === 'true',
|
||||
name: action.name,
|
||||
ext: action.ext || '',
|
||||
progid: action.progid || '',
|
||||
isDefault: !!action.default,
|
||||
urlsrc: action.urlsrc,
|
||||
requires: action.requires || '',
|
||||
|
||||
// parse url to allow request by relative url after
|
||||
// https://github.com/node-modules/urllib/pull/321/commits/514de1924bf17a38a6c2db2a22a6bc3494c0a959
|
||||
urllib.request(
|
||||
urlModule.parse(uri),
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
(err, data) => {
|
||||
if (data) {
|
||||
// create the discovery XML file with the parameters from the response
|
||||
const xmlParseOptions = {
|
||||
attributeNamePrefix: '',
|
||||
ignoreAttributes: false,
|
||||
parseAttributeValue: true,
|
||||
attrValueProcessor: (val) => he.decode(val, { isAttributeValue: true }),
|
||||
};
|
||||
const parser = new xmlParser.XMLParser(xmlParseOptions);
|
||||
// create the discovery XML file with the parameters from the response
|
||||
const discovery = parser.parse(data.toString());
|
||||
if (discovery['wopi-discovery']) {
|
||||
discovery['wopi-discovery']['net-zone'].app.forEach((app) => {
|
||||
let appAction = app.action;
|
||||
if (!Array.isArray(appAction)) {
|
||||
appAction = [appAction];
|
||||
}
|
||||
appAction.forEach((action) => {
|
||||
actions.push({ // write all the parameters to the actions element
|
||||
app: app.name,
|
||||
favIconUrl: app.favIconUrl,
|
||||
checkLicense: app.checkLicense === 'true',
|
||||
name: action.name,
|
||||
ext: action.ext || '',
|
||||
progid: action.progid || '',
|
||||
isDefault: !!action.default,
|
||||
urlsrc: action.urlsrc,
|
||||
requires: action.requires || '',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
resolve(actions);
|
||||
});
|
||||
resolve(actions);
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// get the wopi discovery information
|
||||
const getDiscoveryInfo = async function getDiscoveryInfo(url) {
|
||||
const getDiscoveryInfo = async function getDiscoveryInfo(DocManager) {
|
||||
let actions = [];
|
||||
|
||||
if (cache) return cache;
|
||||
|
||||
try {
|
||||
actions = await requestDiscovery(url);
|
||||
actions = await requestDiscovery(DocManager);
|
||||
} catch (e) {
|
||||
return actions;
|
||||
}
|
||||
@ -91,19 +106,9 @@ const getDiscoveryInfo = async function getDiscoveryInfo(url) {
|
||||
return actions;
|
||||
};
|
||||
|
||||
const initWopi = async function initWopi(DocManager) {
|
||||
let absSiteUrl = siteUrl;
|
||||
if (absSiteUrl.indexOf('/') === 0) {
|
||||
absSiteUrl = DocManager.getServerHost() + siteUrl;
|
||||
}
|
||||
|
||||
// get the wopi discovery information
|
||||
await getDiscoveryInfo(absSiteUrl);
|
||||
};
|
||||
|
||||
// get actions of the specified extension
|
||||
const getActions = async function getActions(ext) {
|
||||
const actions = await getDiscoveryInfo(); // get the wopi discovery information
|
||||
const getActions = async function getActions(DocManager, ext) {
|
||||
const actions = await getDiscoveryInfo(DocManager); // get the wopi discovery information
|
||||
const filtered = [];
|
||||
|
||||
actions.forEach((action) => { // and filter it by the specified extention
|
||||
@ -116,8 +121,8 @@ const getActions = async function getActions(ext) {
|
||||
};
|
||||
|
||||
// get an action for the specified extension and name
|
||||
const getAction = async function getAction(ext, name) {
|
||||
const actions = await getDiscoveryInfo();
|
||||
const getAction = async function getAction(DocManager, ext, name) {
|
||||
const actions = await getDiscoveryInfo(DocManager);
|
||||
let act = null;
|
||||
|
||||
actions.forEach((action) => {
|
||||
@ -130,8 +135,8 @@ const getAction = async function getAction(ext, name) {
|
||||
};
|
||||
|
||||
// get the default action for the specified extension
|
||||
const getDefaultAction = async function getDefaultAction(ext) {
|
||||
const actions = await getDiscoveryInfo();
|
||||
const getDefaultAction = async function getDefaultAction(DocManager, ext) {
|
||||
const actions = await getDiscoveryInfo(DocManager);
|
||||
let act = null;
|
||||
|
||||
actions.forEach((action) => {
|
||||
@ -149,7 +154,6 @@ const getActionUrl = function getActionUrl(host, userAddress, action, filename)
|
||||
return `${action.urlsrc.replace(/<.*&>/g, '')}WOPISrc=${encodeURIComponent(WOPISrc)}`;
|
||||
};
|
||||
|
||||
exports.initWopi = initWopi;
|
||||
exports.getDiscoveryInfo = getDiscoveryInfo;
|
||||
exports.getAction = getAction;
|
||||
exports.getActions = getActions;
|
||||
|
||||
@ -45,15 +45,13 @@ exports.registerRoutes = function registerRoutes(app) {
|
||||
app.get('/wopi', async (req, res) => {
|
||||
req.DocManager = new DocManager(req, res);
|
||||
|
||||
await utils.initWopi(req.DocManager);
|
||||
|
||||
// get the wopi discovery information
|
||||
const actions = await utils.getDiscoveryInfo();
|
||||
const actions = await utils.getDiscoveryInfo(req.DocManager);
|
||||
const wopiEnable = actions.length !== 0;
|
||||
const docsExtEdit = []; // Supported extensions for WOPI
|
||||
|
||||
actions.forEach((el) => {
|
||||
if (el.name === 'edit') docsExtEdit.push(`.${el.ext}`);
|
||||
if (el.name === 'edit') docsExtEdit.push(`${el.ext}`);
|
||||
});
|
||||
|
||||
// Checking supported extensions
|
||||
@ -67,11 +65,13 @@ exports.registerRoutes = function registerRoutes(app) {
|
||||
// run through all the files and write the corresponding information to each file
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const file of files) {
|
||||
const mobile = new RegExp(configServer.get('mobileRegEx'), 'i').test(req.get('User-Agent'));
|
||||
const ext = fileUtility.getFileExtension(file.name, true); // get an extension of each file
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
file.actions = await utils.getActions(ext); // get actions of the specified extension
|
||||
file.actions = await utils.getActions(req.DocManager, ext); // get actions of the specified extension
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
file.defaultAction = await utils.getDefaultAction(ext);// get the default action of the specified extension
|
||||
file.defaultAction = await utils.getDefaultAction(req.DocManager, ext);// get the default action for extension
|
||||
if (mobile) file.actions.forEach((act) => { if (act.name === 'mobileEdit') file.defaultAction = act; });
|
||||
}
|
||||
|
||||
// render wopiIndex template with the parameters specified
|
||||
@ -111,14 +111,12 @@ exports.registerRoutes = function registerRoutes(app) {
|
||||
try {
|
||||
req.DocManager = new DocManager(req, res);
|
||||
|
||||
await utils.initWopi(req.DocManager);
|
||||
|
||||
let fileName = req.DocManager.getCorrectName(req.params.id);
|
||||
const fileExt = fileUtility.getFileExtension(fileName, true); // get the file extension from the request
|
||||
const user = users.getUser(req.query.userid); // get a user by the id
|
||||
|
||||
// get an action for the specified extension and name
|
||||
const action = await utils.getAction(fileExt, req.query.action);
|
||||
const action = await utils.getAction(req.DocManager, fileExt, req.query.action);
|
||||
|
||||
if (action && req.query.action === 'editnew') {
|
||||
fileName = req.DocManager.requestEditnew(req, fileName, user);
|
||||
|
||||
@ -17,17 +17,17 @@
|
||||
"url": "https://github.com/ONLYOFFICE/document-server-integration/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"config": "^3.3.2",
|
||||
"debug": "^4.2.0",
|
||||
"ejs": "^3.1.5",
|
||||
"express": "^4.17.1",
|
||||
"fast-xml-parser": "^4.3.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"config": "^3.3.11",
|
||||
"debug": "^4.3.4",
|
||||
"ejs": "^3.1.9",
|
||||
"express": "^4.18.2",
|
||||
"fast-xml-parser": "^4.3.4",
|
||||
"formidable": "^1.2.2",
|
||||
"he": "^1.2.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwa": "^2.0.0",
|
||||
"log4js": "^6.3.0",
|
||||
"log4js": "^6.9.1",
|
||||
"mime": "^2.4.6",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"urllib": "^2.36.1"
|
||||
@ -44,8 +44,16 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.28.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.26.0"
|
||||
"eslint-plugin-import": "^2.29.1"
|
||||
},
|
||||
"overrides": {
|
||||
"semver": "7.5.2",
|
||||
"word-wrap": "1.2.4",
|
||||
"pac-resolver": "7.0.0",
|
||||
"degenerator": "3.0.1",
|
||||
"qs": "6.7.3",
|
||||
"json5": "2.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4285 13C14.4102 13 14 13 14 13.5V15H6C5.44772 15 5 15.4477 5 16V17C5 17.5523 5.44771 18 6 18H14V19.5C14 20 14.3816 20 14.4285 20C14.6359 20 15.0099 19.9113 15.2172 19.7363L18.6207 17.0833C19.1264 16.6566 19.1264 16.3434 18.6207 15.9167L15.2172 13.2637C15.0099 13.0887 14.6359 13 14.4285 13Z" fill="#444444"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.5715 4C9.58984 4 10 4 10 4.50002V6H18C18.5523 6 19 6.44772 19 7V8C19 8.55228 18.5523 9 18 9H10V10.5C10 11 9.61841 11 9.57151 11C9.36409 11 8.99012 10.9113 8.78279 10.7363L5.37934 8.08333C4.87356 7.65662 4.87356 7.34338 5.37934 6.91667L8.78279 4.26366C8.99012 4.08874 9.36409 4 9.5715 4Z" fill="#444444"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 821 B |
3
web/documentserver-example/nodejs/public/images/home.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 17V11H12V17H17V9H20L10 0L0 9H3V17H8Z" fill="#444444"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
class Format {
|
||||
constructor(name, type, actions, convert, mime) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.actions = actions;
|
||||
this.convert = convert;
|
||||
this.mime = mime;
|
||||
}
|
||||
|
||||
isAutoConvertible() {
|
||||
return this.actions.includes('auto-convert');
|
||||
}
|
||||
|
||||
isEditable() {
|
||||
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
|
||||
}
|
||||
|
||||
isFillable() {
|
||||
return this.actions.includes('fill');
|
||||
}
|
||||
}
|
||||
|
||||
class FormatManager {
|
||||
formats = [];
|
||||
|
||||
constructor(formats) {
|
||||
if(Array.isArray(formats)) this.formats = formats;
|
||||
}
|
||||
|
||||
findByExtension(extension) {
|
||||
return this.formats.find(format => format.name == extension);
|
||||
}
|
||||
|
||||
isAutoConvertible(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isAutoConvertible();
|
||||
}
|
||||
|
||||
isEditable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isEditable();
|
||||
}
|
||||
|
||||
isFillable(extension) {
|
||||
let format = this.findByExtension(extension);
|
||||
return format !== undefined && format.isFillable();
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,27 @@
|
||||
var language;
|
||||
var userid;
|
||||
var directUrl;
|
||||
var formatManager;
|
||||
|
||||
window.onload = function () {
|
||||
fetch('formats')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.formats) {
|
||||
let formats = [];
|
||||
data.formats.forEach(format => {
|
||||
formats.push(new Format(
|
||||
format.name,
|
||||
format.type,
|
||||
format.actions,
|
||||
format.convert,
|
||||
format.mime
|
||||
));
|
||||
});
|
||||
formatManager = new FormatManager(formats);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof jQuery != "undefined") {
|
||||
jq = jQuery.noConflict();
|
||||
@ -100,7 +121,7 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
var checkConvert = function (filePass) {
|
||||
var checkConvert = function (filePass, fileType) {
|
||||
filePass = filePass ? filePass : null;
|
||||
if (timer != null) {
|
||||
clearTimeout(timer);
|
||||
@ -116,7 +137,7 @@ if (typeof jQuery != "undefined") {
|
||||
var posExt = fileName.lastIndexOf('.') + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (ConverExtList.indexOf(posExt) == -1) {
|
||||
if (!formatManager.isAutoConvertible(posExt)) {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
return;
|
||||
@ -128,7 +149,7 @@ if (typeof jQuery != "undefined") {
|
||||
async: true,
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: {filename: fileName, filePass: filePass, lang: language},
|
||||
data: {filename: fileName, filePass: filePass, lang: language, fileExt: fileType},
|
||||
url: UrlConverter,
|
||||
complete: function (data) {
|
||||
var responseText = data.responseText;
|
||||
@ -148,6 +169,12 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (response.error.includes("-9")){
|
||||
jq("#select-file-type").removeClass("invisible");
|
||||
jq("#step2").removeClass("current");
|
||||
jq("#hiddenFileName").attr("placeholder",filePass);
|
||||
return;
|
||||
}
|
||||
jq(".current").removeClass("current");
|
||||
jq(".step:not(.done)").addClass("error");
|
||||
jq("#mainProgress .error-message").show().find("span").text(response.error);
|
||||
@ -159,7 +186,7 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#hiddenFileName").val(response.filename);
|
||||
|
||||
if (typeof response.step != "undefined" && response.step < 100) {
|
||||
checkConvert(filePass);
|
||||
checkConvert(filePass, fileType);
|
||||
} else {
|
||||
jq("#step2").addClass("done").removeClass("current");
|
||||
loadScripts();
|
||||
@ -197,14 +224,20 @@ if (typeof jQuery != "undefined") {
|
||||
var posExt = fileName.lastIndexOf('.') + 1;
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
var checkEdited = EditedExtList.split(",").filter(function(ext) { return ext == posExt;});
|
||||
var checkFilled = FilledExtList.split(",").filter(function(ext) { return ext == posExt;});
|
||||
|
||||
if (checkEdited != "" || checkFilled != "") {
|
||||
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
|
||||
jq(document).on("click", ".file-type:not(.disable)", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileType = currentElement.attr("data");
|
||||
var filePass = jq("#hiddenFileName").attr("placeholder");
|
||||
jq(".file-type").addClass(["disable", "pale"]);
|
||||
currentElement.removeClass("pale");
|
||||
checkConvert(filePass, fileType);
|
||||
});
|
||||
|
||||
jq(document).on("click", "#enterPass", function () {
|
||||
var pass = jq("#filePass").val();
|
||||
if (pass) {
|
||||
@ -272,6 +305,38 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#uploadSteps").after('<iframe id="embeddedView" src="' + url + '" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>');
|
||||
});
|
||||
|
||||
jq(document).on("click", "#beginEditConverted:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').attr("data"));
|
||||
if (UrlEditor == "wopi-action"){
|
||||
var url = UrlEditor + "/" + fileId + "?action=edit" + collectParams(true);
|
||||
}else{
|
||||
var url = UrlEditor + "?fileName=" + fileId + collectParams(true);
|
||||
}
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
window.location = collectParams();
|
||||
});
|
||||
|
||||
jq(document).on("click", "#beginViewConverted:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').attr("data"));
|
||||
if (UrlEditor == "wopi-action"){
|
||||
var url = UrlEditor + "/" + fileId + "?action=view" + collectParams(true);
|
||||
}else{
|
||||
var url = UrlEditor + "?mode=view&fileName=" + fileId + collectParams(true);
|
||||
}
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
window.location = collectParams();
|
||||
});
|
||||
|
||||
jq(document).on("click", "#downloadConverted:not(.disable)", function () {
|
||||
var fileId = jq('#hiddenFileName').attr("data");
|
||||
if (jq("#downloadConverted").attr("data") == "fromConverter") window.location.assign(fileId);
|
||||
else window.location.href = "download?fileName=" + encodeURIComponent(fileId);
|
||||
});
|
||||
|
||||
jq(document).on("click", ".reload-page", function () {
|
||||
setTimeout(function () { window.location = collectParams(); }, 1000);
|
||||
return true;
|
||||
@ -293,6 +358,101 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
});
|
||||
|
||||
jq(document).on("click", ".convert-file", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileName = currentElement.attr("data");
|
||||
var type = currentElement.attr("data-type");
|
||||
|
||||
jq.blockUI({
|
||||
theme: true,
|
||||
title: "Converting file" + "<div class=\"dialog-close\"></div>",
|
||||
message: jq("#convertingProgress"),
|
||||
overlayCSS: { "background-color": "#aaa" },
|
||||
themedCSS: { width: "539px", top: "20%", left: "50%", marginLeft: "-269px" }
|
||||
});
|
||||
|
||||
jq("#convertFileName").text(decodeURIComponent(fileName));
|
||||
jq("#convertFileName").removeClass("word slide cell");
|
||||
jq("#convertFileName").addClass(type);
|
||||
jq("#convTypes").empty();
|
||||
|
||||
let format = formatManager.findByExtension(fileName.split('.').pop());
|
||||
if (format) {
|
||||
format.convert.forEach(ext => {
|
||||
jq("#convTypes").append(jq(`<td name="convertingTypeButton" id="wordTo${ext}" class="button hoar" data="${ext}">${ext}</td>`));
|
||||
});
|
||||
}
|
||||
|
||||
jq("#hiddenFileName").val(fileName);
|
||||
jq("#convertStep1").addClass("done");
|
||||
jq("#convertStep2").addClass("waiting");
|
||||
});
|
||||
|
||||
jq(document).on("click", "td[name='convertingTypeButton']:not(.disable, .orange)", function () {
|
||||
const currentElement = jq(this);
|
||||
let id = currentElement[0].id;
|
||||
let fileExt = jq(`#${id}`).attr("data");
|
||||
jq(`#${id}`).addClass("orange");
|
||||
jq("td[name='convertingTypeButton']").addClass("disable");
|
||||
jq("#convertStep2").removeClass("waiting").removeClass("done").addClass("current");
|
||||
jq("#convertStep2").text('2. File conversion');
|
||||
jq("#convert-descr").removeClass("disable");
|
||||
jq("#convertPercent").text("0 %");
|
||||
jq("#hiddenFileName").attr("placeholder",fileExt);
|
||||
jq("#downloadConverted").addClass("disable");
|
||||
jq("#beginEditConverted").addClass("disable");
|
||||
jq("#beginViewConverted").addClass("disable");
|
||||
mustReload = true;
|
||||
|
||||
convertFile();
|
||||
});
|
||||
|
||||
function convertFile (filePass) {
|
||||
let fileName = decodeURIComponent(jq("#hiddenFileName").val());
|
||||
let fileExt = jq("#hiddenFileName").attr("placeholder");
|
||||
|
||||
if (timer != null) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(function () {
|
||||
jq.ajaxSetup({ cache: false });
|
||||
jq.ajax({
|
||||
async: true,
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: {filename: fileName, filePass: filePass, lang: language, fileExt: fileExt, keepOriginal: true},
|
||||
url: UrlConverter,
|
||||
complete: function (data) {
|
||||
try {
|
||||
var response = jq.parseJSON(data.responseText);
|
||||
} catch (e) {
|
||||
response = { error: e };
|
||||
}
|
||||
if(response.step !==100) {
|
||||
jq("#convertPercent").text(`${response.step} %`);
|
||||
convertFile();
|
||||
} else {
|
||||
jq("#convertPercent").text(`${response.step} %`);
|
||||
jq("#convertStep2").removeClass("current").addClass("done");
|
||||
jq("#convertStep2").text(`2. File conversion to ${fileExt}`);
|
||||
jq("#downloadConverted").removeClass("disable");
|
||||
if (response.error !== "FileTypeIsNotSupported") {
|
||||
jq("#hiddenFileName").attr("data",response.filename);
|
||||
jq("#beginEditConverted").removeClass("disable");
|
||||
jq("#beginViewConverted").removeClass("disable");
|
||||
jq("#downloadConverted").attr("data","fromStorage");
|
||||
} else {
|
||||
let newFilename = fileName.split('.').slice(0,-1).join('.')
|
||||
jq("#hiddenFileName").attr("data",response.filename.split("&filename=download").join(`&filename=${newFilename}`));
|
||||
jq("#downloadConverted").attr("data","fromConverter");
|
||||
}
|
||||
jq("td[name='convertingTypeButton']").removeClass("disable orange");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
jq(document).on("click", ".delete-file", function () {
|
||||
const currentElement = jq(this);
|
||||
var fileName = currentElement.attr("data");
|
||||
@ -319,6 +479,22 @@ if (typeof jQuery != "undefined") {
|
||||
});
|
||||
});
|
||||
|
||||
jq(document).on("click", ".clear-all", function () {
|
||||
if (confirm("Delete all the files?")) {
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
type: "delete",
|
||||
url: "file",
|
||||
complete: function (data) {
|
||||
if (JSON.parse(data.responseText).success) {
|
||||
window.location = collectParams();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jq("#createSample").click(function () {
|
||||
jq(".try-editor").each(function () {
|
||||
var href = jq(this).attr("href");
|
||||
|
||||
@ -33,6 +33,15 @@
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.tableHeaderCellFileName{
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
@media (max-width: 1280px) and (min-width: 1080px) {
|
||||
.tableHeaderCellViewers {
|
||||
width: 24%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.tableHeaderCellRemove{
|
||||
@ -40,6 +49,7 @@
|
||||
text-align: center;
|
||||
}
|
||||
.tableHeaderCellDownload{
|
||||
width: 13%;
|
||||
padding-right: 11px;
|
||||
}
|
||||
.tableHeaderCellViewers{
|
||||
@ -58,6 +68,9 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 45%;
|
||||
}
|
||||
.tableHeaderCellViewers {
|
||||
width: 23%;
|
||||
}
|
||||
}
|
||||
@media (max-width: 986px) and (min-width: 890px){
|
||||
.tableHeaderCellRemove{
|
||||
@ -68,12 +81,15 @@
|
||||
padding-right: 0;
|
||||
}
|
||||
.tableHeaderCellViewers{
|
||||
width: 24%;
|
||||
width: 22%;
|
||||
padding-right: 0;
|
||||
}
|
||||
.tableRow td:first-child {
|
||||
max-width: 40%;
|
||||
}
|
||||
.contentCells-wopi {
|
||||
padding-right: 114px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 890px) and (min-width: 769px){
|
||||
.tableRow td:first-child{
|
||||
@ -85,6 +101,9 @@
|
||||
.contentCells-wopi{
|
||||
width: unset;
|
||||
}
|
||||
.tableHeaderCellRemove {
|
||||
width: 5%;
|
||||
}
|
||||
}
|
||||
@media (max-width: 769px) {
|
||||
.tableRow td{
|
||||
@ -112,7 +131,7 @@
|
||||
}
|
||||
@media (max-width: 769px) and (min-width: 320px){
|
||||
.contentCells-icon {
|
||||
width: 1%;
|
||||
width: 9%;
|
||||
}
|
||||
}
|
||||
@media (max-width: 508px) {
|
||||
|
||||
@ -42,10 +42,14 @@
|
||||
}
|
||||
|
||||
.tableHeaderCellViewers {
|
||||
width: 29%;
|
||||
width: 18%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tableHeaderCellAction {
|
||||
width: 23%;
|
||||
}
|
||||
|
||||
.tableHeaderCellDownload {
|
||||
width: 21%;
|
||||
padding-right: 18px;
|
||||
@ -79,7 +83,9 @@
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
@ -102,6 +108,10 @@
|
||||
.tableHeaderCellRemove {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1008px) {
|
||||
@ -119,7 +129,8 @@
|
||||
.contentCells-icon{
|
||||
width: 5%;
|
||||
}
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
menu.links {
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
@ -135,7 +146,7 @@
|
||||
}
|
||||
|
||||
.scroll-table-body {
|
||||
top: 31px;
|
||||
top: 33px;
|
||||
}
|
||||
|
||||
footer {
|
||||
@ -175,7 +186,9 @@
|
||||
}
|
||||
|
||||
@media (max-width: 715px) {
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 45%;
|
||||
}
|
||||
}
|
||||
@ -217,7 +230,7 @@
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
width: 16%;
|
||||
width: 9%;
|
||||
}
|
||||
|
||||
.tableHeaderCellEditors {
|
||||
@ -226,7 +239,12 @@
|
||||
|
||||
.tableHeaderCellViewers {
|
||||
text-align: right;
|
||||
width: 37%;
|
||||
width: 9%;
|
||||
}
|
||||
|
||||
.tableHeaderCellAction{
|
||||
width: 11%;
|
||||
padding-right: 82px;
|
||||
}
|
||||
|
||||
.tableHeaderCellDownload {
|
||||
@ -241,19 +259,24 @@
|
||||
}
|
||||
|
||||
.tableHeaderCellEditors {
|
||||
width: 26%;
|
||||
width: 15%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
width: 17%;
|
||||
width: 28%;
|
||||
}
|
||||
|
||||
.tableHeaderCellViewers {
|
||||
width: 27%;
|
||||
width: 6%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tableHeaderCellAction{
|
||||
width: 18%;
|
||||
padding-right: 54px;
|
||||
}
|
||||
|
||||
.tableHeaderCellDownload {
|
||||
padding-right: 18px;
|
||||
width: 20%;
|
||||
@ -263,7 +286,9 @@
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
@ -273,12 +298,21 @@
|
||||
|
||||
.tableRow td:first-child {
|
||||
flex-grow: 0;
|
||||
width: 15%;
|
||||
width: 25%;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
width: 3%;
|
||||
}
|
||||
|
||||
.firstContentCellViewers {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 890px) and (min-width: 769px ) {
|
||||
@ -286,14 +320,16 @@
|
||||
width: 20%;
|
||||
}
|
||||
.contentCells-shift {
|
||||
padding-right: 28px;
|
||||
padding-right: 27px;
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
@ -318,11 +354,20 @@
|
||||
|
||||
.tableHeaderCellEditors {
|
||||
text-align: left;
|
||||
width: 31%;
|
||||
width: 1%;
|
||||
}
|
||||
|
||||
.tableHeaderCellViewers {
|
||||
width: 18%;
|
||||
width: 19%;
|
||||
}
|
||||
|
||||
.tableHeaderCellAction {
|
||||
width: 19%;
|
||||
padding-right: 45px;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,6 +394,10 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -367,7 +416,7 @@
|
||||
}
|
||||
|
||||
.scroll-table-body {
|
||||
top: 31px;
|
||||
top: 33px;
|
||||
}
|
||||
|
||||
footer table tr {
|
||||
@ -407,7 +456,9 @@
|
||||
padding: 16px 0 6px;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
@ -423,8 +474,8 @@
|
||||
|
||||
.downloadContentCellShift {
|
||||
max-width: 7%;
|
||||
margin-right: -11px;
|
||||
margin-left: auto;
|
||||
margin-right: 24px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
@ -432,13 +483,13 @@
|
||||
}
|
||||
|
||||
.tableRow td:last-child {
|
||||
width: 12%;
|
||||
padding-right: 40px;
|
||||
width: 7%;
|
||||
padding-right: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.contentCells-shift {
|
||||
padding-right: 35px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.downloadContentCellShift:after {
|
||||
@ -502,6 +553,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
@ -513,6 +575,15 @@
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
.button.hoar{
|
||||
width: 18%;
|
||||
height: 27px;
|
||||
margin-bottom: 7px !important;
|
||||
}
|
||||
.button.converting{
|
||||
width: 126px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
@ -521,13 +592,15 @@
|
||||
}
|
||||
|
||||
.downloadContentCellShift {
|
||||
padding-right: 45px;
|
||||
padding-right: 16px;
|
||||
max-width: 4%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 510px) and (min-width: 470px) {
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
@ -540,7 +613,7 @@
|
||||
|
||||
.downloadContentCellShift {
|
||||
max-width: 6%;
|
||||
padding-right: 37px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.firstContentCellShift {
|
||||
@ -553,7 +626,9 @@
|
||||
}
|
||||
|
||||
@media (max-width: 470px) and (min-width: 420px) {
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 30%;
|
||||
}
|
||||
.tableRow td:first-child{
|
||||
@ -565,12 +640,12 @@
|
||||
|
||||
.downloadContentCellShift {
|
||||
max-width: 3%;
|
||||
padding-right: 37px;
|
||||
padding-right: 0px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.firstContentCellShift {
|
||||
margin-left: 1px;
|
||||
margin-left: 2px;
|
||||
flex-basis: 14%;
|
||||
}
|
||||
|
||||
@ -588,7 +663,9 @@
|
||||
}
|
||||
|
||||
@media (max-width: 420px) and (min-width: 320px) {
|
||||
.tableRow {
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
@ -599,7 +676,7 @@
|
||||
|
||||
.downloadContentCellShift {
|
||||
max-width: 4%;
|
||||
margin-right: -18px;
|
||||
margin-right: 18px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
@ -608,7 +685,7 @@
|
||||
}
|
||||
|
||||
.contentCells-icon{
|
||||
width: 10%;
|
||||
width: 12%;
|
||||
}
|
||||
footer table td {
|
||||
margin: 0;
|
||||
@ -624,6 +701,10 @@
|
||||
padding-right: 2px;
|
||||
width: 11%;
|
||||
}
|
||||
|
||||
.header-list {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1160px) {
|
||||
@ -638,7 +719,9 @@
|
||||
}
|
||||
}
|
||||
@media (max-width: 769px) and (min-width: 715px){
|
||||
.tableRow{
|
||||
.tableRow,
|
||||
.storedHeader,
|
||||
menu.links {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,6 +228,79 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.converting {
|
||||
margin-top: -20px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
|
||||
.button.converting.wide {
|
||||
padding: 16px 29px;
|
||||
}
|
||||
|
||||
.button.hoar {
|
||||
background: #EFEFEF;
|
||||
border: 1px solid #EFEFEF;
|
||||
margin-right: 7px;
|
||||
margin-bottom: 7px;
|
||||
width: 13%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.button.hoar.disable {
|
||||
opacity: 30%;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.hoar:not(.disable):hover {
|
||||
background: #FF6F3D;
|
||||
border: 1px solid #FF6F3D;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.button.hoar.orange {
|
||||
background: #FF6F3D;
|
||||
border: 1px solid #FF6F3D;
|
||||
color: #FFFFFF;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.hoar.orange.disable {
|
||||
background: #444444;
|
||||
border: 1px solid #444444;
|
||||
color: #FFFFFF;
|
||||
cursor: default;
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -258,24 +331,64 @@ label .checkbox {
|
||||
width: 192px;
|
||||
}
|
||||
|
||||
.create-panel,
|
||||
.links-panel {
|
||||
.create-panel {
|
||||
float: left;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
padding: 0;
|
||||
column-gap: 30px;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid #E2E2E2;
|
||||
margin: 0;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.links li {
|
||||
padding: 4px;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.links li.active {
|
||||
border-bottom: 2px solid #FF6F3D;
|
||||
}
|
||||
|
||||
.links li.active a {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.links li.active a img {
|
||||
filter: invert(55%) sepia(67%) saturate(2727%) hue-rotate(335deg) brightness(104%) contrast(101%);
|
||||
}
|
||||
|
||||
.links a {
|
||||
display: inline-block;
|
||||
padding: 2px 0;
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.home-link {
|
||||
height: 24px;
|
||||
padding: 0 2px 8px !important;
|
||||
}
|
||||
|
||||
.home-link a {
|
||||
padding: 0;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.upload-panel,
|
||||
.create-panel {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #D0D5DA;
|
||||
}
|
||||
|
||||
.links-panel-border {
|
||||
margin-top: 24px;
|
||||
width: 100%;
|
||||
border-top: 1px solid #D0D5DA;
|
||||
}
|
||||
|
||||
#mainProgress {
|
||||
color: #333333;
|
||||
display: none;
|
||||
@ -313,6 +426,32 @@ label .checkbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#convertingProgress {
|
||||
color: #333333;
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
margin: 30px 35px;
|
||||
}
|
||||
|
||||
#convertingProgress .convertFileName{
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 160%;
|
||||
overflow: hidden;
|
||||
padding-left: 28px;
|
||||
margin-bottom: 16px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#convertingProgress .describeUpload {
|
||||
line-height: 150%;
|
||||
letter-spacing: -0.02em;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: url(../images/error.svg) no-repeat scroll 4px 10px;
|
||||
color: #CB0000;
|
||||
@ -334,6 +473,10 @@ label .checkbox {
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
.waiting {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.current {
|
||||
background-image: url("../images/loader16.gif");
|
||||
}
|
||||
@ -346,6 +489,12 @@ label .checkbox {
|
||||
background-image: url("../images/notdone.svg");
|
||||
}
|
||||
|
||||
.convertPercent {
|
||||
color: #FF6F3D;
|
||||
font-weight: 700;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.step-descr {
|
||||
display: block;
|
||||
margin-left: 35px;
|
||||
@ -353,6 +502,10 @@ label .checkbox {
|
||||
line-height: 188%;
|
||||
}
|
||||
|
||||
.step-descr.disable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-descr {
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 150%;
|
||||
@ -455,16 +608,19 @@ footer table tr td:first-child {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.convertFileName.word,
|
||||
.stored-edit.word,
|
||||
.uploadFileName.word {
|
||||
background-image: url("../images/icon_docx.svg");
|
||||
}
|
||||
|
||||
.convertFileName.cell,
|
||||
.stored-edit.cell,
|
||||
.uploadFileName.cell {
|
||||
background-image: url("../images/icon_xlsx.svg");
|
||||
}
|
||||
|
||||
.convertFileName.slide,
|
||||
.stored-edit.slide,
|
||||
.uploadFileName.slide {
|
||||
background-image: url("../images/icon_pptx.svg");
|
||||
@ -526,6 +682,11 @@ footer table tr td:first-child {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.convertTable {
|
||||
margin-top: 10px;
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
background: transparent;
|
||||
-moz-transition: all 0.2s ease-in-out;
|
||||
@ -572,6 +733,12 @@ footer table tr td:first-child {
|
||||
width: 11%;
|
||||
}
|
||||
|
||||
.tableHeaderCellAction{
|
||||
width: 13%;
|
||||
text-align: right;
|
||||
padding-right: 88px;
|
||||
}
|
||||
|
||||
.tableHeaderCellDownload{
|
||||
width: 13%;
|
||||
text-align: right;
|
||||
@ -595,7 +762,7 @@ footer table tr td:first-child {
|
||||
}
|
||||
|
||||
.contentCells-shift {
|
||||
padding-right: 44px;
|
||||
padding-right: 43px;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
@ -613,6 +780,28 @@ footer table tr td:first-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -672,7 +861,7 @@ footer table tr td:first-child {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.icon-delete {
|
||||
.icon-action {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -688,7 +877,7 @@ footer table tr td:first-child {
|
||||
overflow-x: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 71px;
|
||||
top: 75px;
|
||||
scrollbar-color: #D0D5DA transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
@ -751,6 +940,14 @@ html {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.typeButtonsRow {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.tableRow td:first-child {
|
||||
display: flex;
|
||||
@ -759,11 +956,11 @@ html {
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
width: 30%;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.tableHeaderCellEditors {
|
||||
width: 28%;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.tableHeaderCellViewers {
|
||||
@ -789,3 +986,13 @@ html {
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
@ -42,9 +42,7 @@
|
||||
"close": <%- JSON.stringify(editor.close) %>,
|
||||
"feedback": true,
|
||||
"forcesave": false,
|
||||
"goback": {
|
||||
"url": "<%- editor.backUrl %>"
|
||||
},
|
||||
"goback": <%- JSON.stringify(editor.goback) %>,
|
||||
"submitForm": <%- editor.submitForm %>
|
||||
},
|
||||
"embedded": {
|
||||
|
||||
@ -354,9 +354,7 @@
|
||||
};
|
||||
|
||||
var onDocumentReady = function(){
|
||||
if (config.type === "mobile") {
|
||||
document.getElementsByTagName("iframe")[0].style.height = window.innerHeight + "px";
|
||||
}
|
||||
fixSize();
|
||||
};
|
||||
|
||||
config = {
|
||||
@ -381,13 +379,15 @@
|
||||
config.events.onRequestEditRights = onRequestEditRights;
|
||||
config.events.onRequestHistory = onRequestHistory;
|
||||
config.events.onRequestHistoryData = onRequestHistoryData;
|
||||
config.events.onRequestHistoryClose = onRequestHistoryClose;
|
||||
config.events.onRequestRestore = onRequestRestore;
|
||||
config.events.onRequestRename = onRequestRename;
|
||||
config.events.onRequestUsers = onRequestUsers;
|
||||
config.events.onRequestSendNotify = onRequestSendNotify;
|
||||
config.events.onRequestReferenceData = onRequestReferenceData;
|
||||
config.events.onRequestReferenceSource = onRequestReferenceSource;
|
||||
if (<%- JSON.stringify(editor.userid) %> != "uid-3") {
|
||||
config.events.onRequestHistoryClose = onRequestHistoryClose;
|
||||
config.events.onRequestRestore = onRequestRestore;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.editorConfig.createUrl) {
|
||||
@ -403,14 +403,21 @@
|
||||
}
|
||||
|
||||
var connectEditor = function () {
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
fixSize();
|
||||
};
|
||||
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
// get the editor sizes
|
||||
var fixSize = function () {
|
||||
if (config.type !== "mobile") {
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
var wrapEl = document.getElementsByTagName("iframe");
|
||||
if (wrapEl.length) {
|
||||
wrapEl[0].style.height = screen.availHeight + "px";
|
||||
window.scrollTo(0, -1);
|
||||
wrapEl[0].style.height = window.innerHeight + "px";
|
||||
}
|
||||
};
|
||||
|
||||
const getFileExt = function (fileName) {
|
||||
@ -422,8 +429,12 @@
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("load", connectEditor);
|
||||
window.addEventListener("resize", fixSize);
|
||||
window.addEventListener("orientationchange", fixSize);
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent("onload", connectEditor);
|
||||
window.attachEvent("onresize", fixSize);
|
||||
window.attachEvent("orientationchange", fixSize);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -106,15 +106,21 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="links-panel links-panel-border clearFix">
|
||||
<a href="wopi" class="">Go to WOPI page</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="section">
|
||||
<div class="main-panel">
|
||||
<menu class="links">
|
||||
<li class="home-link active" >
|
||||
<a href="./">
|
||||
<img src="images/home.svg" alt="Home"/>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="wopi">Wopi</a>
|
||||
</li>
|
||||
</menu>
|
||||
<div id="portal-info" style="display: <%= storedFiles.length > 0 ? "none" : "table-cell" %>">
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
@ -137,15 +143,21 @@
|
||||
<%if (storedFiles.length > 0)
|
||||
{%>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td class="tableHeaderCell tableHeaderCellEditors contentCells-shift">Editors</td>
|
||||
<td class="tableHeaderCell tableHeaderCellViewers">Viewers</td>
|
||||
<td class="tableHeaderCell tableHeaderCellDownload">Download</td>
|
||||
<td class="tableHeaderCell tableHeaderCellRemove">Remove</td>
|
||||
<td class="tableHeaderCell tableHeaderCellAction">Action</td>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
@ -230,13 +242,21 @@
|
||||
<a class="action-link" href="editor?type=embedded&mode=embedded&fileName=<%= encodeURIComponent(storedFiles[i].name) %>" target="_blank">
|
||||
<img src="images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode" /></a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift downloadContentCellShift">
|
||||
<% if (storedFiles[i].documentType != null ) {%>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a class="convert-file" data="<%= encodeURIComponent(storedFiles[i].name) %>" data-type="<%= storedFiles[i].documentType %>">
|
||||
<img class="icon-action" src="images/convert.svg" alt="Convert" title="Convert" /></a>
|
||||
</td>
|
||||
<% } else { %>
|
||||
<td class="contentCells contentCells-icon downloadContentCellShift"></td>
|
||||
<% } %>
|
||||
<td class="contentCells contentCells-icon downloadContentCellShift">
|
||||
<a href="download?fileName=<%= encodeURIComponent(storedFiles[i].name) %>">
|
||||
<img class="icon-download" src="images/download.svg" 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.svg" alt="Delete" title="Delete" /></a>
|
||||
<img class="icon-action" src="images/delete.svg" alt="Delete" title="Delete" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
@ -258,6 +278,15 @@
|
||||
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
|
||||
<span id="step1" class="step">1. Loading the file.</span>
|
||||
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
|
||||
<div id="select-file-type" class="invisible">
|
||||
<br />
|
||||
<span class="step">Please select the current document type</span>
|
||||
<div class="buttonsMobile indent">
|
||||
<div class="button file-type document" data="docx">Document</div>
|
||||
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
|
||||
<div class="button file-type presentation" data="pptx">Presentation</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<span id="step2" class="step">2. Conversion.</span>
|
||||
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
|
||||
@ -294,6 +323,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="convertingProgress">
|
||||
<div id="convertingSteps">
|
||||
<span id="convertFileName" class="convertFileName"></span>
|
||||
<span id="convertStep1" class="step">1. Select a format file to convert</span>
|
||||
<span class="step-descr">The converting speed depends on file size and additional elements it contains.</span>
|
||||
<table cellspacing="0" cellpadding="0" width="100%" class="convertTable">
|
||||
<tbody>
|
||||
<tr class="typeButtonsRow" id="convTypes"></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<span id="convertStep2" class="step">2. File conversion</span>
|
||||
<span class="step-descr disable" id="convert-descr">The file is converted <div class="convertPercent" id="convertPercent">0 %</div></span>
|
||||
<div class="describeUpload">Note the speed of all operations depends on your connection quality and server location.</div>
|
||||
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
|
||||
</div>
|
||||
<br />
|
||||
<div class="buttonsMobile">
|
||||
<div id="downloadConverted" class="button converting orange disable">DOWNLOAD</div>
|
||||
<div id="beginViewConverted" class="button converting wide gray disable">VIEW</div>
|
||||
<div id="beginEditConverted" class="button converting wide gray disable">EDIT</div>
|
||||
<div id="cancelEdit" class="button converting gray">CANCEL</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="loadScripts" data-docs="<%= preloaderUrl %>"></span>
|
||||
|
||||
<footer>
|
||||
@ -323,12 +377,10 @@
|
||||
<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/formats.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jscript.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ConverExtList = "<%= convertExts %>";
|
||||
var EditedExtList = "<%= editedExts %>";
|
||||
var FilledExtList = "<%= fillExts %>";
|
||||
var UrlConverter = "convert";
|
||||
var UrlEditor = "editor";
|
||||
</script>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
*
|
||||
-->
|
||||
<title>ONLYOFFICE Document Editors</title>
|
||||
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
<link href="../images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
@ -32,7 +32,7 @@
|
||||
overflow: hidden;
|
||||
-ms-content-zooming: none;
|
||||
}
|
||||
|
||||
|
||||
#office_frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -66,11 +66,33 @@
|
||||
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 allow-downloads allow-modals');
|
||||
office_frame.setAttribute('allow', 'autoplay camera microphone display-capture');
|
||||
frameholder.appendChild(office_frame);
|
||||
|
||||
document.getElementById('office_form').submit();
|
||||
|
||||
var _onMessage = function(msg) {
|
||||
var data = msg.data;
|
||||
if (Object.prototype.toString.apply(data) !== '[object String]' || !window.JSON) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cmd = JSON.parse(data);
|
||||
if (cmd) {
|
||||
if ( cmd.MessageId == 'App_LoadingStatus' ) {
|
||||
var fixSize = function() {
|
||||
document.getElementsByTagName("iframe")[0].style.height = window.innerHeight + "px";
|
||||
}
|
||||
|
||||
fixSize();
|
||||
window.addEventListener("orientationchange", fixSize);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', function (e) {
|
||||
_onMessage(e);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@ -98,14 +98,20 @@
|
||||
</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">
|
||||
<menu class="links">
|
||||
<li class="home-link" >
|
||||
<a href="./">
|
||||
<img src="images/home.svg" alt="Home"/>
|
||||
</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a href="wopi">Wopi</a>
|
||||
</li>
|
||||
</menu>
|
||||
<div id="portal-info" style="display: <%= storedFiles.length > 0 ? "none" : "table-cell" %>">
|
||||
<% if (!wopiEnable)
|
||||
{ %>
|
||||
@ -129,7 +135,14 @@
|
||||
<% if (storedFiles.length > 0)
|
||||
{ %>
|
||||
<div class="stored-list">
|
||||
<span class="header-list">Your documents</span>
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -172,7 +185,7 @@
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<a class="delete-file" data="<%= encodeURIComponent(storedFiles[i].name) %>">
|
||||
<img class="icon-delete" src="images/delete.svg" alt="Delete" title="Delete" /></a>
|
||||
<img class="icon-action" src="images/delete.svg" alt="Delete" title="Delete" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
@ -259,12 +272,10 @@
|
||||
<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/formats.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jscript.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ConverExtList = "<%= convertExts %>";
|
||||
var EditedExtList = "<%= editedExts %>";
|
||||
var FilledExtList = "<%= fillExts %>";
|
||||
var UrlConverter = "convert";
|
||||
var UrlEditor = "wopi-action";
|
||||
</script>
|
||||
|
||||
@ -61,6 +61,12 @@ compose-prod: # Up containers in a production environment.
|
||||
@docker-compose build
|
||||
@docker-compose up --detach
|
||||
|
||||
.PHONY: restart
|
||||
restart: # Restart containers replacing volume files.
|
||||
@docker-compose rm --stop --force proxy example
|
||||
@docker volume rm php_example
|
||||
@docker compose up --detach --build
|
||||
|
||||
.PHONY: lint
|
||||
lint: # Lint the source code for the style.
|
||||
@./vendor/bin/phpcs src index.php
|
||||
|
||||
117
web/documentserver-example/php/assets/components/file-row.js
Normal file
@ -0,0 +1,117 @@
|
||||
export class FileRow extends HTMLTableRowElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const encodedTitle = encodeURIComponent(this.file.title);
|
||||
const encodedUser = encodeURIComponent(this.user);
|
||||
const directUrl = this.directUrl ? "&directUrl=true&" : "";
|
||||
|
||||
this.innerHTML = `
|
||||
<td class="contentCells">
|
||||
<a class="stored-edit ${this.file.type}" href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}" target="_blank">
|
||||
<span>${this.file.title}</span>
|
||||
</a>
|
||||
</td>
|
||||
${this.file.editable ? `
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=edit&type=desktop" target="_blank">
|
||||
<img src="assets/images/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=edit&type=mobile" target="_blank">
|
||||
<img src="assets/images/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=comment&type=desktop" target="_blank">
|
||||
<img src="assets/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment" />
|
||||
</a>
|
||||
</td>
|
||||
${this.file.type === "word" ? `
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=review&type=desktop" target="_blank">
|
||||
<img src="assets/images/review.svg" alt="Open in editor for review" title="Open in editor for review" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon ">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=blockcontent&type=desktop" target="_blank">
|
||||
<img src="assets/images/block-content.svg" alt="Open in editor without content control modification" title="Open in editor without content control modification"
|
||||
</a>
|
||||
</td>
|
||||
`: ``}
|
||||
${this.file.type === "cell" ? `
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=filter&type=desktop" target="_blank">
|
||||
<img src="assets/images/filter.svg" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
|
||||
</a>
|
||||
</td>
|
||||
`: ``}
|
||||
${this.file.type !== "word" && this.file.type !== "cell" ? `<td class="contentCells contentCells-icon"></td><td class="contentCells contentCells-icon"></td>` : ``}
|
||||
${this.file.fillable ? `
|
||||
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=fillForms&type=desktop" target="_blank">
|
||||
<img src="assets/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" />
|
||||
</a>
|
||||
</td>
|
||||
`: `<td class="contentCells contentCells-shift contentCells-iconfirstContentCellShift"></td>`}
|
||||
` : ``}
|
||||
${this.file.fillable ? `
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=fillForms&type=desktop" target="_blank">
|
||||
<img src="assets/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon"></td>
|
||||
<td class="contentCells contentCells-icon"></td>
|
||||
<td class="contentCells contentCells-icon"></td>
|
||||
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=fillForms&type=desktop" target="_blank">
|
||||
<img src="assets/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
|
||||
</a>
|
||||
</td>
|
||||
` : `<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>`}
|
||||
<td class="contentCells contentCells-icon firstContentCellViewers">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=view&type=desktop" target="_blank">
|
||||
<img src="assets/images/desktop.svg" alt="Open in viewer for full size screens" title="Open in viewer for full size screens" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=view&type=mobile" target="_blank">
|
||||
<img src="assets/images/mobile.svg" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<a href="editor?fileID=${encodedTitle}&user=${encodedUser + directUrl}&action=embedded&type=embedded" target="_blank">
|
||||
<img src="assets/images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift downloadContentCellShift">
|
||||
<a href="download?fileName=${encodedTitle}">
|
||||
<img class="icon-download" src="assets/images/download.svg" alt="Download" title="Download"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<a class="delete-file" data="${encodedTitle}">
|
||||
<img class="icon-delete" src="assets/images/delete.svg" alt="Delete" title="Delete" />
|
||||
</a>
|
||||
</td>
|
||||
`;
|
||||
this.classList.add("tableRow");
|
||||
this.title = `${this.file.title} ${this.file.version}`;
|
||||
}
|
||||
|
||||
get file() {
|
||||
return JSON.parse(this.dataset.file || {});
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this.dataset.user;
|
||||
}
|
||||
|
||||
get directUrl() {
|
||||
return this.dataset.directUrl;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
export class FileTable extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const files = this.data.files;
|
||||
const user = this.data.user;
|
||||
const directUrl = this.data.directUrl
|
||||
|
||||
this.innerHTML = `
|
||||
<div class="stored-list">
|
||||
<div class="storedHeader">
|
||||
<div class="storedHeaderText">
|
||||
<span class="header-list">Your documents</span>
|
||||
</div>
|
||||
<div class="storedHeaderClearAll">
|
||||
<div class="clear-all">Clear all</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td class="tableHeaderCell tableHeaderCellEditors contentCells-shift">Editors</td>
|
||||
<td class="tableHeaderCell tableHeaderCellViewers">Viewers</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>
|
||||
${files.map(file =>`
|
||||
<tr
|
||||
is="file-row"
|
||||
data-file='${JSON.stringify(file)}'
|
||||
data-user="${user}"
|
||||
data-direct-url="${directUrl}"
|
||||
></tr>
|
||||
`).join("")}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
get data() {
|
||||
return JSON.parse(this.getAttribute("data")) || {}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
import { FileRow } from "./file-row.js";
|
||||
import { FileTable } from "./file-table.js";
|
||||
customElements.define("file-row", FileRow, { extends: "tr" });
|
||||
customElements.define("file-table", FileTable);
|
||||
@ -504,6 +504,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.buttonsMobile.indent {
|
||||
margin-bottom: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.button.file-type:hover,
|
||||
.button.file-type {
|
||||
height: 28px;
|
||||
width: 100px;
|
||||
margin-bottom: 10px !important;
|
||||
font-size: 9px;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -229,6 +229,33 @@ label .checkbox {
|
||||
color: #FF6F3D;
|
||||
}
|
||||
|
||||
.button.file-type {
|
||||
font-size: 11px;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button.file-type.disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button.file-type.pale {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.button.file-type.document {
|
||||
background: #446995;
|
||||
}
|
||||
|
||||
.button.file-type.spreadsheet {
|
||||
background: #40865C;
|
||||
}
|
||||
|
||||
.button.file-type.presentation {
|
||||
background: #AA5252;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
float: left;
|
||||
padding: 24px 0;
|
||||
@ -594,6 +621,29 @@ footer table tr td:first-child {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
.storedHeader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storedHeaderClearAll {
|
||||
padding-right: 52px;
|
||||
}
|
||||
|
||||
.clear-all {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding: 2px;
|
||||
outline: 1px solid #E5E5E5;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
text-transform: uppercase;
|
||||
background-color: #F5F5F5;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
color: #444444;
|
||||
font-family: Open Sans;
|
||||
@ -743,6 +793,16 @@ html {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.buttonsMobile.indent{
|
||||
padding-left: 35px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
|
||||