Merge branch 'release/1.0.0' into bugfix/filterlist-extra-items
This commit is contained in:
commit
390430c3ee
@ -122,10 +122,6 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
path += ".gz";
|
||||
encoding = "gzip";
|
||||
}
|
||||
using (var stream = storage.GetReadStream(_domain, path))
|
||||
{
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
|
||||
var headersToCopy = new List<string> { "Content-Disposition", "Cache-Control", "Content-Encoding", "Content-Language", "Content-Type", "Expires" };
|
||||
foreach (var h in headers)
|
||||
@ -145,7 +141,15 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
//}
|
||||
|
||||
if (encoding != null)
|
||||
context.Response.Headers["Content-Encoding"] = encoding;
|
||||
context.Response.Headers["Content-Encoding"] = encoding;
|
||||
|
||||
using (var stream = storage.GetReadStream(_domain, path))
|
||||
{
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
|
||||
await context.Response.Body.FlushAsync();
|
||||
await context.Response.CompleteAsync();
|
||||
|
||||
string GetRouteValue(string name)
|
||||
{
|
||||
|
@ -32,8 +32,6 @@ class SnackBar extends React.Component {
|
||||
const bar = document.querySelector(`#${window.snackbar.parentElementId}`);
|
||||
bar.remove();
|
||||
//ReactDOM.unmountComponentAtNode(window.snackbar.parentElementId);
|
||||
} else {
|
||||
console.error("Not found snackbar");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ namespace ASC.Web.Files.Core.Compress
|
||||
/// <param name="title">File name with extension, this name will have the file in the archive</param>
|
||||
public void CreateEntry(string title)
|
||||
{
|
||||
zipEntry = new ZipEntry(title);
|
||||
zipEntry = new ZipEntry(title) { IsUnicodeText = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,7 +28,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
@ -49,9 +48,6 @@ using ASC.Web.Studio.Core;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writers.Zip;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
internal class FileDownloadOperationData<T> : FileOperationData<T>
|
||||
@ -89,21 +85,23 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
using var scope = ThirdPartyOperation.CreateScope();
|
||||
var scopeClass = scope.ServiceProvider.GetService<FileDownloadOperationScope>();
|
||||
var (zip, globalStore, filesLinkUtility, _, _, _) = scopeClass;
|
||||
using var stream = TempStream.Create();
|
||||
|
||||
var writerOptions = new ZipWriterOptions(CompressionType.Deflate);
|
||||
writerOptions.ArchiveEncoding.Default = Encoding.UTF8;
|
||||
writerOptions.DeflateCompressionLevel = SharpCompress.Compressors.Deflate.CompressionLevel.Level3;
|
||||
|
||||
zip.SetStream(stream);
|
||||
(ThirdPartyOperation as FileDownloadOperation<string>).CompressToZip(zip, stream, scope);
|
||||
(DaoOperation as FileDownloadOperation<int>).CompressToZip(zip, stream, scope);
|
||||
var (globalStore, filesLinkUtility, _, _, _) = scopeClass;
|
||||
var stream = TempStream.Create();
|
||||
|
||||
(ThirdPartyOperation as FileDownloadOperation<string>).CompressToZip(stream, scope);
|
||||
(DaoOperation as FileDownloadOperation<int>).CompressToZip(stream, scope);
|
||||
|
||||
if (stream != null)
|
||||
{
|
||||
var archiveExtension = "";
|
||||
|
||||
using(var zip = scope.ServiceProvider.GetService<CompressToArchive>())
|
||||
{
|
||||
archiveExtension = zip.ArchiveExtension;
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
string fileName = FileConstant.DownloadTitle + zip.ArchiveExtension;
|
||||
string fileName = FileConstant.DownloadTitle + archiveExtension;
|
||||
var store = globalStore.GetStore();
|
||||
var path = string.Format(@"{0}\{1}", ((IAccount)Thread.CurrentPrincipal.Identity).ID, fileName);
|
||||
|
||||
@ -118,7 +116,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
stream,
|
||||
MimeMapping.GetMimeMapping(path),
|
||||
"attachment; filename=\"" + fileName + "\"");
|
||||
Result = string.Format("{0}?{1}=bulk&ext={2}", filesLinkUtility.FileHandlerPath, FilesLinkUtility.Action, zip.ArchiveExtension);
|
||||
Result = string.Format("{0}?{1}=bulk&ext={2}", filesLinkUtility.FileHandlerPath, FilesLinkUtility.Action, archiveExtension);
|
||||
}
|
||||
|
||||
FillDistributedTask();
|
||||
@ -239,114 +237,121 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
return entriesPathId;
|
||||
}
|
||||
|
||||
internal void CompressToZip(ICompress compressTo, Stream stream, IServiceScope scope)
|
||||
internal void CompressToZip(Stream stream, IServiceScope scope)
|
||||
{
|
||||
if (entriesPathId == null) return;
|
||||
var scopeClass = scope.ServiceProvider.GetService<FileDownloadOperationScope>();
|
||||
var (_, _, _, _, fileConverter, filesMessageService) = scopeClass;
|
||||
var (_, _, _, fileConverter, filesMessageService) = scopeClass;
|
||||
var FileDao = scope.ServiceProvider.GetService<IFileDao<T>>();
|
||||
|
||||
foreach (var path in entriesPathId.AllKeys)
|
||||
using (var compressTo = scope.ServiceProvider.GetService<CompressToArchive>())
|
||||
{
|
||||
var counter = 0;
|
||||
foreach (var entryId in entriesPathId[path])
|
||||
compressTo.SetStream(stream);
|
||||
|
||||
foreach (var path in entriesPathId.AllKeys)
|
||||
{
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
var counter = 0;
|
||||
foreach (var entryId in entriesPathId[path])
|
||||
{
|
||||
compressTo.Dispose();
|
||||
stream.Dispose();
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
var newtitle = path;
|
||||
|
||||
File<T> file = null;
|
||||
var convertToExt = string.Empty;
|
||||
|
||||
if (!Equals(entryId, default(T)))
|
||||
{
|
||||
FileDao.InvalidateCache(entryId);
|
||||
file = FileDao.GetFile(entryId);
|
||||
|
||||
if (file == null)
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_FileNotFound;
|
||||
continue;
|
||||
compressTo.Dispose();
|
||||
stream.Dispose();
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
if (files.ContainsKey(file.ID))
|
||||
{
|
||||
convertToExt = files[file.ID];
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
{
|
||||
newtitle = FileUtility.ReplaceFileExtension(path, convertToExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
var newtitle = path;
|
||||
|
||||
if (0 < counter)
|
||||
{
|
||||
var suffix = " (" + counter + ")";
|
||||
File<T> file = null;
|
||||
var convertToExt = string.Empty;
|
||||
|
||||
if (!Equals(entryId, default(T)))
|
||||
{
|
||||
newtitle = 0 < newtitle.IndexOf('.') ? newtitle.Insert(newtitle.LastIndexOf('.'), suffix) : newtitle + suffix;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
FileDao.InvalidateCache(entryId);
|
||||
file = FileDao.GetFile(entryId);
|
||||
|
||||
compressTo.CreateEntry(newtitle);
|
||||
|
||||
if (!Equals(entryId, default(T)) && file != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fileConverter.EnableConvert(file, convertToExt))
|
||||
if (file == null)
|
||||
{
|
||||
//Take from converter
|
||||
using (var readStream = fileConverter.Exec(file, convertToExt))
|
||||
{
|
||||
compressTo.PutStream(readStream);
|
||||
Error = FilesCommonResource.ErrorMassage_FileNotFound;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
if (files.ContainsKey(file.ID))
|
||||
{
|
||||
convertToExt = files[file.ID];
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
{
|
||||
newtitle = FileUtility.ReplaceFileExtension(path, convertToExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < counter)
|
||||
{
|
||||
var suffix = " (" + counter + ")";
|
||||
|
||||
if (!Equals(entryId, default(T)))
|
||||
{
|
||||
newtitle = 0 < newtitle.IndexOf('.') ? newtitle.Insert(newtitle.LastIndexOf('.'), suffix) : newtitle + suffix;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
compressTo.CreateEntry(newtitle);
|
||||
|
||||
if (!Equals(entryId, default(T)) && file != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fileConverter.EnableConvert(file, convertToExt))
|
||||
{
|
||||
//Take from converter
|
||||
using (var readStream = fileConverter.Exec(file, convertToExt))
|
||||
{
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloadedAs, file.Title, convertToExt);
|
||||
compressTo.PutStream(readStream);
|
||||
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
{
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloadedAs, file.Title, convertToExt);
|
||||
}
|
||||
else
|
||||
{
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var readStream = FileDao.GetFileStream(file))
|
||||
{
|
||||
compressTo.PutStream(readStream);
|
||||
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
using (var readStream = FileDao.GetFileStream(file))
|
||||
{
|
||||
compressTo.PutStream(readStream);
|
||||
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
Error = ex.Message;
|
||||
Logger.Error(Error, ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
Error = ex.Message;
|
||||
Logger.Error(Error, ex);
|
||||
compressTo.PutNextEntry();
|
||||
}
|
||||
compressTo.CloseEntry();
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
compressTo.PutNextEntry();
|
||||
}
|
||||
compressTo.CloseEntry();
|
||||
counter++;
|
||||
}
|
||||
|
||||
ProgressStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ProgressStep();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReplaceLongPath(ItemNameValueCollection<T> entriesPathId)
|
||||
@ -429,27 +434,23 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
private SetupInfo SetupInfo { get; }
|
||||
private FileConverter FileConverter { get; }
|
||||
private FilesMessageService FilesMessageService { get; }
|
||||
private CompressToArchive CompressToArchive { get; }
|
||||
|
||||
public FileDownloadOperationScope(
|
||||
GlobalStore globalStore,
|
||||
FilesLinkUtility filesLinkUtility,
|
||||
SetupInfo setupInfo,
|
||||
FileConverter fileConverter,
|
||||
FilesMessageService filesMessageService,
|
||||
CompressToArchive compressToArchive)
|
||||
FilesMessageService filesMessageService)
|
||||
{
|
||||
GlobalStore = globalStore;
|
||||
FilesLinkUtility = filesLinkUtility;
|
||||
SetupInfo = setupInfo;
|
||||
FileConverter = fileConverter;
|
||||
FilesMessageService = filesMessageService;
|
||||
CompressToArchive = compressToArchive;
|
||||
}
|
||||
|
||||
public void Deconstruct(out CompressToArchive compressToArchive, out GlobalStore globalStore, out FilesLinkUtility filesLinkUtility, out SetupInfo setupInfo, out FileConverter fileConverter, out FilesMessageService filesMessageService)
|
||||
{
|
||||
compressToArchive = CompressToArchive;
|
||||
public void Deconstruct(out GlobalStore globalStore, out FilesLinkUtility filesLinkUtility, out SetupInfo setupInfo, out FileConverter fileConverter, out FilesMessageService filesMessageService)
|
||||
{
|
||||
globalStore = GlobalStore;
|
||||
filesLinkUtility = FilesLinkUtility;
|
||||
setupInfo = SetupInfo;
|
||||
|
@ -34,7 +34,8 @@ using ASC.Common;
|
||||
using ASC.Common.Threading;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core.Resources;
|
||||
|
||||
using ASC.Web.Files.Core.Compress;
|
||||
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
@ -181,6 +182,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
services.TryAdd<FileMoveCopyOperationScope>();
|
||||
services.TryAdd<FileOperationScope>();
|
||||
services.TryAdd<FileDownloadOperationScope>();
|
||||
services.TryAdd<CompressToArchive>();
|
||||
services.AddDistributedTaskQueueService<FileOperation>(10);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"AboutCompanyAddressTitle": "address",
|
||||
"AboutCompanyEmailTitle": "email",
|
||||
"AboutCompanyLicensor": "Copyright",
|
||||
"AboutCompanyTelTitle": "tel.",
|
||||
"AllRightsReservedCustomMode": "<0>Ascensio System SIA.</0> <1>All rights reserved.</1>",
|
||||
"LicensedUnder": "This software is licensed under: <1>{{license}}</1>",
|
||||
"SourceCode": "Source code is available on"
|
||||
}
|
||||
"AboutHeader": "About this program",
|
||||
"DocumentManagement": "Document management",
|
||||
"OnlineEditors": "Online editors",
|
||||
"SoftwareLicense": "Software license",
|
||||
"AboutCompanyAddressTitle": "Address",
|
||||
"AboutCompanyEmailTitle": "Email",
|
||||
"AboutCompanyTelTitle": "Phone"
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"AboutCompanyAddressTitle": "адрес",
|
||||
"AboutCompanyEmailTitle": "email",
|
||||
"AboutCompanyLicensor": "АВТОРСКИЕ ПРАВА",
|
||||
"AboutCompanyTelTitle": "тел.",
|
||||
"AllRightsReservedCustomMode": "<0>Ascensio System SIA.</0> <1>All rights reserved.</1>",
|
||||
"LicensedUnder": "Программа распространяется под лицензией: {{license}}",
|
||||
"SourceCode": "Исходный код программы доступен по cсылке"
|
||||
}
|
||||
"AboutHeader": "Об этой программе",
|
||||
"DocumentManagement": "Управление документами",
|
||||
"OnlineEditors": "Онлайн редакторы",
|
||||
"SoftwareLicense": "Лицензия на ПО",
|
||||
"AboutCompanyAddressTitle": "Адрес",
|
||||
"AboutCompanyEmailTitle": "Email",
|
||||
"AboutCompanyTelTitle": "Телефон"
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import { inject, observer } from "mobx-react";
|
||||
import { withRouter } from "react-router";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
import config from "../../../../package.json";
|
||||
import { isDesktop } from "react-device-detect";
|
||||
import AboutDialog from "../../pages/About/AboutDialog";
|
||||
|
||||
const { proxyURL } = AppServerConfig;
|
||||
const homepage = config.homepage;
|
||||
@ -61,8 +63,10 @@ const HeaderNav = ({
|
||||
isAuthenticated,
|
||||
peopleAvailable,
|
||||
isPersonal,
|
||||
versionAppServer,
|
||||
}) => {
|
||||
const { t } = useTranslation(["NavMenu", "Common"]);
|
||||
const { t } = useTranslation(["NavMenu", "Common", "About"]);
|
||||
const [visibleDialog, setVisibleDialog] = useState(false);
|
||||
|
||||
const onProfileClick = useCallback(() => {
|
||||
peopleAvailable
|
||||
@ -70,7 +74,15 @@ const HeaderNav = ({
|
||||
: window.open(PROFILE_MY_URL, "_blank");
|
||||
}, []);
|
||||
|
||||
const onAboutClick = useCallback(() => history.push(ABOUT_URL), []);
|
||||
const onAboutClick = useCallback(() => {
|
||||
if (isDesktop) {
|
||||
setVisibleDialog(true);
|
||||
} else {
|
||||
history.push(ABOUT_URL);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onCloseDialog = () => setVisibleDialog(false);
|
||||
|
||||
const onSwitchToDesktopClick = useCallback(() => {
|
||||
deleteCookie("desktop_view");
|
||||
@ -142,6 +154,14 @@ const HeaderNav = ({
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
<AboutDialog
|
||||
t={t}
|
||||
visible={visibleDialog}
|
||||
onClose={onCloseDialog}
|
||||
personal={isPersonal}
|
||||
versionAppServer={versionAppServer}
|
||||
/>
|
||||
</StyledNav>
|
||||
);
|
||||
};
|
||||
@ -167,7 +187,11 @@ export default withRouter(
|
||||
language,
|
||||
logout,
|
||||
} = auth;
|
||||
const { defaultPage, personal: isPersonal } = settingsStore;
|
||||
const {
|
||||
defaultPage,
|
||||
personal: isPersonal,
|
||||
version: versionAppServer,
|
||||
} = settingsStore;
|
||||
const { user } = userStore;
|
||||
const modules = auth.availableModules;
|
||||
return {
|
||||
@ -180,6 +204,7 @@ export default withRouter(
|
||||
modules,
|
||||
logout,
|
||||
peopleAvailable: modules.some((m) => m.appName === "people"),
|
||||
versionAppServer,
|
||||
};
|
||||
})(observer(HeaderNav))
|
||||
);
|
||||
|
115
web/ASC.Web.Client/src/components/pages/About/AboutContent.js
Normal file
115
web/ASC.Web.Client/src/components/pages/About/AboutContent.js
Normal file
@ -0,0 +1,115 @@
|
||||
import React from "react";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const AboutBody = styled.div`
|
||||
width: 100%;
|
||||
|
||||
.avatar {
|
||||
margin-top: 32px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
margin-top: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const AboutContent = ({ personal, versionAppServer }) => {
|
||||
const { t } = useTranslation("About");
|
||||
const versionEditor = "6.3.1";
|
||||
const license = "AGPL-3.0";
|
||||
const link = "https://github.com/ONLYOFFICE";
|
||||
const phone = "+371 660-16425";
|
||||
const email = "support@onlyoffice.com";
|
||||
const address =
|
||||
"20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050";
|
||||
|
||||
return (
|
||||
<AboutBody>
|
||||
<div className="avatar">
|
||||
{personal ? (
|
||||
<ReactSVG src="images/logo_personal_about.svg" />
|
||||
) : (
|
||||
<img src="images/dark_general.png" alt="Logo" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<Text fontSize="13px">{t("DocumentManagement")}:</Text>
|
||||
<Link
|
||||
color="#2DA7DB"
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
href={link}
|
||||
target="_blank"
|
||||
>
|
||||
ONLYOFFICE App Server
|
||||
</Link>
|
||||
<Text fontSize="13px" fontWeight="600">
|
||||
v.{versionAppServer}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<Text fontSize="13px">{t("OnlineEditors")}:</Text>
|
||||
<Link
|
||||
color="#2DA7DB"
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
href={link}
|
||||
target="_blank"
|
||||
>
|
||||
ONLYOFFICE Docs
|
||||
</Link>
|
||||
<Text fontSize="13px" fontWeight="600">
|
||||
v.{versionEditor}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<Text fontSize="13px">{t("SoftwareLicense")}: </Text>
|
||||
<Text fontSize="13px" fontWeight="600">
|
||||
{license}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Text className="copyright" fontSize="14px" fontWeight="600">
|
||||
© Ascensio System SIA
|
||||
</Text>
|
||||
|
||||
<div className="row">
|
||||
<Text fontSize="13px">
|
||||
{t("AboutCompanyAddressTitle")}: {address}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<Text fontSize="13px">
|
||||
{t("AboutCompanyTelTitle")}: {phone}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="row">
|
||||
<Text fontSize="13px">{t("AboutCompanyEmailTitle")}:</Text>
|
||||
<Link
|
||||
color="#2DA7DB"
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
href={`mailto:${email}`}
|
||||
>
|
||||
{email}
|
||||
</Link>
|
||||
</div>
|
||||
</AboutBody>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutContent;
|
42
web/ASC.Web.Client/src/components/pages/About/AboutDialog.js
Normal file
42
web/ASC.Web.Client/src/components/pages/About/AboutDialog.js
Normal file
@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import ModalDialogContainer from "./ModalDialogContainer";
|
||||
import { I18nextProvider, useTranslation } from "react-i18next";
|
||||
import AboutContent from "./AboutContent";
|
||||
import i18n from "./i18n";
|
||||
|
||||
const AboutDialog = (props) => {
|
||||
const { visible, onClose, personal, versionAppServer } = props;
|
||||
const { t, ready } = useTranslation(["About", "Common"]);
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
isLoading={!ready}
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ModalDialog.Header>{t("AboutHeader")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<AboutContent personal={personal} versionAppServer={versionAppServer} />
|
||||
</ModalDialog.Body>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
AboutDialog.propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
onClose: PropTypes.func,
|
||||
personal: PropTypes.bool,
|
||||
versionAppServer: PropTypes.string,
|
||||
};
|
||||
|
||||
const AboutDialogWrapper = (props) => {
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AboutDialog {...props} />
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutDialogWrapper;
|
@ -0,0 +1,67 @@
|
||||
import styled from "styled-components";
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
|
||||
const ModalDialogContainer = styled(ModalDialog)`
|
||||
.invite-link-dialog-wrapper {
|
||||
display: flex;
|
||||
|
||||
@media ${tablet} {
|
||||
display: grid;
|
||||
grid-gap: 8px;
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.text-dialog {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.input-dialog {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.button-dialog {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.warning-text {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.textarea-dialog {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.link-dialog {
|
||||
transition: opacity 0.2s;
|
||||
margin-right: 12px;
|
||||
opacity: ${(props) => (props.ChangeTextAnim ? 0 : 1)};
|
||||
}
|
||||
|
||||
.error-label {
|
||||
position: absolute;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.field-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.toggle-content-dialog {
|
||||
.heading-toggle-content {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.modal-dialog-content {
|
||||
padding: 8px 16px;
|
||||
border: 1px solid lightgray;
|
||||
|
||||
.modal-dialog-checkbox:not(:last-child) {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default ModalDialogContainer;
|
@ -1,203 +1,38 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import PageLayout from "@appserver/common/components/PageLayout";
|
||||
import { I18nextProvider, Trans, withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { setDocumentTitle } from "../../../helpers/utils";
|
||||
import i18n from "./i18n";
|
||||
import withLoader from "../Confirm/withLoader";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import AboutContent from "./AboutContent";
|
||||
|
||||
const BodyStyle = styled.div`
|
||||
margin-top: ${isMobile ? "80px" : "24px"};
|
||||
|
||||
.avatar {
|
||||
text-align: center;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.text-about {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.text-license {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.text_style {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
text-align: center;
|
||||
max-width: 216px;
|
||||
max-height: 35px;
|
||||
}
|
||||
|
||||
.hidden-text {
|
||||
height: 0;
|
||||
visibility: hidden;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.copyright-line {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr max-content 1fr;
|
||||
grid-column-gap: 24px;
|
||||
padding-bottom: 15px;
|
||||
text-align: center;
|
||||
|
||||
:before {
|
||||
background-color: #e1e1e1;
|
||||
content: "";
|
||||
height: 2px;
|
||||
margin-top: 9px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
:after {
|
||||
background-color: #e1e1e1;
|
||||
content: "";
|
||||
height: 2px;
|
||||
margin-top: 9px;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
padding: ${isMobileOnly ? "48px 0 0" : "80px 147px 0"};
|
||||
`;
|
||||
|
||||
const Style = styled.div`
|
||||
margin-top: 8px;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const VersionStyle = styled.div`
|
||||
padding: 8px 0px 20px 0px;
|
||||
`;
|
||||
|
||||
const Body = ({ t, personal, version }) => {
|
||||
const Body = ({ t, personal, versionAppServer }) => {
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Common:About"));
|
||||
}, [t]);
|
||||
|
||||
const gitHub = "GitHub";
|
||||
const license = "AGPL-3.0";
|
||||
const link = "www.onlyoffice.com";
|
||||
const phone = "+371 660-16425";
|
||||
const supportLink = "support@onlyoffice.com";
|
||||
const address =
|
||||
"20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050";
|
||||
const licenseContent = (
|
||||
<Text as="div" className="text_style" fontSize="12px">
|
||||
<Trans t={t} i18nKey="LicensedUnder" ns="About">
|
||||
"This software is licensed under:"
|
||||
<Link
|
||||
href="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
isHovered={true}
|
||||
fontSize="12px"
|
||||
target="_blank"
|
||||
>
|
||||
{{ license }}
|
||||
</Link>
|
||||
</Trans>
|
||||
</Text>
|
||||
);
|
||||
|
||||
return (
|
||||
<BodyStyle>
|
||||
<div className="avatar">
|
||||
{personal ? (
|
||||
<ReactSVG src="images/logo_personal_about.svg" />
|
||||
) : (
|
||||
<img
|
||||
className="logo-img"
|
||||
src="images/dark_general.png"
|
||||
width="320"
|
||||
height="181"
|
||||
alt="Logo"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<VersionStyle>
|
||||
<Text className="text_style" fontSize="14px" color="#A3A9AE">
|
||||
{`${t("Common:Version")}: ${version}`}
|
||||
</Text>
|
||||
</VersionStyle>
|
||||
|
||||
<Text className="copyright-line" fontSize="14px">
|
||||
{t("AboutCompanyLicensor")}
|
||||
<Text fontSize="32px" fontWeight="600">
|
||||
{t("AboutHeader")}
|
||||
</Text>
|
||||
|
||||
<Text as="div" className="text_style" fontSize="16px" isBold={true}>
|
||||
<Trans t={t} i18nKey="AllRightsReservedCustomMode" ns="About">
|
||||
Ascensio System SIA
|
||||
<p className="hidden-text">All rights reserved.</p>
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Style>
|
||||
<Text className="text_style" fontSize="12px">
|
||||
<Text
|
||||
className="text_style"
|
||||
fontSize="12px"
|
||||
as="span"
|
||||
color="#A3A9AE"
|
||||
>
|
||||
{t("AboutCompanyAddressTitle")}:{" "}
|
||||
</Text>
|
||||
{address}
|
||||
</Text>
|
||||
|
||||
<Text fontSize="12px" className="text_style" as="span" color="#A3A9AE">
|
||||
{t("AboutCompanyEmailTitle")}:{" "}
|
||||
<Link href="mailto:support@onlyoffice.com" fontSize="12px">
|
||||
{supportLink}
|
||||
</Link>
|
||||
</Text>
|
||||
|
||||
<div className="text-about">
|
||||
<Text className="text_style" fontSize="12px">
|
||||
<Text
|
||||
fontSize="12px"
|
||||
className="text_style"
|
||||
as="span"
|
||||
color="#A3A9AE"
|
||||
>
|
||||
{t("AboutCompanyTelTitle")}:{" "}
|
||||
</Text>
|
||||
{phone}
|
||||
</Text>
|
||||
</div>
|
||||
<Link href="http://www.onlyoffice.com" fontSize="12px" target="_blank">
|
||||
{link}
|
||||
</Link>
|
||||
|
||||
<div className="text-license">
|
||||
<div className="text-row">{licenseContent}</div>
|
||||
|
||||
<Text className="text_style" fontSize="12px">
|
||||
{t("SourceCode")}:{" "}
|
||||
<Link
|
||||
href="https://github.com/ONLYOFFICE/AppServer"
|
||||
isHovered={true}
|
||||
fontSize="12px"
|
||||
target="_blank"
|
||||
>
|
||||
{gitHub}
|
||||
</Link>
|
||||
</Text>
|
||||
</div>
|
||||
</Style>
|
||||
<AboutContent personal={personal} versionAppServer={versionAppServer} />
|
||||
</BodyStyle>
|
||||
);
|
||||
};
|
||||
|
||||
const BodyWrapper = inject(({ auth }) => ({
|
||||
personal: auth.settingsStore,
|
||||
version: auth.settingsStore.version,
|
||||
versionAppServer: auth.settingsStore.version,
|
||||
}))(withTranslation(["About", "Common"])(withLoader(observer(Body))));
|
||||
|
||||
const About = (props) => {
|
||||
|
Loading…
Reference in New Issue
Block a user