Merge branch 'release/v1.1.0' into feature/translate-1.1.0
@ -159,7 +159,8 @@ namespace ASC.Common.Web
|
||||
AddMimeMapping(".docm", "application/vnd.ms-word.document.macroEnabled.12");
|
||||
AddMimeMapping(".doct", "application/doct");
|
||||
AddMimeMapping(".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
AddMimeMapping(".docxf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
AddMimeMapping(".docxf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
AddMimeMapping(".docxf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf");
|
||||
AddMimeMapping(".dot", "application/msword");
|
||||
AddMimeMapping(".dotm", "application/vnd.ms-word.template.macroEnabled.12");
|
||||
AddMimeMapping(".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template");
|
||||
@ -431,7 +432,8 @@ namespace ASC.Common.Web
|
||||
AddMimeMapping(".odp", "application/vnd.oasis.opendocument.presentation");
|
||||
AddMimeMapping(".ods", "application/vnd.oasis.opendocument.spreadsheet");
|
||||
AddMimeMapping(".odt", "application/vnd.oasis.opendocument.text");
|
||||
AddMimeMapping(".oform", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
AddMimeMapping(".oform", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
AddMimeMapping(".oform", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform");
|
||||
AddMimeMapping(".oga", "audio/ogg");
|
||||
AddMimeMapping(".ogg", "video/ogg");
|
||||
AddMimeMapping(".ogg", "audio/ogg");
|
||||
|
@ -299,11 +299,25 @@ namespace ASC.ApiSystem.Controllers
|
||||
//return null;
|
||||
}
|
||||
|
||||
public bool ValidateRecaptcha(string response, string ip)
|
||||
public bool ValidateRecaptcha(string response, RecaptchaType recaptchaType, string ip)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = string.Format("secret={0}&remoteip={1}&response={2}", Configuration["recaptcha:private-key"], ip, response);
|
||||
{
|
||||
string privateKey;
|
||||
switch (recaptchaType)
|
||||
{
|
||||
case RecaptchaType.AndroidV2:
|
||||
privateKey = Configuration["recaptcha:private-key:android"];
|
||||
break;
|
||||
case RecaptchaType.iOSV2:
|
||||
privateKey = Configuration["recaptcha:private-key:ios"];
|
||||
break;
|
||||
default:
|
||||
privateKey = Configuration["recaptcha:private-key"];
|
||||
break;
|
||||
}
|
||||
|
||||
var data = string.Format("secret={0}&remoteip={1}&response={2}", privateKey, ip, response);
|
||||
var url = Configuration["recaptcha:verify-url"] ?? "https://www.recaptcha.net/recaptcha/api/siteverify";
|
||||
|
||||
var webRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
|
@ -671,12 +671,12 @@ namespace ASC.ApiSystem.Controllers
|
||||
{
|
||||
Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha via app key: {1}. {2}", model.PortalName, model.AppKey, sw.ElapsedMilliseconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
var data = string.Format("{0} {1} {2} {3} {4}", model.PortalName, model.FirstName, model.LastName, model.Email, model.Phone);
|
||||
}
|
||||
|
||||
var data = string.Format("{0} {1} {2} {3} {4} {5}", model.PortalName, model.FirstName, model.LastName, model.Email, model.Phone, model.RecaptchaType);
|
||||
|
||||
/*** validate recaptcha ***/
|
||||
if (!CommonMethods.ValidateRecaptcha(model.RecaptchaResponse, clientIP))
|
||||
if (!CommonMethods.ValidateRecaptcha(model.RecaptchaResponse, model.RecaptchaType, clientIP))
|
||||
{
|
||||
Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha error: {1} {2}", model.PortalName, sw.ElapsedMilliseconds, data);
|
||||
sw.Stop();
|
||||
|
25
common/services/ASC.ApiSystem/Models/RecaptchaType.cs
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2021
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ApiSystem.Models
|
||||
{
|
||||
public enum RecaptchaType
|
||||
{
|
||||
Default = 0,
|
||||
AndroidV2 = 1,
|
||||
iOSV2 = 2
|
||||
}
|
||||
}
|
@ -73,7 +73,9 @@ namespace ASC.ApiSystem.Models
|
||||
[StringLength(32)]
|
||||
public string Phone { get; set; }
|
||||
|
||||
public string RecaptchaResponse { get; set; }
|
||||
public string RecaptchaResponse { get; set; }
|
||||
|
||||
public RecaptchaType RecaptchaType { get; set; }
|
||||
|
||||
[StringLength(20)]
|
||||
public string Region { get; set; }
|
||||
|
@ -60,7 +60,7 @@
|
||||
"commented-docs": [ ".docx", ".docxf", ".xlsx", ".pptx" ],
|
||||
"convert-docs": [ ".pptm", ".ppt", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".rtf" ],
|
||||
"edited-docs": [ ".pptx", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".xlsx", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".csv", ".docx", ".docxf", ".oform", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".txt", ".rtf", ".mht", ".html", ".htm" ],
|
||||
"encrypted-docs": [ ".docx", ".docxf", ".xlsx", ".pptx" ],
|
||||
"encrypted-docs": [ ".docx", ".docxf", ".xlsx", ".pptx", ".oform" ],
|
||||
"formfilling-docs": [ ".oform" ],
|
||||
"customfilter-docs": [ ".xlsx" ],
|
||||
"reviewed-docs": [ ".docx", ".docxf" ],
|
||||
|
@ -1,9 +1,7 @@
|
||||
module.exports = {
|
||||
globDirectory: 'build/deploy/',
|
||||
globPatterns: [
|
||||
"**/*.{js,css,woff2,svg}"
|
||||
],
|
||||
globIgnores: ['**/remoteEntry.js'],
|
||||
swSrc: 'packages/asc-web-common/utils/sw-template.js',
|
||||
swDest: 'build/deploy/public/sw.js'
|
||||
};
|
||||
globDirectory: "build/deploy/",
|
||||
globPatterns: ["**/*.{js,css,woff2,svg}"],
|
||||
globIgnores: ["**/remoteEntry.js"],
|
||||
swSrc: "packages/asc-web-common/sw/template.js",
|
||||
swDest: "build/deploy/public/sw.js",
|
||||
};
|
||||
|
@ -797,3 +797,15 @@ export function checkFillFormDraft(fileId) {
|
||||
data: { fileId },
|
||||
});
|
||||
}
|
||||
|
||||
export function fileCopyAs(fileId, destTitle, destFolderId, enableExternalExt) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `files/file/${fileId}/copyas`,
|
||||
data: {
|
||||
destTitle,
|
||||
destFolderId,
|
||||
enableExternalExt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import IconButton from "@appserver/components/icon-button";
|
||||
|
||||
const CloseButton = (props) => {
|
||||
//console.log("CloseButton render");
|
||||
const { className, isDisabled, onClick } = props;
|
||||
const { className, isDisabled, onClick, isClickable } = props;
|
||||
return (
|
||||
<div className={`styled-close-button ${className}`}>
|
||||
<IconButton
|
||||
@ -17,6 +17,7 @@ const CloseButton = (props) => {
|
||||
isFill={true}
|
||||
isDisabled={isDisabled}
|
||||
onClick={!isDisabled ? onClick : undefined}
|
||||
isClickable={isClickable}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -251,7 +251,7 @@ class FilterItem extends React.Component {
|
||||
isDisabled={isDisabled}
|
||||
isClickable={true}
|
||||
>
|
||||
<CloseButton isDisabled={isDisabled} onClick={this.onClick} />
|
||||
<CloseButton isDisabled={isDisabled} isClickable />
|
||||
</StyledCloseButtonBlock>
|
||||
</StyledFilterItem>
|
||||
);
|
||||
|
@ -67,7 +67,7 @@ const RowLoader = ({ id, className, style, isRectangle, ...rest }) => {
|
||||
/>
|
||||
)}
|
||||
</StyledBox1>
|
||||
<StyledBox2>
|
||||
<StyledBox2 className="row-content">
|
||||
<RectangleLoader
|
||||
className="first-row-content__mobile"
|
||||
title={title}
|
||||
|
11
packages/asc-web-common/sw/helper.js
Normal file
@ -0,0 +1,11 @@
|
||||
import registerSW from "./register";
|
||||
import unregisterSW from "./unregister";
|
||||
|
||||
window.SW = {
|
||||
register: registerSW,
|
||||
unregister: unregisterSW,
|
||||
};
|
||||
|
||||
export { unregisterSW as registerSW, unregisterSW };
|
||||
// TODO: Replace 'unregisterSW as registerSW' to 'registerSW' when sw.js is needed
|
||||
//export { registerSW, unregisterSW };
|
131
packages/asc-web-common/sw/register.js
Normal file
@ -0,0 +1,131 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import { Workbox } from "workbox-window";
|
||||
import SnackBar from "@appserver/components/snackbar";
|
||||
import i18n from "i18next";
|
||||
import { useTranslation, initReactI18next } from "react-i18next";
|
||||
import Backend from "i18next-http-backend";
|
||||
import { LANGUAGE } from "../constants";
|
||||
import { loadLanguagePath } from "../utils";
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || "en",
|
||||
fallbackLng: "en",
|
||||
load: "currentOnly",
|
||||
//debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
backend: {
|
||||
loadPath: loadLanguagePath(""),
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
|
||||
const SnackBarWrapper = (props) => {
|
||||
const { t, ready } = useTranslation("Common", { i18n });
|
||||
|
||||
if (ready) {
|
||||
const barConfig = {
|
||||
parentElementId: "snackbar",
|
||||
text: t("NewVersionAvailable"),
|
||||
btnText: t("Load"),
|
||||
onAction: () => props.onButtonClick(),
|
||||
opacity: 1,
|
||||
countDownTime: 5 * 60 * 1000,
|
||||
};
|
||||
|
||||
return <SnackBar {...barConfig} />;
|
||||
}
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export default function () {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
!("serviceWorker" in navigator)
|
||||
) {
|
||||
console.log("SKIP registerSW because of DEV mode");
|
||||
return;
|
||||
}
|
||||
|
||||
const wb = new Workbox(`/sw.js`);
|
||||
|
||||
const showSkipWaitingPrompt = (event) => {
|
||||
console.log(
|
||||
`A new service worker has installed, but it can't activate` +
|
||||
`until all tabs running the current version have fully unloaded.`
|
||||
);
|
||||
|
||||
function refresh() {
|
||||
wb.addEventListener("controlling", () => {
|
||||
localStorage.removeItem("sw_need_activation");
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
// This will postMessage() to the waiting service worker.
|
||||
wb.messageSkipWaiting();
|
||||
}
|
||||
|
||||
try {
|
||||
const snackbarNode = document.createElement("div");
|
||||
snackbarNode.id = "snackbar";
|
||||
document.body.appendChild(snackbarNode);
|
||||
|
||||
ReactDOM.render(
|
||||
<SnackBarWrapper
|
||||
onButtonClick={() => {
|
||||
snackbarNode.remove();
|
||||
refresh();
|
||||
}}
|
||||
/>,
|
||||
document.getElementById("snackbar")
|
||||
);
|
||||
|
||||
localStorage.setItem("sw_need_activation", true);
|
||||
} catch (e) {
|
||||
console.error("showSkipWaitingPrompt", e);
|
||||
refresh();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", async () => {
|
||||
if (localStorage.getItem("sw_need_activation")) {
|
||||
localStorage.removeItem("sw_need_activation");
|
||||
wb.messageSkipWaiting();
|
||||
}
|
||||
});
|
||||
|
||||
// Add an event listener to detect when the registered
|
||||
// service worker has installed but is waiting to activate.
|
||||
wb.addEventListener("waiting", showSkipWaitingPrompt);
|
||||
|
||||
wb.register()
|
||||
.then((reg) => {
|
||||
console.log("Successful service worker registration", reg);
|
||||
|
||||
if (!window.swUpdateTimer) {
|
||||
console.log("SW timer checks for updates every hour");
|
||||
window.swUpdateTimer = setInterval(() => {
|
||||
console.log("SW update timer check");
|
||||
reg.update().catch((e) => {
|
||||
console.error("SW update timer FAILED", e);
|
||||
});
|
||||
}, 60 * 60 * 1000);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.error("Service worker registration failed", err));
|
||||
}
|
55
packages/asc-web-common/sw/unregister.js
Normal file
@ -0,0 +1,55 @@
|
||||
function clearCaches() {
|
||||
try {
|
||||
caches?.keys()?.then(function (keyList) {
|
||||
return Promise.all(
|
||||
keyList.map(function (key) {
|
||||
if (
|
||||
key.startsWith("workbox-") ||
|
||||
key.startsWith("wb6-") ||
|
||||
key.startsWith("appserver-")
|
||||
) {
|
||||
return caches.delete(key);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("clearCaches failed", error);
|
||||
}
|
||||
}
|
||||
export default function () {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
!("serviceWorker" in navigator)
|
||||
) {
|
||||
console.log("SKIP registerSW because of DEV mode");
|
||||
return;
|
||||
}
|
||||
|
||||
clearCaches();
|
||||
|
||||
return navigator.serviceWorker
|
||||
.getRegistrations()
|
||||
.then(function (registrations) {
|
||||
for (let registration of registrations) {
|
||||
registration
|
||||
.unregister()
|
||||
.then(function () {
|
||||
return self.clients?.matchAll() || [];
|
||||
})
|
||||
.then(function (clients) {
|
||||
clients.forEach((client) => {
|
||||
if (client.url && "navigate" in client) {
|
||||
client.navigate(client.url);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import { Workbox } from "workbox-window";
|
||||
import SnackBar from "@appserver/components/snackbar";
|
||||
import i18n from "i18next";
|
||||
import { useTranslation, initReactI18next } from "react-i18next";
|
||||
import Backend from "i18next-http-backend";
|
||||
import { LANGUAGE } from "../constants";
|
||||
import { loadLanguagePath } from "./";
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || "en",
|
||||
fallbackLng: "en",
|
||||
load: "currentOnly",
|
||||
//debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
backend: {
|
||||
loadPath: loadLanguagePath(""),
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
|
||||
const SnackBarWrapper = (props) => {
|
||||
const { t, ready } = useTranslation("Common", { i18n });
|
||||
|
||||
if (ready) {
|
||||
const barConfig = {
|
||||
parentElementId: "snackbar",
|
||||
text: t("NewVersionAvailable"),
|
||||
btnText: t("Load"),
|
||||
onAction: () => props.onButtonClick(),
|
||||
opacity: 1,
|
||||
countDownTime: 5 * 60 * 1000,
|
||||
};
|
||||
|
||||
return <SnackBar {...barConfig} />;
|
||||
}
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const registerSW = () => {
|
||||
return; //TODO: Enable service-worker after fix of infinite reloading (Bug 53063)
|
||||
|
||||
/*
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
const wb = new Workbox(`/sw.js`);
|
||||
|
||||
const showSkipWaitingPrompt = (event) => {
|
||||
console.log(
|
||||
`A new service worker has installed, but it can't activate` +
|
||||
`until all tabs running the current version have fully unloaded.`
|
||||
);
|
||||
|
||||
function refresh() {
|
||||
wb.addEventListener("controlling", () => {
|
||||
localStorage.removeItem("sw_need_activation");
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
// This will postMessage() to the waiting service worker.
|
||||
wb.messageSkipWaiting();
|
||||
}
|
||||
|
||||
try {
|
||||
const snackbarNode = document.createElement("div");
|
||||
snackbarNode.id = "snackbar";
|
||||
document.body.appendChild(snackbarNode);
|
||||
|
||||
ReactDOM.render(
|
||||
<SnackBarWrapper
|
||||
onButtonClick={() => {
|
||||
snackbarNode.remove();
|
||||
refresh();
|
||||
}}
|
||||
/>,
|
||||
document.getElementById("snackbar")
|
||||
);
|
||||
|
||||
localStorage.setItem("sw_need_activation", true);
|
||||
} catch (e) {
|
||||
console.error("showSkipWaitingPrompt", e);
|
||||
refresh();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", async () => {
|
||||
if (localStorage.getItem("sw_need_activation")) {
|
||||
localStorage.removeItem("sw_need_activation");
|
||||
wb.messageSkipWaiting();
|
||||
}
|
||||
});
|
||||
|
||||
// Add an event listener to detect when the registered
|
||||
// service worker has installed but is waiting to activate.
|
||||
wb.addEventListener("waiting", showSkipWaitingPrompt);
|
||||
|
||||
wb.register()
|
||||
.then((reg) => {
|
||||
console.log("Successful service worker registration", reg);
|
||||
|
||||
if (!window.swUpdateTimer) {
|
||||
console.log("SW timer checks for updates every hour");
|
||||
window.swUpdateTimer = setInterval(() => {
|
||||
console.log("SW update timer check");
|
||||
reg.update().catch((e) => {
|
||||
console.error("SW update timer FAILED", e);
|
||||
});
|
||||
}, 60 * 60 * 1000);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.error("Service worker registration failed", err));
|
||||
} else {
|
||||
console.log("SKIP registerSW because of DEV mode");
|
||||
}
|
||||
|
||||
*/
|
||||
};
|
||||
|
||||
window.SW = {
|
||||
registerSW: registerSW,
|
||||
};
|
||||
|
||||
export { registerSW };
|
@ -28,6 +28,8 @@ const Content = styled.div`
|
||||
props.displayType === "modal"
|
||||
? props.theme.modalDialog.content.modalPadding
|
||||
: props.theme.modalDialog.content.asidePadding};
|
||||
border-radius: ${(props) =>
|
||||
props.theme.modalDialog.content.modalBorderRadius};
|
||||
|
||||
.heading {
|
||||
max-width: ${(props) => props.theme.modalDialog.content.heading.maxWidth};
|
||||
@ -73,7 +75,7 @@ const CloseButton = styled(CrossSidebarIcon)`
|
||||
|
||||
&:hover {
|
||||
path {
|
||||
fill: ${(props) => props.theme.modalDialog.closeButton.hoverColor};
|
||||
stroke: ${(props) => props.theme.modalDialog.closeButton.hoverColor};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -492,6 +492,7 @@ const Base = {
|
||||
content: {
|
||||
backgroundColor: white,
|
||||
modalPadding: "0 12px 12px",
|
||||
modalBorderRadius: "6px",
|
||||
asidePadding: "0 16px 16px",
|
||||
heading: {
|
||||
maxWidth: "500px",
|
||||
@ -509,13 +510,13 @@ const Base = {
|
||||
},
|
||||
|
||||
closeButton: {
|
||||
width: "17px",
|
||||
height: "17px",
|
||||
minWidth: "17px",
|
||||
minHeight: "17px",
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
|
||||
right: "16px",
|
||||
top: "11px",
|
||||
top: "13px",
|
||||
hoverColor: grayMain,
|
||||
},
|
||||
},
|
||||
@ -758,10 +759,10 @@ const Base = {
|
||||
span: { maxWidth: "300px" },
|
||||
|
||||
caret: {
|
||||
width: "8px",
|
||||
minWidth: "8px",
|
||||
height: "8px",
|
||||
minHeight: "8px",
|
||||
width: "5px",
|
||||
minWidth: "5px",
|
||||
height: "4px",
|
||||
minHeight: "4px",
|
||||
marginLeft: "5px",
|
||||
marginTop: "-4px",
|
||||
right: "6px",
|
||||
|
@ -458,6 +458,7 @@ const Dark = {
|
||||
content: {
|
||||
backgroundColor: white,
|
||||
padding: "0 16px 16px",
|
||||
modalBorderRadius: "6px",
|
||||
|
||||
heading: {
|
||||
maxWidth: "500px",
|
||||
@ -472,13 +473,13 @@ const Dark = {
|
||||
},
|
||||
|
||||
closeButton: {
|
||||
width: "17px",
|
||||
height: "17px",
|
||||
minWidth: "17px",
|
||||
minHeight: "17px",
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
|
||||
right: "16px",
|
||||
top: "19px",
|
||||
top: "13px",
|
||||
hoverColor: grayMain,
|
||||
},
|
||||
},
|
||||
@ -719,10 +720,10 @@ const Dark = {
|
||||
span: { maxWidth: "300px" },
|
||||
|
||||
caret: {
|
||||
width: "8px",
|
||||
minWidth: "8px",
|
||||
height: "8px",
|
||||
minHeight: "8px",
|
||||
width: "5px",
|
||||
minWidth: "5px",
|
||||
height: "4px",
|
||||
minHeight: "4px",
|
||||
marginLeft: "5px",
|
||||
marginTop: "-4px",
|
||||
right: "6px",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.CRM/client && shx cp -r dist/* ../../../build/deploy/products/ASC.CRM/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.CRM/client && shx cp -r dist/* ../../../build/deploy/products/ASC.CRM/client",
|
||||
"serve": "serve dist -p 5014",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5014"
|
||||
|
2
products/ASC.CRM/Client/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.Calendar/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Calendar/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.Calendar/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Calendar/client",
|
||||
"serve": "serve dist -p 5017",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5017"
|
||||
|
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.Files/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Files/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.Files/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Files/client",
|
||||
"serve": "serve dist -p 5008",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5008"
|
||||
|
@ -4,10 +4,5 @@
|
||||
"NewPresentation": "New Presentation",
|
||||
"NewSpreadsheet": "New Spreadsheet",
|
||||
"UploadFiles": "Upload files",
|
||||
"UploadFolder": "Upload folder",
|
||||
"NewForm": "Master form",
|
||||
"NewFormFile": "Master form from file",
|
||||
"CreateMasterFormFromFile": "Create Master Form from file",
|
||||
"SubNewForm": "From blank",
|
||||
"SubNewFormFile": "From an existing text file"
|
||||
"UploadFolder": "Upload folder"
|
||||
}
|
||||
|
@ -40,5 +40,10 @@
|
||||
"TypeTitleSharePoint": "SharePoint",
|
||||
"TypeTitleSkyDrive": "OneDrive",
|
||||
"TypeTitleWebDav": "WebDAV",
|
||||
"TypeTitleYandex": "Yandex.Disk"
|
||||
"TypeTitleYandex": "Yandex.Disk",
|
||||
"NewForm": "Master form",
|
||||
"NewFormFile": "Master form from file",
|
||||
"CreateMasterFormFromFile": "Create Master Form from file",
|
||||
"SubNewForm": "From blank",
|
||||
"SubNewFormFile": "From an existing text file"
|
||||
}
|
||||
|
@ -20,6 +20,16 @@ export default function withContextOptions(WrappedComponent) {
|
||||
return this.gotoDocEditor(false);
|
||||
};
|
||||
|
||||
onClickMakeForm = () => {
|
||||
const { copyAsAction, item, formfillingDocs } = this.props;
|
||||
const { title, id, folderId, fileExst } = item;
|
||||
|
||||
const newTitle =
|
||||
title.substring(0, title.length - fileExst.length) + formfillingDocs[0];
|
||||
|
||||
copyAsAction(id, newTitle, folderId).catch((err) => toastr.error(err));
|
||||
};
|
||||
|
||||
onOpenLocation = () => {
|
||||
const { item, openLocationAction } = this.props;
|
||||
const { parentId, folderId, fileExst } = item;
|
||||
@ -376,6 +386,14 @@ export default function withContextOptions(WrappedComponent) {
|
||||
onClick: this.onClickLinkFillForm,
|
||||
disabled: false,
|
||||
};
|
||||
case "make-form":
|
||||
return {
|
||||
key: option,
|
||||
label: t("Common:MakeForm"),
|
||||
icon: "/static/images/form.plus.react.svg",
|
||||
onClick: this.onClickMakeForm,
|
||||
disabled: false,
|
||||
};
|
||||
case "edit":
|
||||
return {
|
||||
key: option,
|
||||
@ -533,45 +551,48 @@ export default function withContextOptions(WrappedComponent) {
|
||||
return inject(
|
||||
(
|
||||
{
|
||||
filesStore,
|
||||
filesActionsStore,
|
||||
auth,
|
||||
versionHistoryStore,
|
||||
mediaViewerDataStore,
|
||||
dialogsStore,
|
||||
filesActionsStore,
|
||||
filesStore,
|
||||
mediaViewerDataStore,
|
||||
treeFoldersStore,
|
||||
uploadDataStore,
|
||||
versionHistoryStore,
|
||||
},
|
||||
{ item }
|
||||
) => {
|
||||
const { openDocEditor, fileActionStore } = filesStore;
|
||||
const { openDocEditor, fileActionStore, formatsStore } = filesStore;
|
||||
const {
|
||||
openLocationAction,
|
||||
finalizeVersionAction,
|
||||
setFavoriteAction,
|
||||
lockFileAction,
|
||||
deleteItemAction,
|
||||
downloadAction,
|
||||
duplicateAction,
|
||||
setThirdpartyInfo,
|
||||
onSelectItem,
|
||||
deleteItemAction,
|
||||
finalizeVersionAction,
|
||||
lockFileAction,
|
||||
markAsRead,
|
||||
onSelectItem,
|
||||
openLocationAction,
|
||||
setFavoriteAction,
|
||||
setThirdpartyInfo,
|
||||
unsubscribeAction,
|
||||
} = filesActionsStore;
|
||||
const {
|
||||
setChangeOwnerPanelVisible,
|
||||
setMoveToPanelVisible,
|
||||
setCopyPanelVisible,
|
||||
setDownloadDialogVisible,
|
||||
setRemoveItem,
|
||||
setDeleteThirdPartyDialogVisible,
|
||||
setSharingPanelVisible,
|
||||
setDeleteDialogVisible,
|
||||
setDeleteThirdPartyDialogVisible,
|
||||
setDownloadDialogVisible,
|
||||
setMoveToPanelVisible,
|
||||
setRemoveItem,
|
||||
setSharingPanelVisible,
|
||||
setUnsubscribe,
|
||||
} = dialogsStore;
|
||||
const { isTabletView, isDesktopClient } = auth.settingsStore;
|
||||
const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore;
|
||||
const { setAction, type, extension, id } = fileActionStore;
|
||||
const { setMediaViewerData } = mediaViewerDataStore;
|
||||
const { copyAsAction } = uploadDataStore;
|
||||
const { formfillingDocs } = formatsStore.docserviceStore;
|
||||
|
||||
const { isRecycleBinFolder, isShare } = treeFoldersStore;
|
||||
const isShareFolder = isShare(item.rootFolderType);
|
||||
@ -610,6 +631,8 @@ export default function withContextOptions(WrappedComponent) {
|
||||
setDeleteDialogVisible,
|
||||
setUnsubscribe,
|
||||
isDesktop: isDesktopClient,
|
||||
copyAsAction,
|
||||
formfillingDocs,
|
||||
};
|
||||
}
|
||||
)(observer(WithContextOptions));
|
||||
|
2
products/ASC.Files/Client/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -30,7 +30,7 @@ class ArticleBodyContent extends React.Component {
|
||||
} = this.props;
|
||||
|
||||
setSelectedNode(data);
|
||||
hideArticle(false);
|
||||
hideArticle();
|
||||
setIsLoading(true);
|
||||
// const selectedFolderTitle =
|
||||
// (e.node && e.node.props && e.node.props.title) || null;
|
||||
|
@ -25,7 +25,8 @@ class ArticleMainButtonContent extends React.Component {
|
||||
};
|
||||
|
||||
onShowSelectFileDialog = () => {
|
||||
const { setSelectFileDialogVisible } = this.props;
|
||||
const { setSelectFileDialogVisible, hideArticle } = this.props;
|
||||
hideArticle();
|
||||
setSelectFileDialogVisible(true);
|
||||
};
|
||||
|
||||
@ -96,17 +97,17 @@ class ArticleMainButtonContent extends React.Component {
|
||||
{
|
||||
className: "main-button_drop-down",
|
||||
icon: "images/form.react.svg",
|
||||
label: t("NewForm"),
|
||||
label: t("Translations:NewForm"),
|
||||
items: [
|
||||
{
|
||||
className: "main-button_drop-down_sub",
|
||||
label: t("SubNewForm"),
|
||||
label: t("Translations:SubNewForm"),
|
||||
onClick: this.onCreate,
|
||||
action: "docxf",
|
||||
},
|
||||
{
|
||||
className: "main-button_drop-down_sub",
|
||||
label: t("SubNewFormFile"),
|
||||
label: t("Translations:SubNewFormFile"),
|
||||
onClick: this.onShowSelectFileDialog,
|
||||
},
|
||||
],
|
||||
@ -116,14 +117,14 @@ class ArticleMainButtonContent extends React.Component {
|
||||
{
|
||||
className: "main-button_drop-down_sub",
|
||||
icon: "images/form.react.svg",
|
||||
label: t("NewForm"),
|
||||
label: t("Translations:NewForm"),
|
||||
onClick: this.onCreate,
|
||||
action: "docxf",
|
||||
},
|
||||
{
|
||||
className: "main-button_drop-down_sub",
|
||||
icon: "images/form.file.react.svg",
|
||||
label: t("NewFormFile"),
|
||||
label: t("Translations:NewFormFile"),
|
||||
onClick: this.onShowSelectFileDialog,
|
||||
},
|
||||
];
|
||||
@ -208,11 +209,12 @@ ArticleMainButtonContent.propTypes = {
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ filesStore, uploadDataStore, treeFoldersStore, dialogsStore }) => {
|
||||
({ auth, filesStore, uploadDataStore, treeFoldersStore, dialogsStore }) => {
|
||||
const { firstLoad, fileActionStore, filter, canCreate } = filesStore;
|
||||
const { isPrivacyFolder } = treeFoldersStore;
|
||||
const { startUpload } = uploadDataStore;
|
||||
const { setSelectFileDialogVisible } = dialogsStore;
|
||||
const { hideArticle } = auth.settingsStore;
|
||||
return {
|
||||
homepage: config.homepage,
|
||||
firstLoad,
|
||||
@ -223,11 +225,12 @@ export default inject(
|
||||
setAction: fileActionStore.setAction,
|
||||
startUpload,
|
||||
setSelectFileDialogVisible,
|
||||
hideArticle,
|
||||
};
|
||||
}
|
||||
)(
|
||||
withRouter(
|
||||
withTranslation(["Article", "Common"])(
|
||||
withTranslation(["Article", "Common", "Translations"])(
|
||||
withLoader(observer(ArticleMainButtonContent))(<Loaders.MainButton />)
|
||||
)
|
||||
)
|
||||
|
@ -38,7 +38,10 @@ const EmptyFolderContainer = ({
|
||||
{t("Spreadsheet")},
|
||||
</Link>
|
||||
<Link data-format="pptx" onClick={onCreate} {...linkStyles}>
|
||||
{t("Presentation")}
|
||||
{t("Presentation")},
|
||||
</Link>
|
||||
<Link data-format="docxf" onClick={onCreate} {...linkStyles}>
|
||||
{t("Translations:NewForm")}
|
||||
</Link>
|
||||
</Box>
|
||||
</div>
|
||||
@ -88,4 +91,4 @@ export default inject(({ filesStore, selectedFolderStore }) => {
|
||||
setIsLoading: filesStore.setIsLoading,
|
||||
parentId: selectedFolderStore.parentId,
|
||||
};
|
||||
})(withTranslation("Home")(observer(EmptyFolderContainer)));
|
||||
})(withTranslation(["Home", "Translations"])(observer(EmptyFolderContainer)));
|
||||
|
@ -45,7 +45,7 @@ const Panels = (props) => {
|
||||
setSelectFileDialogVisible,
|
||||
} = props;
|
||||
|
||||
const { t } = useTranslation(["Article", "SelectFile"]);
|
||||
const { t } = useTranslation(["Translations", "SelectFile"]);
|
||||
|
||||
const onClose = () => {
|
||||
setSelectFileDialogVisible(false);
|
||||
@ -92,7 +92,7 @@ const Panels = (props) => {
|
||||
foldersType="exceptPrivacyTrashFolders"
|
||||
ByExtension
|
||||
searchParam={"docx"}
|
||||
headerName={t("Article:CreateMasterFormFromFile")}
|
||||
headerName={t("Translations:CreateMasterFormFromFile")}
|
||||
titleFilesList={t("SelectFile:SelectDOCXFormat")}
|
||||
creationButtonPrimary
|
||||
/>
|
||||
|
@ -134,7 +134,7 @@ class DeleteDialogComponent extends React.Component {
|
||||
? t("Common:Confirmation")
|
||||
: unsubscribe
|
||||
? t("UnsubscribeTitle")
|
||||
: checkedSelections.length === 1 || isPrivacyFolder
|
||||
: checkedSelections.length === 1
|
||||
? checkedSelections[0].fileExst
|
||||
? t("MoveToTrashOneFileTitle")
|
||||
: t("MoveToTrashOneFolderTitle")
|
||||
@ -142,7 +142,7 @@ class DeleteDialogComponent extends React.Component {
|
||||
|
||||
const noteText = unsubscribe
|
||||
? t("UnsubscribeNote")
|
||||
: checkedSelections.length === 1 || isPrivacyFolder
|
||||
: checkedSelections.length === 1
|
||||
? checkedSelections[0].fileExst
|
||||
? t("MoveToTrashOneFileNote")
|
||||
: personal
|
||||
|
@ -107,6 +107,7 @@ const SelectFileDialogAsideView = ({
|
||||
<Loaders.Rows
|
||||
style={{
|
||||
marginBottom: "24px",
|
||||
marginTop: "20px",
|
||||
}}
|
||||
count={12}
|
||||
/>
|
||||
|
@ -79,9 +79,10 @@ const FilesListBody = ({
|
||||
>
|
||||
<Loaders.Rows
|
||||
style={{
|
||||
marginBottom: displayType === "aside" ? "24px" : "19px",
|
||||
marginBottom: displayType === "aside" ? "24px" : "26px",
|
||||
marginTop: displayType === "aside" ? "8px" : "10px",
|
||||
}}
|
||||
count={displayType === "aside" ? 12 : 7}
|
||||
count={displayType === "aside" ? 12 : 5}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,7 +103,7 @@ const FilesListBody = ({
|
||||
const isLoaded = isItemLoaded(index);
|
||||
|
||||
if (!isLoaded) {
|
||||
if (countLoad > 1) return renderPageLoader(style);
|
||||
if (countLoad >= 1) return renderPageLoader(style);
|
||||
return renderFirstLoader(style);
|
||||
}
|
||||
|
||||
@ -156,7 +157,7 @@ const FilesListBody = ({
|
||||
<List
|
||||
height={displayType === "aside" ? height : listHeight}
|
||||
itemCount={itemCount}
|
||||
itemSize={displayType === "aside" ? 56 : 41}
|
||||
itemSize={displayType === "aside" ? 56 : 50}
|
||||
onItemsRendered={onItemsRendered}
|
||||
ref={ref}
|
||||
width={width + 8}
|
||||
|
@ -233,6 +233,7 @@ class SelectFileDialogModalView extends React.Component {
|
||||
selectedFile={selectedFile}
|
||||
listHeight={isHeaderChildren ? 260 : 303}
|
||||
onSetLoadingData={this.onSetLoadingData}
|
||||
displayType={"modal"}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -31,7 +31,7 @@ class SelectFileDialogBody extends React.Component {
|
||||
filter,
|
||||
creationButtonPrimary,
|
||||
t,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
this.buttonName = creationButtonPrimary
|
||||
? t("Common:Create")
|
||||
@ -384,9 +384,9 @@ const SelectFileDialogWrapper = inject(
|
||||
|
||||
const { setSelectedNode, setExpandedPanelKeys } = treeFoldersStore;
|
||||
const { filter } = filesStore;
|
||||
const { setSelectedFolder } = selectedFolderStore;
|
||||
const { setSelectedFolder, id } = selectedFolderStore;
|
||||
return {
|
||||
storeFolderId,
|
||||
storeFolderId: storeFolderId || id,
|
||||
fileInfo,
|
||||
setFile,
|
||||
setFolderId,
|
||||
|
@ -130,15 +130,6 @@ class SharingRow extends React.Component {
|
||||
];
|
||||
|
||||
const externalLinkOptions = [
|
||||
{
|
||||
key: "linkItem_0",
|
||||
label: t("CopyExternalLink"),
|
||||
onClick: this.onCopyClick,
|
||||
},
|
||||
{
|
||||
key: "linkItem_1",
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
key: "linkItem_2",
|
||||
label: `${t("ShareVia")} e-mail`,
|
||||
@ -181,6 +172,7 @@ class SharingRow extends React.Component {
|
||||
externalLinkData={externalLinkData}
|
||||
onToggleLink={onToggleLink}
|
||||
withToggle
|
||||
onCopyLink={this.onCopyClick}
|
||||
{...this.props}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
import Row from "@appserver/components/row";
|
||||
import LinkWithDropdown from "@appserver/components/link-with-dropdown";
|
||||
import ToggleButton from "@appserver/components/toggle-button";
|
||||
@ -7,6 +7,7 @@ import { StyledLinkRow } from "../StyledPanels";
|
||||
import AccessComboBox from "./AccessComboBox";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
import AccessEditIcon from "../../../../../../../public/images/access.edit.react.svg";
|
||||
import CopyIcon from "../../../../../../../public/images/copy.react.svg";
|
||||
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
|
||||
|
||||
const StyledAccessEditIcon = styled(AccessEditIcon)`
|
||||
@ -16,6 +17,19 @@ const StyledAccessEditIcon = styled(AccessEditIcon)`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCopyIcon = styled(CopyIcon)`
|
||||
${commonIconsStyles}
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
${(props) =>
|
||||
props.isDisabled &&
|
||||
css`
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
`}
|
||||
`;
|
||||
|
||||
class LinkRow extends React.Component {
|
||||
onToggleButtonChange = () => {
|
||||
const { onToggleLink, item } = this.props;
|
||||
@ -34,6 +48,7 @@ class LinkRow extends React.Component {
|
||||
externalAccessOptions,
|
||||
onChangeItemAccess,
|
||||
isLoading,
|
||||
onCopyLink,
|
||||
} = this.props;
|
||||
|
||||
const isChecked = item.access !== ShareAccessRights.DenyAccess;
|
||||
@ -71,17 +86,27 @@ class LinkRow extends React.Component {
|
||||
contextButtonSpacerWidth="0px"
|
||||
>
|
||||
<>
|
||||
<LinkWithDropdown
|
||||
className="sharing_panel-link"
|
||||
color="#333"
|
||||
dropdownType="alwaysDashed"
|
||||
data={options}
|
||||
fontSize="14px"
|
||||
fontWeight={600}
|
||||
isDisabled={isDisabled}
|
||||
>
|
||||
{linkText}
|
||||
</LinkWithDropdown>
|
||||
<div className="sharing_panel-link-container">
|
||||
<LinkWithDropdown
|
||||
className="sharing_panel-link"
|
||||
color="#333"
|
||||
dropdownType="alwaysDashed"
|
||||
data={options}
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
isDisabled={isDisabled}
|
||||
>
|
||||
{linkText}
|
||||
</LinkWithDropdown>
|
||||
{onCopyLink && (
|
||||
<StyledCopyIcon
|
||||
isDisabled={isDisabled}
|
||||
size="medium"
|
||||
onClick={onCopyLink}
|
||||
title={t("CopyExternalLink")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{withToggle && (
|
||||
<div>
|
||||
<ToggleButton
|
||||
|
@ -572,6 +572,24 @@ const StyledLinkRow = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.sharing_panel-link-container {
|
||||
display: flex;
|
||||
|
||||
.sharing_panel-link {
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
${(props) =>
|
||||
props.isDisabled &&
|
||||
css`
|
||||
:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
`};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.link-row {
|
||||
${(props) => !props.withToggle && "border-bottom:none;"}
|
||||
}
|
||||
@ -641,6 +659,16 @@ const StyledSelectFolderPanel = styled.div`
|
||||
.nav-thumb-horizontal {
|
||||
height: 0px !important;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.displayType === "modal" &&
|
||||
css`
|
||||
.nav-thumb-vertical {
|
||||
margin-left: 4px !important;
|
||||
width: 4px !important;
|
||||
}
|
||||
`}
|
||||
|
||||
.scroll-body {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
@ -673,6 +701,15 @@ const StyledSelectFilePanel = styled.div`
|
||||
margin-left: -7px !important;
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.displayType === "modal" &&
|
||||
css`
|
||||
.nav-thumb-vertical {
|
||||
margin-left: 4px !important;
|
||||
width: 4px !important;
|
||||
}
|
||||
`}
|
||||
}
|
||||
.select-file-dialog_aside_body-files_list {
|
||||
height: 100%;
|
||||
@ -724,14 +761,24 @@ const StyledSelectFilePanel = styled.div`
|
||||
padding: 7px 0px;
|
||||
}
|
||||
.panel-loader-wrapper {
|
||||
${(props) =>
|
||||
props.displayType === "modal" &&
|
||||
css`
|
||||
margin-top: 16px;
|
||||
`};
|
||||
.first-row-content__mobile {
|
||||
width: ${(props) => (props.displayType === "aside" ? "147px" : "402px")};
|
||||
width: ${(props) => (props.displayType === "aside" ? "147px" : "234px")};
|
||||
height: ${(props) => (props.displayType === "aside" ? "16px" : "10px")};
|
||||
}
|
||||
|
||||
@media ${desktop} {
|
||||
.second-row-content__mobile {
|
||||
max-width: 185px;
|
||||
height: 8px;
|
||||
display: block;
|
||||
}
|
||||
.row-content {
|
||||
grid-template-rows: 10px;
|
||||
grid-row-gap: 6px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
}
|
||||
|
||||
.second-row-content__mobile {
|
||||
width: 229px;
|
||||
}
|
||||
@ -759,7 +806,7 @@ const StyledSelectFilePanel = styled.div`
|
||||
|
||||
.modal-dialog_body {
|
||||
display: grid;
|
||||
grid-template-columns: 212px 493px;
|
||||
grid-template-columns: 228px 477px;
|
||||
height: 295px;
|
||||
grid-template-areas: "tree files-list";
|
||||
.modal-dialog_tree-body {
|
||||
@ -805,14 +852,20 @@ const StyledFilesList = styled.div`
|
||||
}
|
||||
|
||||
.files-list_file-owner {
|
||||
max-width: 213px;
|
||||
max-width: ${(props) =>
|
||||
props.displayType === "aside" ? "213px" : "406px"};
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #a3a9ae;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
${(props) => props.displayType === "modal" && ` font-size: 11px;`}
|
||||
|
||||
height: ${(props) => (props.displayType === "aside" ? "16px" : "12px")};
|
||||
padding-bottom: ${(props) =>
|
||||
props.displayType === "aside" ? "10px" : "11px"};
|
||||
}
|
||||
.file-exst {
|
||||
color: #a3a9ae;
|
||||
font-weight: 600;
|
||||
@ -824,52 +877,46 @@ const StyledFilesList = styled.div`
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
max-width: ${(props) =>
|
||||
props.displayType === "aside" ? "213px" : "274px"};
|
||||
max-width: ${(props) => props.displayType === "aside" && "213px"};
|
||||
|
||||
grid-area: full-name;
|
||||
display: flex;
|
||||
${(props) =>
|
||||
props.displayType === "aside" &&
|
||||
css`
|
||||
padding-top: 4px;
|
||||
`}
|
||||
padding-top: 10px;
|
||||
}
|
||||
.select-file-dialog_icon {
|
||||
grid-area: icon-name;
|
||||
padding-top: 12px;
|
||||
}
|
||||
.select-file-dialog_checked {
|
||||
grid-area: checked-button;
|
||||
}
|
||||
.files-list_file-children_wrapper {
|
||||
grid-area: owner-name;
|
||||
margin-right: 12px;
|
||||
${(props) =>
|
||||
props.displayType === "aside" &&
|
||||
css`
|
||||
margin-top: -17px;
|
||||
`}
|
||||
margin-top: ${(props) => props.displayType === "modal" && "-8px"};
|
||||
}
|
||||
.modal-dialog_file-name {
|
||||
border-radius: 3px;
|
||||
padding-right: 12px;
|
||||
${(props) => props.isChecked && `background:#F8F9F9;`}
|
||||
cursor: ${(props) => (props.needRowSelection ? "pointer" : "default")};
|
||||
border-bottom: 1px solid #eceef1;
|
||||
align-items: center;
|
||||
display: grid;
|
||||
${(props) =>
|
||||
props.displayType === "aside"
|
||||
? css`
|
||||
height: 56px;
|
||||
grid-template-areas: "checked-button icon-name full-name full-name" "checked-button icon-name owner-name owner-name";
|
||||
grid-template-areas: "checked-button icon-name full-name" "checked-button icon-name owner-name";
|
||||
`
|
||||
: css`
|
||||
height: 41px;
|
||||
grid-template-areas: "checked-button icon-name full-name owner-name";
|
||||
height: 49px;
|
||||
grid-template-areas: "checked-button icon-name full-name" "checked-button icon-name owner-name";
|
||||
`}
|
||||
grid-template-columns: 22px 33px 1fr;
|
||||
${(props) => props.displayType === "modal" && ` grid-row-gap: 4px;`}
|
||||
|
||||
padding-left: ${(props) =>
|
||||
props.displayType === "aside" ? "16px" : "12px"};
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -879,6 +926,9 @@ const StyledModalRowContainer = styled.div`
|
||||
min-height: 47px;
|
||||
|
||||
.link-row__container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 41px;
|
||||
width: 100%;
|
||||
|
||||
.link-row {
|
||||
|
@ -174,6 +174,13 @@ class SectionHeaderContent extends React.Component {
|
||||
|
||||
createPresentation = () => this.onCreate("pptx");
|
||||
|
||||
createForm = () => this.onCreate("docxf");
|
||||
|
||||
createFormFromFile = () => {
|
||||
const { setSelectFileDialogVisible } = this.props;
|
||||
setSelectFileDialogVisible(true);
|
||||
};
|
||||
|
||||
createFolder = () => this.onCreate();
|
||||
|
||||
uploadToFolder = () => console.log("Upload To Folder click");
|
||||
@ -197,6 +204,14 @@ class SectionHeaderContent extends React.Component {
|
||||
label: t("NewPresentation"),
|
||||
onClick: this.createPresentation,
|
||||
},
|
||||
{
|
||||
label: t("Translations:NewForm"),
|
||||
onClick: this.createForm,
|
||||
},
|
||||
{
|
||||
label: t("Translations:NewFormFile"),
|
||||
onClick: this.createFormFromFile,
|
||||
},
|
||||
{
|
||||
key: "new-folder",
|
||||
label: t("NewFolder"),
|
||||
@ -522,6 +537,7 @@ export default inject(
|
||||
setCopyPanelVisible,
|
||||
setDeleteDialogVisible,
|
||||
setEmptyTrashDialogVisible,
|
||||
setSelectFileDialogVisible,
|
||||
} = dialogsStore;
|
||||
|
||||
const { isRecycleBinFolder } = treeFoldersStore;
|
||||
@ -557,6 +573,7 @@ export default inject(
|
||||
downloadAction,
|
||||
getHeaderMenu,
|
||||
getCheckboxItemLabel,
|
||||
setSelectFileDialogVisible,
|
||||
|
||||
isRecycleBinFolder,
|
||||
setEmptyTrashDialogVisible,
|
||||
|
@ -285,7 +285,7 @@ class PureHome extends React.Component {
|
||||
hideAside={
|
||||
!!fileActionId ||
|
||||
primaryProgressDataVisible ||
|
||||
secondaryProgressDataStoreVisible
|
||||
secondaryProgressDataStoreVisible //TODO: use hideArticle action
|
||||
}
|
||||
isLoaded={!firstLoad}
|
||||
isHeaderVisible={isHeaderVisible}
|
||||
|
@ -489,12 +489,15 @@ class FilesStore {
|
||||
const shouldFillForm = canFormFillingDocs(item.fileExst);
|
||||
const shouldEdit = !shouldFillForm && canWebEdit(item.fileExst);
|
||||
const shouldView = canViewedDocs(item.fileExst);
|
||||
const isMasterForm = item.fileExst === ".docxf";
|
||||
|
||||
let fileOptions = [
|
||||
//"open",
|
||||
"fill-form",
|
||||
"edit",
|
||||
"preview",
|
||||
"view",
|
||||
"make-form",
|
||||
"separator0",
|
||||
"sharing-settings",
|
||||
"external-link",
|
||||
@ -525,6 +528,9 @@ class FilesStore {
|
||||
"delete",
|
||||
];
|
||||
|
||||
if (!isMasterForm)
|
||||
fileOptions = this.removeOptions(fileOptions, ["make-form"]);
|
||||
|
||||
if (!shouldFillForm)
|
||||
fileOptions = this.removeOptions(fileOptions, ["fill-form"]);
|
||||
|
||||
@ -631,11 +637,13 @@ class FilesStore {
|
||||
|
||||
if (isRecycleBinFolder) {
|
||||
fileOptions = this.removeOptions(fileOptions, [
|
||||
"fill-form",
|
||||
"open",
|
||||
"open-location",
|
||||
"view",
|
||||
"preview",
|
||||
"edit",
|
||||
"make-form",
|
||||
"link-for-portal-users",
|
||||
"sharing-settings",
|
||||
"external-link",
|
||||
@ -1514,7 +1522,7 @@ class FilesStore {
|
||||
|
||||
if (webComment) AccessOptions.push("Comment");
|
||||
if (webReview) AccessOptions.push("Review");
|
||||
if (formFillingDocs) AccessOptions.push("FormFilling");
|
||||
if (formFillingDocs && !externalAccess) AccessOptions.push("FormFilling");
|
||||
if (webFilter) AccessOptions.push("FilterEditing");
|
||||
|
||||
return AccessOptions;
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
getFileConversationProgress,
|
||||
copyToFolder,
|
||||
moveToFolder,
|
||||
fileCopyAs,
|
||||
} from "@appserver/common/api/files";
|
||||
|
||||
class UploadDataStore {
|
||||
@ -919,6 +920,18 @@ class UploadDataStore {
|
||||
});
|
||||
};
|
||||
|
||||
copyAsAction = (fileId, title, folderId, enableExternalExt) => {
|
||||
const { fetchFiles, filter } = this.filesStore;
|
||||
|
||||
return fileCopyAs(fileId, title, folderId, enableExternalExt)
|
||||
.then(() => {
|
||||
fetchFiles(folderId, filter, true, true);
|
||||
})
|
||||
.catch((err) => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
itemOperationToFolder = (data) => {
|
||||
const {
|
||||
destFolderId,
|
||||
|
@ -462,18 +462,18 @@ namespace ASC.Files.Core.Security
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.FileEntryType == FileEntryType.File
|
||||
&& file.IsFillFormDraft)
|
||||
{
|
||||
e.Access = FileShare.FillForms;
|
||||
//if (e.FileEntryType == FileEntryType.File
|
||||
// && file.IsFillFormDraft)
|
||||
//{
|
||||
// e.Access = FileShare.FillForms;
|
||||
|
||||
if (action != FilesSecurityActions.Read
|
||||
&& action != FilesSecurityActions.FillForms
|
||||
&& action != FilesSecurityActions.Delete)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// if (action != FilesSecurityActions.Read
|
||||
// && action != FilesSecurityActions.FillForms
|
||||
// && action != FilesSecurityActions.Delete)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (e.RootFolderType == FolderType.USER && e.RootFolderCreator == userId && !isVisitor)
|
||||
{
|
||||
|
11
products/ASC.Files/Core/Model/CopyAsModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace ASC.Files.Core.Model
|
||||
{
|
||||
public class CopyAsModel<T>
|
||||
{
|
||||
public string DestTitle { get; set; }
|
||||
|
||||
public T DestFolderId { get; set; }
|
||||
|
||||
public bool EnableExternalExt { get; set; }
|
||||
}
|
||||
}
|
@ -320,7 +320,8 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
EmbeddedConfig embeddedConfig,
|
||||
CustomizationConfig<T> customizationConfig,
|
||||
FilesSettingsHelper filesSettingsHelper,
|
||||
IDaoFactory daoFactory)
|
||||
IDaoFactory daoFactory,
|
||||
EntryManager entryManager)
|
||||
{
|
||||
UserManager = userManager;
|
||||
AuthContext = authContext;
|
||||
@ -330,6 +331,7 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
Customization = customizationConfig;
|
||||
FilesSettingsHelper = filesSettingsHelper;
|
||||
DaoFactory = daoFactory;
|
||||
EntryManager = entryManager;
|
||||
Plugins = pluginsConfig;
|
||||
Embedded = embeddedConfig;
|
||||
_userInfo = userManager.GetUsers(authContext.CurrentAccount.ID);
|
||||
@ -381,39 +383,43 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
}
|
||||
|
||||
|
||||
public List<TemplatesConfig> GetTemplates(EntryManager entryManager)
|
||||
public List<TemplatesConfig> Templates
|
||||
{
|
||||
if (!AuthContext.IsAuthenticated || UserManager.GetUsers(AuthContext.CurrentAccount.ID).IsVisitor(UserManager)) return null;
|
||||
if (!FilesSettingsHelper.TemplatesSection) return null;
|
||||
|
||||
var extension = FileUtility.GetInternalExtension(_configuration.Document.Title).TrimStart('.');
|
||||
var filter = FilterType.FilesOnly;
|
||||
switch (_configuration.GetFileType)
|
||||
set { }
|
||||
get
|
||||
{
|
||||
case FileType.Document:
|
||||
filter = FilterType.DocumentsOnly;
|
||||
break;
|
||||
case FileType.Spreadsheet:
|
||||
filter = FilterType.SpreadsheetsOnly;
|
||||
break;
|
||||
case FileType.Presentation:
|
||||
filter = FilterType.PresentationsOnly;
|
||||
break;
|
||||
}
|
||||
if (!AuthContext.IsAuthenticated || UserManager.GetUsers(AuthContext.CurrentAccount.ID).IsVisitor(UserManager)) return null;
|
||||
if (!FilesSettingsHelper.TemplatesSection) return null;
|
||||
|
||||
var folderDao = DaoFactory.GetFolderDao<int>();
|
||||
var fileDao = DaoFactory.GetFileDao<int>();
|
||||
var files = entryManager.GetTemplates(folderDao, fileDao, filter, false, Guid.Empty, string.Empty, false);
|
||||
var listTemplates = from file in files
|
||||
select
|
||||
new TemplatesConfig
|
||||
{
|
||||
Image = BaseCommonLinkUtility.GetFullAbsolutePath("skins/default/images/filetype/thumb/" + extension + ".png"),
|
||||
Name = file.Title,
|
||||
Title = file.Title,
|
||||
Url = BaseCommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID))
|
||||
};
|
||||
return listTemplates.ToList();
|
||||
var extension = FileUtility.GetInternalExtension(_configuration.Document.Title).TrimStart('.');
|
||||
var filter = FilterType.FilesOnly;
|
||||
switch (_configuration.GetFileType)
|
||||
{
|
||||
case FileType.Document:
|
||||
filter = FilterType.DocumentsOnly;
|
||||
break;
|
||||
case FileType.Spreadsheet:
|
||||
filter = FilterType.SpreadsheetsOnly;
|
||||
break;
|
||||
case FileType.Presentation:
|
||||
filter = FilterType.PresentationsOnly;
|
||||
break;
|
||||
}
|
||||
|
||||
var folderDao = DaoFactory.GetFolderDao<int>();
|
||||
var fileDao = DaoFactory.GetFileDao<int>();
|
||||
var files = EntryManager.GetTemplates(folderDao, fileDao, filter, false, Guid.Empty, string.Empty, false);
|
||||
var listTemplates = from file in files
|
||||
select
|
||||
new TemplatesConfig
|
||||
{
|
||||
Image = BaseCommonLinkUtility.GetFullAbsolutePath("skins/default/images/filetype/thumb/" + extension + ".png"),
|
||||
Name = file.Title,
|
||||
Title = file.Title,
|
||||
Url = BaseCommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID))
|
||||
};
|
||||
return listTemplates.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public string CallbackUrl { get; set; }
|
||||
@ -435,6 +441,7 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
public CustomizationConfig<T> Customization { get; set; }
|
||||
private FilesSettingsHelper FilesSettingsHelper { get; }
|
||||
private IDaoFactory DaoFactory { get; }
|
||||
private EntryManager EntryManager { get; }
|
||||
|
||||
public EmbeddedConfig Embedded
|
||||
{
|
||||
@ -465,39 +472,41 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
private BaseCommonLinkUtility BaseCommonLinkUtility { get; }
|
||||
|
||||
public string SaveAsUrl { get; set; }
|
||||
|
||||
public List<RecentConfig> GetRecent(EntryManager entryManager)
|
||||
public List<RecentConfig> Recent
|
||||
{
|
||||
if (!AuthContext.IsAuthenticated || UserManager.GetUsers(AuthContext.CurrentAccount.ID).IsVisitor(UserManager)) return null;
|
||||
if (!FilesSettingsHelper.RecentSection) return null;
|
||||
|
||||
var filter = FilterType.FilesOnly;
|
||||
switch (_configuration.GetFileType)
|
||||
get
|
||||
{
|
||||
case FileType.Document:
|
||||
filter = FilterType.DocumentsOnly;
|
||||
break;
|
||||
case FileType.Spreadsheet:
|
||||
filter = FilterType.SpreadsheetsOnly;
|
||||
break;
|
||||
case FileType.Presentation:
|
||||
filter = FilterType.PresentationsOnly;
|
||||
break;
|
||||
if (!AuthContext.IsAuthenticated || UserManager.GetUsers(AuthContext.CurrentAccount.ID).IsVisitor(UserManager)) return null;
|
||||
if (!FilesSettingsHelper.RecentSection) return null;
|
||||
|
||||
var filter = FilterType.FilesOnly;
|
||||
switch (_configuration.GetFileType)
|
||||
{
|
||||
case FileType.Document:
|
||||
filter = FilterType.DocumentsOnly;
|
||||
break;
|
||||
case FileType.Spreadsheet:
|
||||
filter = FilterType.SpreadsheetsOnly;
|
||||
break;
|
||||
case FileType.Presentation:
|
||||
filter = FilterType.PresentationsOnly;
|
||||
break;
|
||||
}
|
||||
|
||||
var folderDao = DaoFactory.GetFolderDao<int>();
|
||||
var files = EntryManager.GetRecent(filter, false, Guid.Empty, string.Empty, false).Cast<File<int>>();
|
||||
|
||||
var listRecent = from file in files
|
||||
where !Equals(_configuration.Document.Info.GetFile().ID, file.ID)
|
||||
select
|
||||
new RecentConfig
|
||||
{
|
||||
Folder = folderDao.GetFolder(file.FolderID).Title,
|
||||
Title = file.Title,
|
||||
Url = BaseCommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID))
|
||||
};
|
||||
return listRecent.ToList();
|
||||
}
|
||||
|
||||
var folderDao = DaoFactory.GetFolderDao<int>();
|
||||
var files = entryManager.GetRecent(filter, false, Guid.Empty, string.Empty, false).Cast<File<int>>();
|
||||
|
||||
var listRecent = from file in files
|
||||
where !Equals(_configuration.Document.Info.GetFile().ID, file.ID)
|
||||
select
|
||||
new RecentConfig
|
||||
{
|
||||
Folder = folderDao.GetFolder(file.FolderID).Title,
|
||||
Title = file.Title,
|
||||
Url = BaseCommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID))
|
||||
};
|
||||
return listRecent.ToList();
|
||||
}
|
||||
|
||||
public string SharingSettingsUrl { get; set; }
|
||||
@ -863,15 +872,13 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
public class LogoConfig<T>
|
||||
{
|
||||
public LogoConfig(
|
||||
SettingsManager settingsManager,
|
||||
BaseCommonLinkUtility baseCommonLinkUtility,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
TenantLogoHelper tenantLogoHelper,
|
||||
FileUtility fileUtility)
|
||||
{
|
||||
BaseCommonLinkUtility = baseCommonLinkUtility;
|
||||
CommonLinkUtility = commonLinkUtility;
|
||||
TenantLogoHelper = tenantLogoHelper;
|
||||
FileUtility = fileUtility;
|
||||
SettingsManager = settingsManager;
|
||||
}
|
||||
|
||||
private Configuration<T> _configuration;
|
||||
@ -890,8 +897,8 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
return
|
||||
_configuration.EditorType == EditorType.Embedded
|
||||
|| fillingForm
|
||||
? BaseCommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.Dark, !_configuration.EditorConfig.Customization.IsRetina))
|
||||
: BaseCommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.DocsEditor, !_configuration.EditorConfig.Customization.IsRetina));
|
||||
? CommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.Dark, !_configuration.EditorConfig.Customization.IsRetina))
|
||||
: CommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.DocsEditor, !_configuration.EditorConfig.Customization.IsRetina));
|
||||
}
|
||||
}
|
||||
|
||||
@ -903,20 +910,19 @@ namespace ASC.Web.Files.Services.DocumentService
|
||||
return
|
||||
_configuration.EditorType != EditorType.Embedded
|
||||
? null
|
||||
: BaseCommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.Dark, !_configuration.EditorConfig.Customization.IsRetina));
|
||||
: CommonLinkUtility.GetFullAbsolutePath(TenantLogoHelper.GetLogo(WhiteLabelLogoTypeEnum.Dark, !_configuration.EditorConfig.Customization.IsRetina));
|
||||
}
|
||||
}
|
||||
|
||||
public string Url
|
||||
{
|
||||
set { }
|
||||
get { return CompanyWhiteLabelSettings.Instance(SettingsManager).Site; }
|
||||
get { return CommonLinkUtility.GetFullAbsolutePath(CommonLinkUtility.GetDefault()); }
|
||||
}
|
||||
|
||||
private BaseCommonLinkUtility BaseCommonLinkUtility { get; }
|
||||
private CommonLinkUtility CommonLinkUtility { get; }
|
||||
private TenantLogoHelper TenantLogoHelper { get; }
|
||||
public FileUtility FileUtility { get; }
|
||||
private SettingsManager SettingsManager { get; }
|
||||
private FileUtility FileUtility { get; }
|
||||
}
|
||||
|
||||
public class RecentConfig
|
||||
|
@ -1007,8 +1007,14 @@ namespace ASC.Web.Files.Utils
|
||||
if (checkRight && (!forcesave.HasValue || forcesave.Value == ForcesaveType.None) && FileTracker.IsEditing(file.ID)) throw new Exception(FilesCommonResource.ErrorMassage_SecurityException_UpdateEditingFile);
|
||||
if (file.RootFolderType == FolderType.TRASH) throw new Exception(FilesCommonResource.ErrorMassage_ViewTrashItem);
|
||||
|
||||
var currentExt = file.ConvertedExtension;
|
||||
if (string.IsNullOrEmpty(newExtension)) newExtension = FileUtility.GetInternalExtension(file.Title);
|
||||
var currentExt = file.ConvertedExtension;
|
||||
if (string.IsNullOrEmpty(newExtension))
|
||||
{
|
||||
if (currentExt != FileUtility.MasterFormExtension)
|
||||
newExtension = FileUtility.GetInternalExtension(file.Title);
|
||||
else
|
||||
newExtension = currentExt;
|
||||
}
|
||||
|
||||
var replaceVersion = false;
|
||||
if (file.Forcesave != ForcesaveType.None)
|
||||
@ -1036,8 +1042,13 @@ namespace ASC.Web.Files.Utils
|
||||
if (!storeTemplate.IsDirectory(path))
|
||||
{
|
||||
path = FileConstant.NewDocPath + "en-US/";
|
||||
}
|
||||
path += "new" + FileUtility.GetInternalExtension(file.Title);
|
||||
}
|
||||
|
||||
var fileExt = currentExt != FileUtility.MasterFormExtension
|
||||
? FileUtility.GetInternalExtension(file.Title)
|
||||
: currentExt;
|
||||
|
||||
path += "new" + fileExt;
|
||||
|
||||
//todo: think about the criteria for saving after creation
|
||||
if (!storeTemplate.IsFile(path) || file.ContentLength != storeTemplate.GetFileSize("", path))
|
||||
|
@ -1118,6 +1118,32 @@ namespace ASC.Api.Documents
|
||||
return FilesControllerHelperInt.GetFileInfo(fileId, version);
|
||||
}
|
||||
|
||||
[Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)]
|
||||
public FileWrapper<int> CopyFileAsFromBody(int fileId, [FromBody] CopyAsModel<int> model)
|
||||
{
|
||||
return FilesControllerHelperInt.CopyFileAs(fileId, model.DestFolderId, model.DestTitle);
|
||||
}
|
||||
|
||||
[Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)]
|
||||
[Consumes("application/x-www-form-urlencoded")]
|
||||
public FileWrapper<int> CopyFileAsFromForm(int fileId, [FromForm] CopyAsModel<int> model)
|
||||
{
|
||||
return FilesControllerHelperInt.CopyFileAs(fileId, model.DestFolderId, model.DestTitle);
|
||||
}
|
||||
|
||||
[Create("file/{fileId}/copyas", order: int.MaxValue)]
|
||||
public FileWrapper<string> CopyFileAsFromBody(string fileId, [FromBody] CopyAsModel<string> model)
|
||||
{
|
||||
return FilesControllerHelperString.CopyFileAs(fileId, model.DestFolderId, model.DestTitle);
|
||||
}
|
||||
|
||||
[Create("file/{fileId}/copyas", order: int.MaxValue)]
|
||||
[Consumes("application/x-www-form-urlencoded")]
|
||||
public FileWrapper<string> CopyFileAsFromForm(string fileId, [FromBody] CopyAsModel<string> model)
|
||||
{
|
||||
return FilesControllerHelperString.CopyFileAs(fileId, model.DestFolderId, model.DestTitle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the information of the selected file with the parameters specified in the request
|
||||
/// </summary>
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 9fea7818de9abb29295c51b39a54c566bead9895
|
||||
Subproject commit 2a80ac03391aff3bf1f15a5149f6124954b73020
|
@ -65,6 +65,7 @@ namespace ASC.Files.Helpers
|
||||
private SettingsManager SettingsManager { get; }
|
||||
private EncryptionKeyPairHelper EncryptionKeyPairHelper { get; }
|
||||
private IHttpContextAccessor HttpContextAccessor { get; }
|
||||
private FileConverter FileConverter { get; }
|
||||
private ILog Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -92,7 +93,8 @@ namespace ASC.Files.Helpers
|
||||
IOptionsMonitor<ILog> optionMonitor,
|
||||
SettingsManager settingsManager,
|
||||
EncryptionKeyPairHelper encryptionKeyPairHelper,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
FileConverter fileConverter)
|
||||
{
|
||||
ApiContext = context;
|
||||
FileStorageService = fileStorageService;
|
||||
@ -114,6 +116,7 @@ namespace ASC.Files.Helpers
|
||||
SettingsManager = settingsManager;
|
||||
EncryptionKeyPairHelper = encryptionKeyPairHelper;
|
||||
HttpContextAccessor = httpContextAccessor;
|
||||
FileConverter = fileConverter;
|
||||
Logger = optionMonitor.Get("ASC.Files");
|
||||
}
|
||||
|
||||
@ -343,6 +346,22 @@ namespace ASC.Files.Helpers
|
||||
var file = FileStorageService.GetFile(fileId, version).NotFoundIfNull("File not found");
|
||||
return FileWrapperHelper.Get(file);
|
||||
}
|
||||
public FileWrapper<T> CopyFileAs(T fileId, T destFolderId, string destTitle)
|
||||
{
|
||||
var file = FileStorageService.GetFile(fileId, -1);
|
||||
var ext = FileUtility.GetFileExtension(file.Title);
|
||||
var destExt = FileUtility.GetFileExtension(destTitle);
|
||||
|
||||
if (ext == destExt)
|
||||
{
|
||||
return CreateFile(destFolderId, destTitle, fileId);
|
||||
}
|
||||
|
||||
using (var fileStream = FileConverter.Exec(file, destExt))
|
||||
{
|
||||
return InsertFile(destFolderId, fileStream, destTitle, true);
|
||||
}
|
||||
}
|
||||
|
||||
public FileWrapper<T> AddToRecent(T fileId, int version = -1)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.Mail/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Mail/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.Mail/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Mail/client",
|
||||
"serve": "serve dist -p 5016",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5016"
|
||||
|
2
products/ASC.Mail/Client/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.People/client && shx cp -r dist/* ../../../build/deploy/products/ASC.People/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.People/client && shx cp -r dist/* ../../../build/deploy/products/ASC.People/client",
|
||||
"serve": "serve dist -p 5002",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5002"
|
||||
|
2
products/ASC.People/Client/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../../build/deploy/products/ASC.Projects/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Projects/client",
|
||||
"deploy": "shx --silent mkdir -p ../../../build/deploy/products/ASC.Projects/client && shx cp -r dist/* ../../../build/deploy/products/ASC.Projects/client",
|
||||
"serve": "serve dist -p 5015",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5015"
|
||||
|
@ -1,7 +1,7 @@
|
||||
import App from "./App";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.85498 16L1.15188 16C0.518827 16 0.00382324 15.485 0.00378789 14.8519L0.00378713 6.14776C0.00378708 5.51468 0.518826 4.99964 1.15187 4.99964L4.01036 4.99964L4.01036 9.96112C4.01036 11.1721 4.75801 11.9963 5.96898 11.9963L11.0031 11.9963L11.0031 14.8519C11.0031 15.485 10.4881 16 9.85498 16ZM14.8703 11.0013L6.12976 11.0013C5.50682 11.0013 4.99997 10.4945 5 9.87155L5 1.12969C5 0.506788 5.50679 9.17346e-07 6.12973 8.62887e-07L14.8703 9.87639e-08C15.4932 4.43048e-08 16 0.506787 16 1.12973L16 9.87155C16 10.4945 15.4932 11.0013 14.8703 11.0013Z" fill="#A3A9AE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.14502 -1.07443e-06L14.8481 -2.59613e-06C15.4812 -2.70681e-06 15.9962 0.515037 15.9962 1.14808L15.9962 9.85224C15.9962 10.4853 15.4812 11.0004 14.8481 11.0004L11.9896 11.0004L11.9896 6.03888C11.9896 4.82791 11.242 4.00369 10.031 4.00369L4.99694 4.00369L4.99694 1.14809C4.99693 0.515038 5.51194 -9.63738e-07 6.14502 -1.07443e-06ZM1.12973 4.99872L9.87024 4.99872C10.4932 4.99872 11 5.50551 11 6.12845L11 14.8703C11 15.4932 10.4932 16 9.87028 16L1.12973 16C0.50679 16 3.70837e-05 15.4932 2.6e-06 14.8703L1.07154e-06 6.12845C9.62618e-07 5.50551 0.506823 4.99872 1.12973 4.99872Z" fill="#A3A9AE"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 716 B After Width: | Height: | Size: 747 B |
@ -1,3 +1,4 @@
|
||||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.9862 0.721877L16.2791 0.0147705L8.50091 7.79295L0.722732 0.0147736L0.015625 0.72188L7.7938 8.50006L0.0156276 16.2782L0.722734 16.9853L8.50091 9.20716L16.2791 16.9853L16.9862 16.2782L9.20801 8.50005L16.9862 0.721877Z" fill="#D0D5DA"/>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 1.99951L1.99968 11.9998" stroke="#A3A9AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M2 1.99951L12.0003 11.9998" stroke="#A3A9AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 344 B |
@ -1,12 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g transform="translate(-168.000000, -936.000000)" fill="#000000">
|
||||
<g transform="translate(24.000000, 888.000000)">
|
||||
<g transform="translate(144.000000, 48.000000)">
|
||||
<path fill="#000000" stroke="#000000" stroke-width="0.1" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" d="m1.40265,7.01045c0,0 21.20239,0 21.20239,0c0,0 -10.56768,11.23794 -10.56768,11.23794c0,0 -10.63471,-11.23794 -10.63471,-11.23794z" id="svg_29"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg width="5" height="4" viewBox="0 0 5 4" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 4L0 1L5 1L2.5 4Z" fill="#333333"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 804 B After Width: | Height: | Size: 188 B |
3
public/images/form.plus.react.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 2C0 0.895431 0.895431 0 2 0H14C15.1046 0 16 0.895431 16 2V7H14H7H2V10H7V16H2C0.895431 16 0 15.1046 0 14V2ZM2 2H14V5H2V2ZM11 9H13V11H15V13H13V15H11V13H9V11H11V9Z" fill="#657077"/>
|
||||
</svg>
|
After Width: | Height: | Size: 334 B |
@ -52,6 +52,7 @@
|
||||
"LoadingDescription": "Please wait...",
|
||||
"LoadingProcessing": "Loading...",
|
||||
"Mail": "Mail",
|
||||
"MakeForm": "Make form",
|
||||
"MeLabel": "Me",
|
||||
"More": "More",
|
||||
"Next": "Next",
|
||||
|
@ -301,7 +301,7 @@ namespace ASC.Web.Api.Controllers
|
||||
try
|
||||
{
|
||||
var token = SecurityContext.AuthenticateMe(user.ID);
|
||||
CookiesManager.SetCookies(CookiesType.AuthKey, token);
|
||||
CookiesManager.SetCookies(CookiesType.AuthKey, token, auth.Session);
|
||||
|
||||
MessageService.Send(viaEmail ? MessageAction.LoginSuccessViaApi : MessageAction.LoginSuccessViaApiSocialAccount);
|
||||
|
||||
@ -436,6 +436,8 @@ namespace ASC.Web.Api.Controllers
|
||||
{
|
||||
throw new Exception("user not found");
|
||||
}
|
||||
|
||||
Cache.Insert("loginsec/" + memberModel.UserName, (--counter).ToString(CultureInfo.InvariantCulture), DateTime.UtcNow.Add(TimeSpan.FromMinutes(1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
public string AccessToken { get; set; }
|
||||
public string SerializedProfile { get; set; }
|
||||
public string Code { get; set; }
|
||||
public bool Session { get; set; }
|
||||
}
|
||||
|
||||
public class MobileModel
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../build/deploy/studio/client && shx cp -r dist/* ../../build/deploy/studio/client",
|
||||
"deploy": "shx --silent mkdir -p ../../build/deploy/studio/client && shx cp -r dist/* ../../build/deploy/studio/client",
|
||||
"serve": "serve dist -p 5001",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5001"
|
||||
|
2
web/ASC.Web.Client/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -19,16 +19,12 @@ const version = pkg.version;
|
||||
|
||||
const config = {
|
||||
entry: "./src/index",
|
||||
target: "web",
|
||||
mode: "development",
|
||||
|
||||
stats: {
|
||||
errorDetails: true,
|
||||
},
|
||||
|
||||
devServer: {
|
||||
devMiddleware: {
|
||||
publicPath: homepage,
|
||||
//writeToDisk: true,
|
||||
},
|
||||
static: {
|
||||
directory: path.join(__dirname, "dist"),
|
||||
@ -240,11 +236,7 @@ module.exports = (env, argv) => {
|
||||
config.optimization = {
|
||||
splitChunks: { chunks: "all" },
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
include: "./src/store",
|
||||
}),
|
||||
],
|
||||
minimizer: [new TerserPlugin()],
|
||||
};
|
||||
} else {
|
||||
config.devtool = "cheap-module-source-map";
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../build/deploy/products/ASC.Files/editor && shx cp -r dist/* ../../build/deploy/products/ASC.Files/editor",
|
||||
"deploy": "shx --silent mkdir -p ../../build/deploy/products/ASC.Files/editor && shx cp -r dist/* ../../build/deploy/products/ASC.Files/editor",
|
||||
"serve": "serve dist -p 5013",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5013"
|
||||
|
@ -20,8 +20,6 @@ import {
|
||||
setEncryptionKeys,
|
||||
getEncryptionAccess,
|
||||
getFileInfo,
|
||||
getRecentFolderList,
|
||||
getFolderInfo,
|
||||
updateFile,
|
||||
removeFromFavorite,
|
||||
markAsFavorite,
|
||||
@ -78,7 +76,8 @@ const Editor = () => {
|
||||
const decodedId = urlParams
|
||||
? urlParams.fileId || urlParams.fileid || null
|
||||
: null;
|
||||
const fileId = encodeURIComponent(decodedId);
|
||||
const fileId =
|
||||
typeof decodedId === "string" ? encodeURIComponent(decodedId) : decodedId;
|
||||
const version = urlParams ? urlParams.version || null : null;
|
||||
const doc = urlParams ? urlParams.doc || null : null;
|
||||
const isDesktop = window["AscDesktopEditor"] !== undefined;
|
||||
@ -143,56 +142,6 @@ const Editor = () => {
|
||||
docEditor.setFavorite(favorite);
|
||||
};
|
||||
|
||||
const getRecent = async (config) => {
|
||||
try {
|
||||
const recentFolderList = await getRecentFolderList();
|
||||
|
||||
const filesArray = recentFolderList.files.slice(0, 25);
|
||||
|
||||
const recentFiles = filesArray.filter(
|
||||
(file) =>
|
||||
file.rootFolderType !== FolderType.SHARE &&
|
||||
((config.documentType === text && file.fileType === 7) ||
|
||||
(config.documentType === spreadSheet && file.fileType === 5) ||
|
||||
(config.documentType === presentation && file.fileType === 6))
|
||||
);
|
||||
|
||||
const groupedByFolder = recentFiles.reduce((r, a) => {
|
||||
r[a.folderId] = [...(r[a.folderId] || []), a];
|
||||
return r;
|
||||
}, {});
|
||||
|
||||
const requests = Object.entries(groupedByFolder).map((item) =>
|
||||
getFolderInfo(item[0])
|
||||
.then((folderInfo) =>
|
||||
Promise.resolve({
|
||||
files: item[1],
|
||||
folderInfo: folderInfo,
|
||||
})
|
||||
)
|
||||
.catch((e) => console.error(e))
|
||||
);
|
||||
|
||||
let recent = [];
|
||||
|
||||
let responses = await Promise.all(requests);
|
||||
|
||||
for (let res of responses) {
|
||||
res.files.forEach((file) => {
|
||||
const convertedData = convertRecentData(file, res.folderInfo);
|
||||
if (Object.keys(convertedData).length !== 0)
|
||||
recent.push(convertedData);
|
||||
});
|
||||
}
|
||||
|
||||
return recent;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const initDesktop = (config) => {
|
||||
const isEncryption = config?.editorConfig["encryptionKeys"] !== undefined;
|
||||
|
||||
@ -312,17 +261,6 @@ const Editor = () => {
|
||||
initDesktop();
|
||||
}
|
||||
|
||||
if (successAuth) {
|
||||
const recent = await getRecent(config); //TODO: too slow for 1st loading
|
||||
|
||||
if (recent) {
|
||||
config.editorConfig = {
|
||||
...config.editorConfig,
|
||||
recent: recent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
isSharingAccess = fileInfo && fileInfo.canShare;
|
||||
|
||||
if (view) {
|
||||
@ -343,20 +281,6 @@ const Editor = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const convertRecentData = (file, folder) => {
|
||||
let obj = {};
|
||||
const folderName = folder.title;
|
||||
const fileName = file.title;
|
||||
|
||||
if (+fileId !== file.id)
|
||||
obj = {
|
||||
folder: folderName,
|
||||
title: fileName,
|
||||
url: file.webUrl,
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
|
||||
const isIPad = () => {
|
||||
return isIOS && deviceType === "tablet";
|
||||
};
|
||||
|
2
web/ASC.Web.Editor/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"clean": "shx rm -rf dist",
|
||||
"deploy": "shx mkdir -p ../../build/deploy/studio/login && shx cp -r dist/* ../../build/deploy/studio/login",
|
||||
"deploy": "shx --silent mkdir -p ../../build/deploy/studio/login && shx cp -r dist/* ../../build/deploy/studio/login",
|
||||
"serve": "serve dist -p 5011",
|
||||
"start": "webpack-cli serve",
|
||||
"start-prod": "webpack --mode production && serve dist -p 5011"
|
||||
|
2
web/ASC.Web.Login/src/bootstrap.js
vendored
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import { registerSW } from "@appserver/common/utils/sw-helper";
|
||||
import { registerSW } from "@appserver/common/sw/helper";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
|