diff --git a/web/documentserver-example/csharp-mvc/Content/images/file_docxf.svg b/web/documentserver-example/csharp-mvc/Content/images/file_docxf.svg new file mode 100644 index 00000000..984761e6 --- /dev/null +++ b/web/documentserver-example/csharp-mvc/Content/images/file_docxf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/csharp-mvc/Content/images/mobile-fill-forms.svg b/web/documentserver-example/csharp-mvc/Content/images/mobile-fill-forms.svg new file mode 100644 index 00000000..31db5ea7 --- /dev/null +++ b/web/documentserver-example/csharp-mvc/Content/images/mobile-fill-forms.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/csharp-mvc/Content/stylesheet.css b/web/documentserver-example/csharp-mvc/Content/stylesheet.css index 903f2d19..a4a47cf8 100644 --- a/web/documentserver-example/csharp-mvc/Content/stylesheet.css +++ b/web/documentserver-example/csharp-mvc/Content/stylesheet.css @@ -158,6 +158,10 @@ label .checkbox { background-image: url("images/file_pptx.svg"); } +.try-editor.form { + background-image: url("images/file_docxf.svg"); +} + .create-sample { color: #666666; line-height: 24px; diff --git a/web/documentserver-example/csharp-mvc/Helpers/DocManagerHelper.cs b/web/documentserver-example/csharp-mvc/Helpers/DocManagerHelper.cs index aa01fdaf..0ed34cba 100644 --- a/web/documentserver-example/csharp-mvc/Helpers/DocManagerHelper.cs +++ b/web/documentserver-example/csharp-mvc/Helpers/DocManagerHelper.cs @@ -44,7 +44,7 @@ namespace OnlineEditorsExampleMVC.Helpers // get all the supported file extensions public static List FileExts { - get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).ToList(); } + get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).Concat(FillFormExts).ToList(); } } // get file extensions that can be viewed @@ -53,6 +53,11 @@ namespace OnlineEditorsExampleMVC.Helpers get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } } + public static List FillFormExts + { + get { return (WebConfigurationManager.AppSettings["files.docservice.fillform-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } + } + // get file extensions that can be edited public static List EditedExts { diff --git a/web/documentserver-example/csharp-mvc/Models/FileModel.cs b/web/documentserver-example/csharp-mvc/Models/FileModel.cs index c25baecb..ebd26b1f 100644 --- a/web/documentserver-example/csharp-mvc/Models/FileModel.cs +++ b/web/documentserver-example/csharp-mvc/Models/FileModel.cs @@ -80,11 +80,16 @@ namespace OnlineEditorsExampleMVC.Models var editorsMode = Mode ?? "edit"; // get editor mode var canEdit = DocManagerHelper.EditedExts.Contains(ext); // check if the file with such an extension can be edited - var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // set the mode parameter: change it to view if the document can't be edited - var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms")); // check if the Submit form button is displayed or not var id = request.Cookies.GetOrDefault("uid", null); var user = Users.getUser(id); // get the user + + if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && DocManagerHelper.FillFormExts.Contains(ext)) { + editorsMode = "fillForms"; + canEdit = true; + } + var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1") && false; // check if the Submit form button is displayed or not + var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // set the mode parameter: change it to view if the document can't be edited // favorite icon state bool? favorite = user.favorite; diff --git a/web/documentserver-example/csharp-mvc/Models/FileUtility.cs b/web/documentserver-example/csharp-mvc/Models/FileUtility.cs index adec7d08..e240ae0b 100644 --- a/web/documentserver-example/csharp-mvc/Models/FileUtility.cs +++ b/web/documentserver-example/csharp-mvc/Models/FileUtility.cs @@ -49,7 +49,7 @@ namespace OnlineEditorsExampleMVC.Models ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", - ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps" + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform" }; // spreadsheet extensions diff --git a/web/documentserver-example/csharp-mvc/OnlineEditorsExampleMVC.csproj b/web/documentserver-example/csharp-mvc/OnlineEditorsExampleMVC.csproj index 017d7e5b..cc4955f8 100644 --- a/web/documentserver-example/csharp-mvc/OnlineEditorsExampleMVC.csproj +++ b/web/documentserver-example/csharp-mvc/OnlineEditorsExampleMVC.csproj @@ -131,6 +131,7 @@ + @@ -143,6 +144,7 @@ + diff --git a/web/documentserver-example/csharp-mvc/Scripts/jscript.js b/web/documentserver-example/csharp-mvc/Scripts/jscript.js index e810a914..b4889c08 100644 --- a/web/documentserver-example/csharp-mvc/Scripts/jscript.js +++ b/web/documentserver-example/csharp-mvc/Scripts/jscript.js @@ -168,7 +168,7 @@ if (typeof jQuery != "undefined") { var posExt = fileName.lastIndexOf('.'); posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : ''; - if (EditedExtList.indexOf(posExt) != -1) { + if (EditedExtList.indexOf(posExt) != -1 || FillExtList.indexOf(posExt) != -1) { jq("#beginEdit").removeClass("disable"); } }; diff --git a/web/documentserver-example/csharp-mvc/Views/Home/Editor.aspx b/web/documentserver-example/csharp-mvc/Views/Home/Editor.aspx index 14d4d78b..c266e8a9 100644 --- a/web/documentserver-example/csharp-mvc/Views/Home/Editor.aspx +++ b/web/documentserver-example/csharp-mvc/Views/Home/Editor.aspx @@ -47,9 +47,11 @@ var docEditor; - var innerAlert = function (message) { + var innerAlert = function (message, inEditor) { if (console && console.log) console.log(message); + if (inEditor && docEditor) + docEditor.showMessage(message); }; // the application is loaded into the browser @@ -134,6 +136,23 @@ <% Model.GetMailMergeConfig(out dataMailMergeRecipients); %> docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>); // insert recipient data for mail merge into the file }; + + var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button + var title = event.data.title; + var url = event.data.url; + var data = { + title: title, + url: url + }; + let xhr = new XMLHttpRequest(); + xhr.open("POST", "webeditor.ashx?type=saveas"); + xhr.setRequestHeader( 'Content-Type', 'application/json'); + xhr.send(JSON.stringify(data)); + xhr.onload = function () { + innerAlert(xhr.responseText); + innerAlert(JSON.parse(xhr.responseText).file, true); + } + }; var config = <%= Model.GetDocConfig(Request, Url) %>; @@ -185,12 +204,15 @@ }; // the user is mentioned in a comment config.events['onRequestSendNotify'] = function (event) { - var actionLink = JSON.stringify(event.data.actionLink); - console.log("onRequestSendNotify:"); - console.log(event.data); - console.log("Link to comment: " + replaceActionLink(location.href, actionLink)); + event.data.actionLink = replaceActionLink(location.href, event.data.actionLink); + var data = JSON.stringify(event.data); + innerAlert("onRequestSendNotify: " + data); }; <% } %> + + if (config.editorConfig.createUrl) { + config.events.onRequestSaveAs = onRequestSaveAs; + }; var сonnectEditor = function () { docEditor = new DocsAPI.DocEditor("iframeEditor", config); diff --git a/web/documentserver-example/csharp-mvc/Views/Home/Index.aspx b/web/documentserver-example/csharp-mvc/Views/Home/Index.aspx index bb207b79..b6e33437 100644 --- a/web/documentserver-example/csharp-mvc/Views/Home/Index.aspx +++ b/web/documentserver-example/csharp-mvc/Views/Home/Index.aspx @@ -65,6 +65,9 @@ Presentation + + Master form + With sample content @@ -178,8 +181,10 @@ <% foreach (var storedFile in storedFiles) { var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name); - var docType = FileUtility.GetFileType(storedFile.Name).ToString().ToLower(); - var canEdit = DocManagerHelper.EditedExts.Contains(Path.GetExtension(storedFile.Name).ToLower()); + var docType = FileUtility.GetFileType(storedFile.Name).ToString().ToLower(); + var ext = Path.GetExtension(storedFile.Name).ToLower(); + var canEdit = DocManagerHelper.EditedExts.Contains(ext); + var isFillFormDoc = DocManagerHelper.FillFormExts.Contains(ext); %> @@ -222,25 +227,40 @@ <% } %> <% if (docType == "word") { %> - " target="_blank"> - - - - <% } else { %> - - <% } %> - <% if (docType == "word"){ %> - " target="_blank"> <% } else { %> - + <% } %> <% if (docType != "word" && docType != "cell") { %> <% } %> + <% if (isFillFormDoc) { %> + + " target="_blank"> + + + + <% } else { %> + + <% } %> + <% } else if (isFillFormDoc) { %> + + + " target="_blank"> + + + + + + + + " target="_blank"> + + + <% } else { %> <% } %> @@ -351,6 +371,7 @@ <%: Scripts.Render("~/bundles/jquery", "~/bundles/scripts") %> diff --git a/web/documentserver-example/csharp/Default.aspx.cs b/web/documentserver-example/csharp/Default.aspx.cs index a47e1ce5..7b3141b8 100644 --- a/web/documentserver-example/csharp/Default.aspx.cs +++ b/web/documentserver-example/csharp/Default.aspx.cs @@ -56,7 +56,7 @@ namespace OnlineEditorsExample ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", - ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps" + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform" }; // get an internal file extension @@ -109,7 +109,7 @@ namespace OnlineEditorsExample // get all the supported file extensions private static List FileExts { - get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).ToList(); } + get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).Concat(FillFormsExts).ToList(); } } // file extensions that can be viewed @@ -117,6 +117,11 @@ namespace OnlineEditorsExample { get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } } + + public static List FillFormsExts + { + get { return (WebConfigurationManager.AppSettings["files.docservice.fillform-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } + } // file extensions that can be edited public static List EditedExts @@ -366,6 +371,72 @@ namespace OnlineEditorsExample return _fileName; } + public static string DoSaveAs(HttpContext context) + { + string fileData; + try + { + using (var receiveStream = context.Request.InputStream) + using (var readStream = new StreamReader(receiveStream)) + { + fileData = readStream.ReadToEnd(); + if (string.IsNullOrEmpty(fileData)) return "{\"error\":\"Request stream is empty\"}"; + } + } + catch (Exception e) + { + throw new HttpException((int)HttpStatusCode.BadRequest, e.Message); + } + + var jss = new JavaScriptSerializer(); + var body = jss.Deserialize>(fileData); + var fileUrl = (string) body["url"]; + var title = (string) body["title"]; + var fileName = GetCorrectName(title); + var extension = "." + (Path.GetExtension(fileName).ToLower() ?? "").Trim('.'); + + var allExt = ConvertExts.Concat(EditedExts).Concat(ViewedExts).Concat(FillFormsExts).ToArray(); + + if (!allExt.Contains(extension)) + { + return "{\"error\":\"File type is not supported\"}"; + } + + var req = (HttpWebRequest)WebRequest.Create(fileUrl); + + // hack. http://ubuntuforums.org/showthread.php?t=1841740 + if (IsMono) + { + ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true; + } + + using (var stream = req.GetResponse().GetResponseStream()) + { + + if (stream == null || req.GetResponse().ContentLength <= 0 || req.GetResponse().ContentLength > MaxFileSize) + { + return "{\"error\": \"File size is incorrect\"}"; + } + const int bufferSize = 4096; + + using (var fs = File.Open(StoragePath(fileName, null), FileMode.Create)) + { + var buffer = new byte[bufferSize]; + int readed; + while ((readed = stream.Read(buffer, 0, bufferSize)) != 0) + { + fs.Write(buffer, 0, readed); // write bytes to the output stream + } + } + } + + var id = context.Request.Cookies.GetOrDefault("uid", null); + var user = Users.getUser(id); // get the user + DocEditor.CreateMeta(fileName, user.id, user.name, null); + + return "{\"file\": \"" + fileName + "\"}"; + } + // converting a file public static string DoConvert(HttpContext context) { diff --git a/web/documentserver-example/csharp/DocEditor.aspx b/web/documentserver-example/csharp/DocEditor.aspx index 858e3d34..91da585d 100644 --- a/web/documentserver-example/csharp/DocEditor.aspx +++ b/web/documentserver-example/csharp/DocEditor.aspx @@ -65,9 +65,11 @@ var docEditor; - var innerAlert = function (message) { + var innerAlert = function (message, inEditor) { if (console && console.log) console.log(message); + if (inEditor && docEditor) + docEditor.showMessage(message); }; // the application is loaded into the browser @@ -146,6 +148,23 @@ var onRequestMailMergeRecipients = function (event) { docEditor.setMailMergeRecipients(<%= DataMailMergeRecipients %>); // insert recipient data for mail merge into the file }; + + var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button + var title = event.data.title; + var url = event.data.url; + var data = { + title: title, + url: url + }; + let xhr = new XMLHttpRequest(); + xhr.open("POST", "webeditor.ashx?type=saveas"); + xhr.setRequestHeader( 'Content-Type', 'application/json'); + xhr.send(JSON.stringify(data)); + xhr.onload = function () { + innerAlert(xhr.responseText); + innerAlert(JSON.parse(xhr.responseText).file, true); + } + }; var config = <%= DocConfig %>; @@ -190,12 +209,15 @@ }; // the user is mentioned in a comment config.events['onRequestSendNotify'] = function (event) { - var actionLink = JSON.stringify(event.data.actionLink); - console.log("onRequestSendNotify:"); - console.log(event.data); - console.log("Link to comment: " + replaceActionLink(location.href, actionLink)); + event.data.actionLink = replaceActionLink(location.href, event.data.actionLink); + var data = JSON.stringify(event.data); + innerAlert("onRequestSendNotify: " + data); }; <% } %> + + if (config.editorConfig.createUrl) { + config.events.onRequestSaveAs = onRequestSaveAs; + }; var сonnectEditor = function () { docEditor = new DocsAPI.DocEditor("iframeEditor", config); diff --git a/web/documentserver-example/csharp/DocEditor.aspx.cs b/web/documentserver-example/csharp/DocEditor.aspx.cs index 2efc8d6f..f29a8cc0 100644 --- a/web/documentserver-example/csharp/DocEditor.aspx.cs +++ b/web/documentserver-example/csharp/DocEditor.aspx.cs @@ -145,12 +145,17 @@ namespace OnlineEditorsExample var editorsMode = Request.GetOrDefault("editorsMode", "edit"); var canEdit = _Default.EditedExts.Contains(ext); // check if this file can be edited - var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // get the editor opening mode (edit or view) - var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms")); // check if the Submit form button is displayed or hidden var editorsType = Request.GetOrDefault("editorsType", "desktop"); var id = Request.Cookies.GetOrDefault("uid", null); var user = Users.getUser(id); // get the user + + if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && _Default.FillFormsExts.Contains(ext)) { + editorsMode = "fillForms"; + canEdit = true; + } + var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1") && false; // check if the Submit form button is displayed or hidden + var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // get the editor opening mode (edit or view) var jss = new JavaScriptSerializer(); @@ -524,6 +529,9 @@ namespace OnlineEditorsExample case "slide": ext = ".pptx"; // .pptx for slide document type break; + case "docxf": + ext = ".docxf"; + break; default: return; } diff --git a/web/documentserver-example/csharp/OnlineEditorsExample.csproj b/web/documentserver-example/csharp/OnlineEditorsExample.csproj index de99848b..da373506 100644 --- a/web/documentserver-example/csharp/OnlineEditorsExample.csproj +++ b/web/documentserver-example/csharp/OnlineEditorsExample.csproj @@ -80,6 +80,7 @@ + @@ -90,6 +91,7 @@ + diff --git a/web/documentserver-example/csharp/WebEditor.ashx.cs b/web/documentserver-example/csharp/WebEditor.ashx.cs index 3f21772c..15849968 100644 --- a/web/documentserver-example/csharp/WebEditor.ashx.cs +++ b/web/documentserver-example/csharp/WebEditor.ashx.cs @@ -62,6 +62,23 @@ namespace OnlineEditorsExample case "files": Files(context); break; + case "saveas": + SaveAs(context); + break; + } + } + + private static void SaveAs(HttpContext context) + { + context.Response.ContentType = "text/plain"; + try + { + var result = _Default.DoSaveAs(context); + context.Response.Write(result); + } + catch (Exception e) + { + context.Response.Write("{ \"error\": \"" + 1 + "\", \"message\": \"" + e.Message + "\"}"); } } diff --git a/web/documentserver-example/csharp/assets b/web/documentserver-example/csharp/assets index f9fc118e..346236dd 160000 --- a/web/documentserver-example/csharp/assets +++ b/web/documentserver-example/csharp/assets @@ -1 +1 @@ -Subproject commit f9fc118e433ac604f1bc62fc4aa71fa334e97756 +Subproject commit 346236dd127c29febc9119aeb6d55aad5ad190b4 diff --git a/web/documentserver-example/csharp/script/jscript.js b/web/documentserver-example/csharp/script/jscript.js index 13910eb3..36a87ce5 100644 --- a/web/documentserver-example/csharp/script/jscript.js +++ b/web/documentserver-example/csharp/script/jscript.js @@ -168,7 +168,7 @@ if (typeof jQuery != "undefined") { var posExt = fileName.lastIndexOf('.'); posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : ''; - if (EditedExtList.indexOf(posExt) != -1) { + if (EditedExtList.indexOf(posExt) != -1 || FillFormExtList.indexOf(posExt) != -1) { jq("#beginEdit").removeClass("disable"); } }; diff --git a/web/documentserver-example/csharp/settings.config b/web/documentserver-example/csharp/settings.config index e1727602..f98711f6 100644 --- a/web/documentserver-example/csharp/settings.config +++ b/web/documentserver-example/csharp/settings.config @@ -6,8 +6,9 @@ + - + diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/FileController.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/FileController.java index 8bfceaa6..81c08e28 100755 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/FileController.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/FileController.java @@ -58,6 +58,9 @@ public class FileController { @Value("${files.docservice.header}") private String documentJwtHeader; + @Value("${filesize-max}") + private String filesizeMax; + @Autowired private FileUtility fileUtility; @Autowired @@ -278,4 +281,35 @@ public class FileController { return"{\"error\":" + error + "}"; } + + @PostMapping("/saveas") + @ResponseBody + public String saveAs(@RequestBody JSONObject body, @CookieValue("uid") String uid) { + String title = (String) body.get("title"); + String saveAsFileUrl = (String) body.get("url"); + + try { + String fileName = documentManager.getCorrectName(title); + String curExt = fileUtility.getFileExtension(fileName); + + if (!fileUtility.getFileExts().contains(curExt)) { + return "{\"error\":\"File type is not supported\"}"; + } + + URL url = new URL(saveAsFileUrl); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + InputStream stream = connection.getInputStream(); + + if (Integer.parseInt(filesizeMax) < stream.available() || stream.available() <= 0) { + return "{\"error\":\"File size is incorrect\"}"; + } + storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(fileName)), stream); + createUserMetadata(uid, fileName); + + return "{\"file\": \"" + fileName + "\"}"; + } catch (IOException e) { + e.printStackTrace(); + return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}"; + } + } } diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/IndexController.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/IndexController.java index 9a22382a..f9e28586 100755 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/IndexController.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/IndexController.java @@ -70,6 +70,7 @@ public class IndexController { List docTypes = new ArrayList<>(); List filesEditable = new ArrayList<>(); List versions = new ArrayList<>(); + List isFillFormDoc = new ArrayList<>(); List users = userService.findAll(); @@ -82,8 +83,10 @@ public class IndexController { docTypes.add(fileUtility.getDocumentType(fileName).toString().toLowerCase()); filesEditable.add(fileUtility.getEditedExts().contains(fileUtility.getFileExtension(fileName))); versions.add(" ["+storagePathBuilder.getFileVersion(fileName, true)+"]"); + isFillFormDoc.add(fileUtility.getFillExts().contains(fileUtility.getFileExtension(fileName))); } + model.addAttribute("isFillFormDoc", isFillFormDoc); model.addAttribute("versions",versions); model.addAttribute("files", files); model.addAttribute("docTypes", docTypes); @@ -100,6 +103,7 @@ public class IndexController { public HashMap configParameters(){ HashMap configuration = new HashMap<>(); + configuration.put("FillExtList", String.join(",", fileUtility.getFillExts())); configuration.put("ConverExtList", String.join(",",fileUtility.getConvertExts())); configuration.put("EditedExtList", String.join(",",fileUtility.getEditedExts())); configuration.put("UrlConverter", urlConverter); diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/DefaultFileUtility.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/DefaultFileUtility.java index 23e115d5..d2338f14 100755 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/DefaultFileUtility.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/DefaultFileUtility.java @@ -46,12 +46,15 @@ public class DefaultFileUtility implements FileUtility { @Value("${files.docservice.convert-docs}") private String docserviceConvertDocs; + @Value("${files.docservice.fillforms-docs}") + private String docserviceFillDocs; + private List ExtsDocument = Arrays.asList( ".doc", ".docx", ".docm", ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", - ".pdf", ".djvu", ".fb2", ".epub", ".xps"); + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oform"); private List ExtsSpreadsheet = Arrays.asList( ".xls", ".xlsx", ".xlsm", @@ -118,6 +121,11 @@ public class DefaultFileUtility implements FileUtility { return ".docx"; } + public List getFillExts() + { + return Arrays.asList(docserviceFillDocs.split("\\|")); + } + public List getViewedExts() { return Arrays.asList(docserviceViewedDocs.split("\\|")); @@ -139,6 +147,7 @@ public class DefaultFileUtility implements FileUtility { res.addAll(getViewedExts()); res.addAll(getEditedExts()); res.addAll(getConvertExts()); + res.addAll(getFillExts()); return res; } diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/FileUtility.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/FileUtility.java index 25b622ed..5a6eaca4 100755 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/FileUtility.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/FileUtility.java @@ -30,6 +30,7 @@ public interface FileUtility { String getFileExtension(String url); String getInternalExtension(DocumentType type); List getFileExts(); + List getFillExts(); List getViewedExts(); List getEditedExts(); List getConvertExts(); diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultCustomizationConfigurer.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultCustomizationConfigurer.java index 022c0c6b..98444687 100644 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultCustomizationConfigurer.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultCustomizationConfigurer.java @@ -20,6 +20,7 @@ package com.onlyoffice.integration.services.configurers.implementations; import com.onlyoffice.integration.documentserver.models.enums.Action; import com.onlyoffice.integration.documentserver.models.configurations.Customization; +import com.onlyoffice.integration.entities.User; import com.onlyoffice.integration.services.configurers.CustomizationConfigurer; import com.onlyoffice.integration.services.configurers.wrappers.DefaultCustomizationWrapper; import org.springframework.context.annotation.Primary; @@ -31,7 +32,7 @@ public class DefaultCustomizationConfigurer implements CustomizationConfigurer>() { }.getType())); } String fileName = wrapper.getFileName(); + String fileExt = fileUtility.getFileExtension(fileName); boolean userIsAnon = wrapper.getUser().getName().equals("Anonymous"); config.setTemplates(userIsAnon ? null : templateManager.createTemplates(fileName)); config.setCallbackUrl(documentManager.getCallback(fileName)); config.setCreateUrl(userIsAnon ? null : documentManager.getCreateUrl(fileName, false)); config.setLang(wrapper.getLang()); - Boolean canEdit = fileUtility.getEditedExts().contains(fileUtility.getFileExtension(fileName)); + Boolean canEdit = wrapper.getCanEdit(); Action action = wrapper.getAction(); defaultCustomizationConfigurer.configure(config.getCustomization(), DefaultCustomizationWrapper.builder() .action(action) - .canEdit(canEdit) + .user(wrapper.getUser()) .build()); config.setMode(canEdit && !action.equals(Action.view) ? Mode.edit : Mode.view); config.setUser(mapper.toModel(wrapper.getUser())); diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultFileConfigurer.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultFileConfigurer.java index 9feb7348..ef30ff02 100755 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultFileConfigurer.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultFileConfigurer.java @@ -66,17 +66,19 @@ public class DefaultFileConfigurer implements FileConfigurer fileModel.setType(wrapper.getType()); Permission userPermissions = mapper.toModel(wrapper.getUser().getPermissions()); - userPermissions.setComment( - !action.equals(Action.view) - && !action.equals(Action.fillForms) - && !action.equals(Action.embedded) - && !action.equals(Action.blockcontent) - ); + + String fileExt = fileUtility.getFileExtension(wrapper.getFileName()); + Boolean canEdit = fileUtility.getEditedExts().contains(fileExt); + if ((!canEdit && action.equals(Action.edit) || action.equals(Action.fillForms)) && fileUtility.getFillExts().contains(fileExt)) { + canEdit = true; + wrapper.setAction(Action.fillForms); + } + wrapper.setCanEdit(canEdit); DefaultDocumentWrapper documentWrapper = DefaultDocumentWrapper .builder() .fileName(fileName) - .permission(userPermissions) + .permission(updatePermissions(userPermissions, action, canEdit)) .favorite(wrapper.getUser().getFavorite()) .build(); @@ -99,4 +101,31 @@ public class DefaultFileConfigurer implements FileConfigurer configure(fileModel, wrapper); return fileModel; } + + private Permission updatePermissions(Permission userPermissions, Action action, Boolean canEdit) { + userPermissions.setComment( + !action.equals(Action.view) + && !action.equals(Action.fillForms) + && !action.equals(Action.embedded) + && !action.equals(Action.blockcontent) + ); + + userPermissions.setFillForms( + !action.equals(Action.view) + && !action.equals(Action.comment) + && !action.equals(Action.embedded) + && !action.equals(Action.blockcontent) + ); + + userPermissions.setReview(canEdit && + (action.equals(Action.review) || action.equals(Action.edit))); + + userPermissions.setEdit(canEdit && + (action.equals(Action.view) + || action.equals(Action.edit) + || action.equals(Action.filter) + || action.equals(Action.blockcontent))); + + return userPermissions; + } } diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultCustomizationWrapper.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultCustomizationWrapper.java index 0b8ff7d5..dfe8b5fc 100644 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultCustomizationWrapper.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultCustomizationWrapper.java @@ -19,6 +19,7 @@ package com.onlyoffice.integration.services.configurers.wrappers; import com.onlyoffice.integration.documentserver.models.enums.Action; +import com.onlyoffice.integration.entities.User; import lombok.Builder; import lombok.Getter; @@ -26,5 +27,5 @@ import lombok.Getter; @Builder public class DefaultCustomizationWrapper { private Action action; - private Boolean canEdit; + private User user; } diff --git a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultFileWrapper.java b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultFileWrapper.java index 81b53e9d..79b1097a 100644 --- a/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultFileWrapper.java +++ b/web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultFileWrapper.java @@ -24,9 +24,11 @@ import com.onlyoffice.integration.documentserver.models.enums.Language; import com.onlyoffice.integration.documentserver.models.enums.Type; import lombok.Builder; import lombok.Getter; +import lombok.Setter; @Getter @Builder +@Setter public class DefaultFileWrapper { private String fileName; private Type type; @@ -34,4 +36,5 @@ public class DefaultFileWrapper { private Language lang; private Action action; private String actionData; + private Boolean canEdit; } diff --git a/web/documentserver-example/java-spring/src/main/resources/application.properties b/web/documentserver-example/java-spring/src/main/resources/application.properties index 509fe98d..6fccee58 100755 --- a/web/documentserver-example/java-spring/src/main/resources/application.properties +++ b/web/documentserver-example/java-spring/src/main/resources/application.properties @@ -8,8 +8,9 @@ filesize-max=5242880 files.storage= files.storage.folder=documents +files.docservice.fillforms-docs=.oform|.docx files.docservice.viewed-docs=.pdf|.djvu|.xps|.oxps -files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt +files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt|.docxf files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2 files.docservice.timeout=120000 files.docservice.history.postfix=-hist diff --git a/web/documentserver-example/java-spring/src/main/resources/assets b/web/documentserver-example/java-spring/src/main/resources/assets index 65addf50..346236dd 160000 --- a/web/documentserver-example/java-spring/src/main/resources/assets +++ b/web/documentserver-example/java-spring/src/main/resources/assets @@ -1 +1 @@ -Subproject commit 65addf50e40c1a9fceb7c270b6c4b0f6bc5cf2ca +Subproject commit 346236dd127c29febc9119aeb6d55aad5ad190b4 diff --git a/web/documentserver-example/java-spring/src/main/resources/static/css/img/file_docxf.svg b/web/documentserver-example/java-spring/src/main/resources/static/css/img/file_docxf.svg new file mode 100644 index 00000000..984761e6 --- /dev/null +++ b/web/documentserver-example/java-spring/src/main/resources/static/css/img/file_docxf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/java-spring/src/main/resources/static/css/img/mobile-fill-forms.svg b/web/documentserver-example/java-spring/src/main/resources/static/css/img/mobile-fill-forms.svg new file mode 100644 index 00000000..31db5ea7 --- /dev/null +++ b/web/documentserver-example/java-spring/src/main/resources/static/css/img/mobile-fill-forms.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/java-spring/src/main/resources/static/css/stylesheet.css b/web/documentserver-example/java-spring/src/main/resources/static/css/stylesheet.css index d00c56c7..dde198c4 100755 --- a/web/documentserver-example/java-spring/src/main/resources/static/css/stylesheet.css +++ b/web/documentserver-example/java-spring/src/main/resources/static/css/stylesheet.css @@ -158,6 +158,10 @@ label .checkbox { background-image: url("img/file_pptx.svg"); } +.try-editor.form { + background-image: url("img/file_docxf.svg"); +} + .create-sample { color: #666666; line-height: 24px; diff --git a/web/documentserver-example/java-spring/src/main/resources/static/scripts/converter.js b/web/documentserver-example/java-spring/src/main/resources/static/scripts/converter.js index 43594e88..f8ae3ca8 100755 --- a/web/documentserver-example/java-spring/src/main/resources/static/scripts/converter.js +++ b/web/documentserver-example/java-spring/src/main/resources/static/scripts/converter.js @@ -20,10 +20,12 @@ var ConverExtList; var EditedExtList; var UrlConverter; var UrlEditor; +var FillExtList; if (typeof jQuery !== "undefined") { jQuery.post('/config', function(data) { + FillExtList = data.FillExtList; ConverExtList = data.ConverExtList; EditedExtList = data.EditedExtList; UrlConverter = data.UrlConverter; diff --git a/web/documentserver-example/java-spring/src/main/resources/static/scripts/jscript.js b/web/documentserver-example/java-spring/src/main/resources/static/scripts/jscript.js index ecc65215..5393d329 100755 --- a/web/documentserver-example/java-spring/src/main/resources/static/scripts/jscript.js +++ b/web/documentserver-example/java-spring/src/main/resources/static/scripts/jscript.js @@ -167,7 +167,7 @@ if (typeof jQuery !== "undefined") { var posExt = fileName.lastIndexOf("."); posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : ""; - if (EditedExtList.indexOf(posExt) !== -1) { + if (EditedExtList.indexOf(posExt) !== -1 || FillExtList.indexOf(posExt) !== -1) { jq("#beginEdit").removeClass("disable"); } }; diff --git a/web/documentserver-example/java-spring/src/main/resources/templates/editor.html b/web/documentserver-example/java-spring/src/main/resources/templates/editor.html index 3b3f5cfb..567077b6 100755 --- a/web/documentserver-example/java-spring/src/main/resources/templates/editor.html +++ b/web/documentserver-example/java-spring/src/main/resources/templates/editor.html @@ -31,9 +31,11 @@ diff --git a/web/documentserver-example/php/assets b/web/documentserver-example/php/assets index f9fc118e..346236dd 160000 --- a/web/documentserver-example/php/assets +++ b/web/documentserver-example/php/assets @@ -1 +1 @@ -Subproject commit f9fc118e433ac604f1bc62fc4aa71fa334e97756 +Subproject commit 346236dd127c29febc9119aeb6d55aad5ad190b4 diff --git a/web/documentserver-example/php/common.php b/web/documentserver-example/php/common.php index 4002df1d..16b13248 100644 --- a/web/documentserver-example/php/common.php +++ b/web/documentserver-example/php/common.php @@ -325,11 +325,13 @@ function getStoredFiles() { foreach($cdir as $key => $fileName) { // run through all the file and folder names if (!in_array($fileName,array(".", ".."))) { if (!is_dir($directory . DIRECTORY_SEPARATOR . $fileName)) { // if an element isn't a directory + $ext = strtolower('.' . pathinfo($fileName, PATHINFO_EXTENSION)); $dat = filemtime($directory . DIRECTORY_SEPARATOR . $fileName); // get the time of element modification $result[$dat] = (object) array( // and write the file to the result "name" => $fileName, "documentType" => getDocumentType($fileName), - "canEdit" => in_array(strtolower('.' . pathinfo($fileName, PATHINFO_EXTENSION)), $GLOBALS['DOC_SERV_EDITED']) + "canEdit" => in_array($ext, $GLOBALS['DOC_SERV_EDITED']), + "isFillFormDoc" => in_array($ext, $GLOBALS['DOC_SERV_FILLFORMS']) ); } } @@ -409,7 +411,7 @@ function getFileInfo($fileId){ // get all the supported file extensions function getFileExts() { - return array_merge($GLOBALS['DOC_SERV_VIEWD'], $GLOBALS['DOC_SERV_EDITED'], $GLOBALS['DOC_SERV_CONVERT']); + return array_merge($GLOBALS['DOC_SERV_VIEWD'], $GLOBALS['DOC_SERV_EDITED'], $GLOBALS['DOC_SERV_CONVERT'], $GLOBALS['DOC_SERV_FILLFORMS']); } // get the correct file name if such a name already exists diff --git a/web/documentserver-example/php/config.php b/web/documentserver-example/php/config.php index 9236a28d..7f83cfb3 100644 --- a/web/documentserver-example/php/config.php +++ b/web/documentserver-example/php/config.php @@ -6,8 +6,9 @@ $GLOBALS['FILE_SIZE_MAX'] = 5242880; $GLOBALS['STORAGE_PATH'] = ""; $GLOBALS['ALONE'] = FALSE; +$GLOBALS['DOC_SERV_FILLFORMS'] = array(".oform", ".docx"); $GLOBALS['DOC_SERV_VIEWD'] = array(".pdf", ".djvu", ".xps", ".oxps"); -$GLOBALS['DOC_SERV_EDITED'] = array(".docx", ".xlsx", ".csv", ".pptx", ".txt"); +$GLOBALS['DOC_SERV_EDITED'] = array(".docx", ".xlsx", ".csv", ".pptx", ".txt", ".docxf"); $GLOBALS['DOC_SERV_CONVERT'] = array(".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2"); $GLOBALS['DOC_SERV_TIMEOUT'] = "120000"; @@ -41,7 +42,7 @@ $GLOBALS['ExtsDocument'] = array(".doc", ".docx", ".docm", ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", - ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps"); + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform"); ?> \ No newline at end of file diff --git a/web/documentserver-example/php/css/images/file_docxf.svg b/web/documentserver-example/php/css/images/file_docxf.svg new file mode 100644 index 00000000..984761e6 --- /dev/null +++ b/web/documentserver-example/php/css/images/file_docxf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/php/css/images/mobile-fill-forms.svg b/web/documentserver-example/php/css/images/mobile-fill-forms.svg new file mode 100644 index 00000000..31db5ea7 --- /dev/null +++ b/web/documentserver-example/php/css/images/mobile-fill-forms.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/php/css/stylesheet.css b/web/documentserver-example/php/css/stylesheet.css index b90123e4..6bdc49ef 100644 --- a/web/documentserver-example/php/css/stylesheet.css +++ b/web/documentserver-example/php/css/stylesheet.css @@ -157,6 +157,10 @@ label .checkbox { background-image: url("images/file_pptx.svg"); } +.try-editor.form { + background-image: url("images/file_docxf.svg"); +} + .create-sample { color: #666666; line-height: 24px; diff --git a/web/documentserver-example/php/doceditor.php b/web/documentserver-example/php/doceditor.php index 88cdf9bb..886ef73f 100644 --- a/web/documentserver-example/php/doceditor.php +++ b/web/documentserver-example/php/doceditor.php @@ -56,9 +56,14 @@ $docKey = getDocEditorKey($filename); $filetype = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + $ext = strtolower('.' . pathinfo($filename, PATHINFO_EXTENSION)); $editorsMode = empty($_GET["action"]) ? "edit" : $_GET["action"]; // get the editors mode - $canEdit = in_array(strtolower('.' . pathinfo($filename, PATHINFO_EXTENSION)), $GLOBALS['DOC_SERV_EDITED']); // check if the file can be edited - $submitForm = $canEdit && ($editorsMode == "edit" || $editorsMode == "fillForms"); // check if the Submit form button is displayed or not + $canEdit = in_array($ext, $GLOBALS['DOC_SERV_EDITED']); // check if the file can be edited + if ((!$canEdit && $editorsMode == "edit" || $editorsMode == "fillForms") && in_array($ext, $GLOBALS['DOC_SERV_FILLFORMS'])) { + $editorsMode = "fillForms"; + $canEdit = true; + } + $submitForm = $editorsMode == "fillForms" && $user->id == "uid-1" && !1; // check if the Submit form button is displayed or not $mode = $canEdit && $editorsMode != "view" ? "edit" : "view"; // define if the editing mode is edit or view $type = empty($_GET["type"]) ? "desktop" : $_GET["type"]; @@ -339,9 +344,11 @@ var docEditor; - var innerAlert = function (message) { + var innerAlert = function (message, inEditor) { if (console && console.log) console.log(message); + if (inEditor && docEditor) + docEditor.showMessage(message); }; // the application is loaded into the browser @@ -421,6 +428,23 @@ docEditor.setMailMergeRecipients(); // insert recipient data for mail merge into the file }; + var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button + var title = event.data.title; + var url = event.data.url; + var data = { + title: title, + url: url + }; + let xhr = new XMLHttpRequest(); + xhr.open("POST", "webeditor-ajax.php?type=saveas"); + xhr.setRequestHeader( 'Content-Type', 'application/json'); + xhr.send(JSON.stringify(data)); + xhr.onload = function () { + innerAlert(xhr.responseText); + innerAlert(JSON.parse(xhr.responseText.substring(xhr.responseText.indexOf("{"))).file, true); + } + }; + var сonnectEditor = function () { + if (config.editorConfig.createUrl) { + config.events.onRequestSaveAs = onRequestSaveAs; + }; + docEditor = new DocsAPI.DocEditor("iframeEditor", config); }; diff --git a/web/documentserver-example/php/index.php b/web/documentserver-example/php/index.php index 497bbce1..00de5b61 100644 --- a/web/documentserver-example/php/index.php +++ b/web/documentserver-example/php/index.php @@ -68,6 +68,9 @@ Presentation + + Master form + With sample content @@ -215,24 +218,36 @@ } if ($storeFile->documentType == "word") { echo ' '; - echo ' '; - echo ' '; - echo ' '; - } - else{ - echo ' '; - } - if ($storeFile->documentType == "word") { - echo ' '; echo ' '; echo ' '; echo ' '; } else{ - echo ' '; + echo ' '; } if($storeFile->documentType!="word" && $storeFile->documentType!="cell"){ echo ' '; } + if ($storeFile->isFillFormDoc) { + echo ' '; + echo ' '; + echo ' '; + echo ' '; + } else { + echo ' '; + } + } else if ($storeFile->isFillFormDoc) { + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; } else { echo ''; } @@ -347,6 +362,7 @@ diff --git a/web/documentserver-example/php/js/jscript.js b/web/documentserver-example/php/js/jscript.js index 776525cc..f05b9bbf 100644 --- a/web/documentserver-example/php/js/jscript.js +++ b/web/documentserver-example/php/js/jscript.js @@ -189,7 +189,7 @@ if (typeof jQuery != "undefined") { var posExt = fileName.lastIndexOf('.'); posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : ''; - if (EditedExtList.indexOf(posExt) != -1) { + if (EditedExtList.indexOf(posExt) != -1 || FillFormsExtList.indexOf(posExt) != -1) { jq("#beginEdit").removeClass("disable"); } }; diff --git a/web/documentserver-example/php/webeditor-ajax.php b/web/documentserver-example/php/webeditor-ajax.php index 70c6c27a..bf9c191e 100644 --- a/web/documentserver-example/php/webeditor-ajax.php +++ b/web/documentserver-example/php/webeditor-ajax.php @@ -87,6 +87,10 @@ if (isset($_GET["type"]) && !empty($_GET["type"])) { case "files": $response_array = files(); die (json_encode($response_array)); + case "saveas": + $response_array = saveas(); + $response_array['status'] = 'success'; + die (json_encode($response_array)); default: $response_array['status'] = 'error'; $response_array['error'] = '404 Method not found'; @@ -94,6 +98,43 @@ if (isset($_GET["type"]) && !empty($_GET["type"])) { } } +// save copy as... +function saveas() { + try { + $result; + $post = json_decode(file_get_contents('php://input'), true); + $fileurl = $post["url"]; + $title = $post["title"]; + $extension = strtolower(pathinfo($title, PATHINFO_EXTENSION)); + $allexts = array_merge($GLOBALS['DOC_SERV_CONVERT'], $GLOBALS['DOC_SERV_EDITED'], $GLOBALS['DOC_SERV_VIEWD'], $GLOBALS['DOC_SERV_FILLFORMS']); + $filename = GetCorrectName($title); + + if (!in_array("." . $extension, $allexts)) { + $result["error"] = "File type is not supported"; + return $result; + } + $headers = get_headers($fileurl, 1); + $content_length = $headers["Content-Length"]; + $data = file_get_contents(str_replace(" ","%20",$fileurl)); + + if ($data === false || $content_length <= 0 || $content_length > $GLOBALS['FILE_SIZE_MAX']) { + $result["error"] = "File size is incorrect"; + return $result; + } + + file_put_contents(getStoragePath($filename), $data, LOCK_EX); // write data to the new file + $user = getUser($_GET["user"]); + createMeta($filename, $user->id, $user->name); // and create meta data for this file + + $result["file"] = $filename; + return $result; + } catch (Exception $e) { + sendlog("SaveAs: ".$e->getMessage(), "webedior-ajax.log"); + $result["error"] = "error: " . 1 . "message:" . $e->getMessage(); + return $result; + } +} + // uploading a file function upload() { $result; $filename; diff --git a/web/documentserver-example/python/assets b/web/documentserver-example/python/assets index f9fc118e..346236dd 160000 --- a/web/documentserver-example/python/assets +++ b/web/documentserver-example/python/assets @@ -1 +1 @@ -Subproject commit f9fc118e433ac604f1bc62fc4aa71fa334e97756 +Subproject commit 346236dd127c29febc9119aeb6d55aad5ad190b4 diff --git a/web/documentserver-example/python/config.py b/web/documentserver-example/python/config.py index dcb9dc1c..184f3791 100644 --- a/web/documentserver-example/python/config.py +++ b/web/documentserver-example/python/config.py @@ -5,8 +5,9 @@ VERSION = '1.0.0' FILE_SIZE_MAX = 5242880 STORAGE_PATH = 'app_data' +DOC_SERV_FILLFORMS = [".oform", ".docx"] DOC_SERV_VIEWED = [".pdf", ".djvu", ".xps", ".oxps"] # file extensions that can be viewed -DOC_SERV_EDITED = [".docx", ".xlsx", ".csv", ".pptx", ".txt"] # file extensions that can be edited +DOC_SERV_EDITED = [".docx", ".xlsx", ".csv", ".pptx", ".txt", ".docxf"] # file extensions that can be edited DOC_SERV_CONVERT = [ # file extensions that can be converted ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", @@ -47,7 +48,7 @@ EXT_DOCUMENT = [ ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", - ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps" + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform" ] if os.environ.get("EXAMPLE_DOMAIN"): # generates a link for example domain diff --git a/web/documentserver-example/python/src/urls.py b/web/documentserver-example/python/src/urls.py index 502398ee..44f150e2 100644 --- a/web/documentserver-example/python/src/urls.py +++ b/web/documentserver-example/python/src/urls.py @@ -39,7 +39,8 @@ urlpatterns = [ path('track', actions.track), path('remove', actions.remove), path('csv', actions.csv), - path('files', actions.files) + path('files', actions.files), + path('saveas', actions.saveAs) ] urlpatterns += staticfiles_urlpatterns() \ No newline at end of file diff --git a/web/documentserver-example/python/src/utils/docManager.py b/web/documentserver-example/python/src/utils/docManager.py index 952d8aee..b79c4ffa 100644 --- a/web/documentserver-example/python/src/utils/docManager.py +++ b/web/documentserver-example/python/src/utils/docManager.py @@ -73,6 +73,9 @@ LANGUAGES = { 'vi': 'Vietnamese' } +def isCanFillForms(ext): + return ext in config.DOC_SERV_FILLFORMS + # check if the file extension can be viewed def isCanView(ext): return ext in config.DOC_SERV_VIEWED @@ -87,14 +90,15 @@ def isCanConvert(ext): # check if the file extension is supported by the editor (it can be viewed or edited or converted) def isSupportedExt(ext): - return isCanView(ext) | isCanEdit(ext) | isCanConvert(ext) + return isCanView(ext) | isCanEdit(ext) | isCanConvert(ext) | isCanFillForms(ext) # get internal extension for a given file type def getInternalExtension(fileType): mapping = { 'word': '.docx', 'cell': '.xlsx', - 'slide': '.pptx' + 'slide': '.pptx', + 'docxf': '.docxf' } return mapping.get(fileType, '.docx') # the default file type is .docx @@ -208,7 +212,7 @@ def getStoredFiles(req): for f in files: if os.path.isfile(os.path.join(directory, f)): - fileInfos.append({'version':historyManager.getFileVersion(historyManager.getHistoryDir(getStoragePath(f, req))), 'type': fileUtils.getFileType(f), 'title': f, 'url': getFileUri(f, True, req), 'canEdit': isCanEdit(fileUtils.getFileExt(f))}) # write information about file type, title and url + fileInfos.append({'isFillFormDoc': isCanFillForms(fileUtils.getFileExt(f)),'version':historyManager.getFileVersion(historyManager.getHistoryDir(getStoragePath(f, req))), 'type': fileUtils.getFileType(f), 'title': f, 'url': getFileUri(f, True, req), 'canEdit': isCanEdit(fileUtils.getFileExt(f))}) # write information about file type, title and url return fileInfos diff --git a/web/documentserver-example/python/src/views/actions.py b/web/documentserver-example/python/src/views/actions.py index 23096937..d14c3a6c 100644 --- a/web/documentserver-example/python/src/views/actions.py +++ b/web/documentserver-example/python/src/views/actions.py @@ -23,6 +23,7 @@ SOFTWARE. """ +import requests import config import json @@ -115,6 +116,37 @@ def createNew(request): return HttpResponse(json.dumps(response), content_type='application/json') +# save file as... +def saveAs(request): + response ={} + + try: + body = json.loads(request.body) + saveAsFileUrl = body.get('url') + title = body.get('title') + + filename = docManager.getCorrectName(title, request) + path = docManager.getStoragePath(filename, request) + resp = requests.get(saveAsFileUrl) + + if ((len(resp.content) > config.FILE_SIZE_MAX) | (len(resp.content) <= 0)): # check if the file size exceeds the maximum size allowed (5242880) + response.setdefault('error', 'File size is incorrect') + raise Exception('File size is incorrect') + + curExt = fileUtils.getFileExt(filename) + if not docManager.isSupportedExt(curExt): # check if the file extension is supported by the document manager + response.setdefault('error', 'File type is not supported') + raise Exception('File type is not supported') + + docManager.saveFileFromUri(saveAsFileUrl, path, request, True) # save the file from the new url in the storage directory + + response.setdefault('file', filename) + except Exception as e: + response.setdefault('error', 1) + response.setdefault('message', e.args[0]) + + return HttpResponse(json.dumps(response), content_type='application/json') + # edit a file def edit(request): filename = fileUtils.getFileName(request.GET['filename']) @@ -129,7 +161,11 @@ def edit(request): edMode = request.GET.get('mode') if request.GET.get('mode') else 'edit' # get the editor mode: view/edit/review/comment/fillForms/embedded (the default mode is edit) canEdit = docManager.isCanEdit(ext) # check if the file with this extension can be edited - submitForm = canEdit & ((edMode == 'edit') | (edMode == 'fillForms')) # if the Submit form button is displayed or hidden + + if (((not canEdit) and edMode == 'edit') or edMode == 'fillForms') and docManager.isCanFillForms(ext) : + edMode = 'fillForms' + canEdit = True + submitForm = edMode == 'fillForms' and user.id == 'uid-1' and False # if the Submit form button is displayed or hidden mode = 'edit' if canEdit & (edMode != 'view') else 'view' # if the file can't be edited, the mode is view edType = request.GET.get('type') if request.GET.get('type') else 'desktop' # get the editor type: embedded/mobile/desktop (the default type is desktop) diff --git a/web/documentserver-example/python/src/views/index.py b/web/documentserver-example/python/src/views/index.py index a658095d..0e74d9c5 100644 --- a/web/documentserver-example/python/src/views/index.py +++ b/web/documentserver-example/python/src/views/index.py @@ -39,6 +39,7 @@ def default(request): # default parameters that will be passed to the template 'preloadurl': config.DOC_SERV_SITE_URL + config.DOC_SERV_PRELOADER_URL, 'editExt': json.dumps(config.DOC_SERV_EDITED), # file extensions that can be edited 'convExt': json.dumps(config.DOC_SERV_CONVERT), # file extensions that can be converted - 'files': docManager.getStoredFiles(request) # information about stored files + 'files': docManager.getStoredFiles(request), # information about stored files + 'fillExt': json.dumps(config.DOC_SERV_FILLFORMS) } return render(request, 'index.html', context) # execute the "index.html" template with context data and return http response in json format \ No newline at end of file diff --git a/web/documentserver-example/python/static/css/stylesheet.css b/web/documentserver-example/python/static/css/stylesheet.css index c1219130..421be08c 100644 --- a/web/documentserver-example/python/static/css/stylesheet.css +++ b/web/documentserver-example/python/static/css/stylesheet.css @@ -166,6 +166,10 @@ label .checkbox { background-image: url("../images/file_pptx.svg"); } +.try-editor.form { + background-image: url("../images/file_docxf.svg"); +} + .create-sample { color: #666666; line-height: 24px; diff --git a/web/documentserver-example/python/static/images/file_docxf.svg b/web/documentserver-example/python/static/images/file_docxf.svg new file mode 100644 index 00000000..984761e6 --- /dev/null +++ b/web/documentserver-example/python/static/images/file_docxf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/python/static/images/mobile-fill-forms.svg b/web/documentserver-example/python/static/images/mobile-fill-forms.svg new file mode 100644 index 00000000..31db5ea7 --- /dev/null +++ b/web/documentserver-example/python/static/images/mobile-fill-forms.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/documentserver-example/python/static/js/jscript.js b/web/documentserver-example/python/static/js/jscript.js index f919ca9b..c2e0db31 100644 --- a/web/documentserver-example/python/static/js/jscript.js +++ b/web/documentserver-example/python/static/js/jscript.js @@ -175,7 +175,7 @@ if (typeof jQuery !== "undefined") { var posExt = fileName.lastIndexOf("."); posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : ""; - if (EditedExtList.indexOf(posExt) !== -1) { + if (EditedExtList.indexOf(posExt) !== -1 || FillExtList.indexOf(posExt) !== -1) { jq("#beginEdit").removeClass("disable"); } }; diff --git a/web/documentserver-example/python/templates/editor.html b/web/documentserver-example/python/templates/editor.html index 90210c47..25a8223d 100644 --- a/web/documentserver-example/python/templates/editor.html +++ b/web/documentserver-example/python/templates/editor.html @@ -50,9 +50,11 @@ var docEditor; - var innerAlert = function (message) { + var innerAlert = function (message, inEditor) { if (console && console.log) console.log(message); + if (inEditor && docEditor) + docEditor.showMessage(message); }; // the application is loaded into the browser @@ -134,6 +136,23 @@ ); }; + var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button + var title = event.data.title; + var url = event.data.url; + var data = { + title: title, + url: url + }; + let xhr = new XMLHttpRequest(); + xhr.open("POST", "saveas"); + xhr.setRequestHeader( 'Content-Type', 'application/json'); + xhr.send(JSON.stringify(data)); + xhr.onload = function () { + innerAlert(xhr.responseText); + innerAlert(JSON.parse(xhr.responseText).file, true); + } + }; + var connectEditor = function () { config = {{ cfg | safe }} @@ -181,14 +200,16 @@ }; // the user is mentioned in a comment config.events['onRequestSendNotify'] = function (event) { - var actionLink = JSON.stringify(event.data.actionLink); - console.log("onRequestSendNotify:"); - console.log(event.data); - console.log("Link to comment: " + replaceActionLink(location.href, actionLink)); + event.data.actionLink = replaceActionLink(location.href, event.data.actionLink); + var data = JSON.stringify(event.data); + innerAlert("onRequestSendNotify: " + data); }; {% endif %} + if (config.editorConfig.createUrl) { + config.events.onRequestSaveAs = onRequestSaveAs; + }; docEditor = new DocsAPI.DocEditor("iframeEditor", config); fixSize(); diff --git a/web/documentserver-example/python/templates/index.html b/web/documentserver-example/python/templates/index.html index dc2f7d13..0edbcd5c 100644 --- a/web/documentserver-example/python/templates/index.html +++ b/web/documentserver-example/python/templates/index.html @@ -67,6 +67,9 @@ Presentation + + Master form + With sample content @@ -187,25 +190,40 @@ {% endif %} {% if file.type == 'word' %} - - - - - {% else %} - - {% endif %} - {% if file.type == 'word' %} - {% else %} - + {% endif %} {% if file.type == 'slide' %} {% endif %} + {% if file.isFillFormDoc %} + + + + + + {% else %} + + {% endif %} + {% elif file.isFillFormDoc %} + + + + + + + + + + + + + + {% else %} {% endif %} @@ -320,6 +338,7 @@