Merge branch 'develop' into feature/create-room

This commit is contained in:
mushka 2022-08-09 19:12:47 +03:00
commit 8f5f597c5f
85 changed files with 1705 additions and 622 deletions

View File

@ -42,6 +42,9 @@ KAFKA_HOST = os.environ["KAFKA_HOST"] if environ.get("KAFKA_HOST") else "kafka:9
RUN_FILE = sys.argv[1] if sys.argv[1] else "none"
LOG_FILE = sys.argv[2] if sys.argv[2] else "none"
REDIS_HOST=os.environ["REDIS_HOST"] if environ.get("REDIS_HOST") else "onlyoffice-redis"
RABBIT_HOST=os.environ["RABBIT_HOST"] if environ.get("RABBIT_HOST") else "onlyoffice-rabbitmq"
class RunServices:
def __init__(self, SERVICE_PORT, PATH_TO_CONF):
self.SERVICE_PORT = SERVICE_PORT
@ -68,7 +71,7 @@ class RunServices:
self.RunService(RUN_FILE, ENV_EXTENSION)
elif ENV_EXTENSION == "none":
os.system("dotnet " + RUN_FILE + " --urls=" + URLS + self.SERVICE_PORT +\
" --$STORAGE_ROOT=" + APP_STORAGE_ROOT +\
" --\'$STORAGE_ROOT\'=" + APP_STORAGE_ROOT +\
" --pathToConf=" + self.PATH_TO_CONF +\
" --log:dir=" + LOG_DIR +\
" --log:name=" + LOG_FILE +\
@ -76,7 +79,7 @@ class RunServices:
" core:products:subfolder=server")
else:
os.system("dotnet " + RUN_FILE + " --urls=" + URLS + self.SERVICE_PORT +\
" --$STORAGE_ROOT=" + APP_STORAGE_ROOT +\
" --\'$STORAGE_ROOT\'=" + APP_STORAGE_ROOT +\
" --pathToConf=" + self.PATH_TO_CONF +\
" --log:dir=" + LOG_DIR +\
" --log:name=" + LOG_FILE +\
@ -159,12 +162,12 @@ writeJsonFile(filePath, jsonData)
filePath = "/app/onlyoffice/config/rabbitmq.json"
jsonData = openJsonFile(filePath)
updateJsonData(jsonData,"$.RabbitMQ.Hostname", "onlyoffice-rebbitmq")
updateJsonData(jsonData,"$.RabbitMQ.Hostname", RABBIT_HOST)
writeJsonFile(filePath, jsonData)
filePath = "/app/onlyoffice/config/redis.json"
jsonData = openJsonFile(filePath)
updateJsonData(jsonData,"$.Redis.Hosts.[0].Host", "onlyoffice-redis")
updateJsonData(jsonData,"$.Redis.Hosts.[0].Host", REDIS_HOST)
writeJsonFile(filePath, jsonData)
run = RunServices(SERVICE_PORT, PATH_TO_CONF)

View File

@ -0,0 +1,13 @@
version: '3'
services:
onlyoffice-rabbitmq:
image: rabbitmq:3
container_name: onlyoffice-rabbitmq
restart: always
expose:
- "5672"
- "80"
networks:
default:
external:
name: ${NETWORK_NAME}

View File

@ -6,15 +6,6 @@ services:
restart: always
expose:
- "6379"
onlyoffice-rebbitmq:
image: rabbitmq:3
container_name: onlyoffice-rebbitmq
restart: always
expose:
- "5672"
- "80"
networks:
default:
external:

View File

@ -34,10 +34,10 @@
<ROW Property="Manufacturer" Value="Ascensio System SIA"/>
<ROW Property="MsiLogging" MultiBuildValue="DefaultBuild:vp"/>
<ROW Property="MySQLConnector" Value="MySQL Connector/ODBC 8.0.21 x86"/>
<ROW Property="PACKAGE_NAME" Value="ONLYOFFICE_AppServer_Win-install.v[|ProductVersion]"/>
<ROW Property="PACKAGE_NAME" Value="ONLYOFFICE_DocSpace_Win-install.v[|ProductVersion]"/>
<ROW Property="PASSWORD_PROP" Value="root"/>
<ROW Property="PORT_PROP" Value="3306"/>
<ROW Property="PRODUCT_NAME" Value="ONLYOFFICE AppServer"/>
<ROW Property="PRODUCT_NAME" Value="ONLYOFFICE DocSpace"/>
<ROW Property="ProductCode" Value="1033:{3FABEB4A-D27F-4BA6-A40E-16BE47540727} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="[|PRODUCT_NAME] [|ProductVersion]"/>
@ -196,7 +196,7 @@
<ROW Action="AI_DetectSoftware" Sequence="151"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="ONLYOFFICE_EXE" BuildOrder="1" BuildType="0" PackageFolder="publish" PackageFileName="[|PACKAGE_NAME]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExeIconPath="Resources\icon.ico" ExtractionFolder="[AppDataFolder][|INSTALL_ROOT_FOLDER_NAME]\AppServer\install" ExtUI="true" UseLargeSchema="true" Unicode="true" ExeName="[|PACKAGE_NAME]" UACExecutionLevel="2"/>
<ROW BuildKey="DefaultBuild" BuildName="ONLYOFFICE_EXE" BuildOrder="1" BuildType="0" PackageFolder="publish" PackageFileName="[|PACKAGE_NAME]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExeIconPath="Resources\icon.ico" ExtractionFolder="[AppDataFolder][|INSTALL_ROOT_FOLDER_NAME]\DocSpace\install" ExtUI="true" UseLargeSchema="true" Unicode="true" ExeName="[|PACKAGE_NAME]" UACExecutionLevel="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
@ -636,12 +636,12 @@
<ROW Action="ElasticSearchSetup" Type="6" Source="utils.vbs" Target="ElasticSearchSetup"/>
<ROW Action="MySQLConfigure" Type="70" Source="utils.vbs" Target="MySQLConfigure"/>
<ROW Action="MySQLConfigureGUI" Type="6" Source="utils.vbs" Target="MySQLConfigure"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder][INSTALL_ROOT_FOLDER_NAME]\AppServer"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder][INSTALL_ROOT_FOLDER_NAME]\AppServer"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
<ROW Action="Set_APPDIR_FORWARD_SLASH" Type="38" Target="Script Text" TargetUnformatted="Session.Property(&quot;APPDIR_FORWARD_SLASH&quot;) = Replace(Session.Property(&quot;APPDIR&quot;), &quot;\&quot;, &quot;/&quot;)&#13;&#10;" AdditionalSeq="AI_DATA_SETTER_6"/>
<ROW Action="StartElasticSearchService" Type="3073" Source="aicustact.dll" Target="StartWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_13"/>
<ROW Action="StartMigrationRunner" Type="3090" Source="ASC.Migration.Runner.exe"/>
<ROW Action="StartMigrationRunner" Type="3106" Source="service_6_Dir" Target="&quot;[APPDIR]services\ASC.Migration.Runner\service\ASC.Migration.Runner.exe&quot;"/>
<ROW Action="StartMySQLService" Type="1" Source="aicustact.dll" Target="StartWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_11"/>
<ROW Action="StopElasticSearchService" Type="1" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_12"/>
<ROW Action="StopMySQLService" Type="1" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_10"/>
@ -740,7 +740,7 @@
<ROW Action="StartElasticSearchService" Condition="( NOT Installed )" Sequence="1613"/>
<ROW Action="AI_DATA_SETTER_13" Condition="( NOT Installed )" Sequence="1612"/>
<ROW Action="AI_GetArpIconPath" Sequence="1401"/>
<ROW Action="StartMigrationRunner" Condition="( NOT Installed )" Sequence="6401"/>
<ROW Action="StartMigrationRunner" Condition="( NOT Installed )" Sequence="5826"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>

View File

@ -57,6 +57,6 @@ del /f /q build\install\win\*.back.*
REM echo ######## Build MySQL Server Installer ########
iscc /Qp /S"byparam="signtool" sign /a /n "%publisher%" /t http://timestamp.digicert.com $f" "build\install\win\MySQL Server Installer Runner.iss"
REM echo ######## Build AppServer package ########
%AdvancedInstaller% /edit build\install\win\AppServer.aip /SetVersion %BUILD_VERSION%.%BUILD_NUMBER%
%AdvancedInstaller% /rebuild build\install\win\AppServer.aip
REM echo ######## Build DocSpace package ########
%AdvancedInstaller% /edit build\install\win\DocSpace.aip /SetVersion %BUILD_VERSION%.%BUILD_NUMBER%
%AdvancedInstaller% /rebuild build\install\win\DocSpace.aip

View File

@ -25,6 +25,7 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using JsonConverter = System.Text.Json.Serialization.JsonConverter;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace ASC.Api.Core;
@ -156,6 +157,12 @@ public abstract class BaseStartup
}
services.AddAutoMapper(typeof(MappingProfile));
if (!_hostEnvironment.IsDevelopment())
{
services.AddStartupTask<WarmupServicesStartupTask>()
.TryAddSingleton(services);
}
}
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)

View File

@ -0,0 +1,92 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Api.Core.Core;
/// <summary>
/// https://andrewlock.net/reducing-latency-by-pre-building-singletons-in-asp-net-core/
/// </summary>
public class WarmupServicesStartupTask : IStartupTask
{
private readonly IServiceCollection _services;
private readonly IServiceProvider _provider;
public WarmupServicesStartupTask(IServiceCollection services, IServiceProvider provider)
{
_services = services;
_provider = provider;
}
public Task ExecuteAsync(CancellationToken cancellationToken)
{
var processedFailed = 0;
var processedSuccessed = 0;
var startTime = DateTime.UtcNow;
using (var scope = _provider.CreateScope())
{
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
var logger = scope.ServiceProvider.GetService<ILogger<WarmupServicesStartupTask>>();
logger.TraceWarmupStarted();
tenantManager.SetCurrentTenant("localhost");
foreach (var service in GetServices(_services))
{
try
{
scope.ServiceProvider.GetServices(service);
processedSuccessed++;
}
catch (Exception ex)
{
processedFailed++;
logger.DebugWarmupFailed(processedFailed, service.FullName, ex.Message);
}
}
var processed = processedSuccessed + processedFailed;
logger.TraceWarmupFinished(processed,
processedSuccessed,
processedFailed,
(DateTime.UtcNow - startTime).TotalMilliseconds);
}
return Task.CompletedTask;
}
static IEnumerable<Type> GetServices(IServiceCollection services)
{
return services
.Where(descriptor => descriptor.ImplementationType != typeof(WarmupServicesStartupTask))
.Where(descriptor => descriptor.ServiceType.ContainsGenericParameters == false)
.Select(descriptor => descriptor.ServiceType)
.Distinct();
}
}

View File

@ -0,0 +1,50 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Api.Core.Extensions;
public interface IStartupTask
{
Task ExecuteAsync(CancellationToken cancellationToken = default);
}
public static class HostExtension
{
public static async Task RunWithTasksAsync(this WebApplication webHost, CancellationToken cancellationToken = default)
{
// Load all tasks from DI
var startupTasks = webHost.Services.GetServices<IStartupTask>();
// Execute all the tasks
foreach (var startupTask in startupTasks)
{
await startupTask.ExecuteAsync(cancellationToken);
}
// Start the tasks as normal
await webHost.RunAsync(cancellationToken);
}
}

View File

@ -168,5 +168,13 @@ public static class ServiceCollectionExtension
services.AddTransient<DistributedTaskQueue>();
services.AddSingleton<IDistributedTaskQueueFactory, DefaultDistributedTaskQueueFactory>();
}
public static IServiceCollection AddStartupTask<T>(this IServiceCollection services)
where T : class, IStartupTask
{
services.AddTransient<IStartupTask, T>();
return services;
}
}

View File

@ -0,0 +1,45 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ASC.Api.Core.Log;
internal static partial class WarmupServicesStartupTaskLogger
{
[LoggerMessage(Level = LogLevel.Trace, Message = "Warm up services is starting...")]
public static partial void TraceWarmupStarted(this ILogger<WarmupServicesStartupTask> logger);
[LoggerMessage(Level = LogLevel.Trace, Message = "Warm up services finished. Processed: {processed}, Successed: {successed}, Failed: {failed}, Time: {processedTime} ms")]
public static partial void TraceWarmupFinished(this ILogger<WarmupServicesStartupTask> logger, int processed, int successed, int failed, double processedTime);
[LoggerMessage(Level = LogLevel.Debug, Message = "#{index} Failed proccessed {serviceTitle} service with exception {errorMessage}")]
public static partial void DebugWarmupFailed(this ILogger<WarmupServicesStartupTask> logger, int index, String serviceTitle, String errorMessage);
}

View File

@ -40,19 +40,43 @@ public class MappingProfile : Profile
{
return;
}
var types = assembly.GetExportedTypes().Where(t => t.IsClosedTypeOf(typeof(IMapFrom<>)) || (t.IsGenericType && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>))));
foreach (var type in types)
{
var mapFromType = typeof(IMapFrom<>);
var mappingMethodName = nameof(IMapFrom<object>.Mapping);
bool HasInterface(Type t) => t.IsGenericType && t.GetGenericTypeDefinition() == mapFromType;
var types = assembly.GetExportedTypes().Where(t => t.GetInterfaces().Any(HasInterface)).ToList();
var argumentTypes = new Type[] { typeof(Profile) };
foreach (var type in types)
{
var resolvedType = type.IsGenericType ? type.MakeGenericType(new[] { typeof(int) }) : type;
var instance = Activator.CreateInstance(resolvedType);
var methodInfo = resolvedType.GetMethod("Mapping")
?? resolvedType.GetInterface("IMapFrom`1").GetMethod("Mapping");
methodInfo?.Invoke(instance, new object[] { this });
var methodInfo = resolvedType.GetMethod(mappingMethodName);
if (methodInfo != null)
{
methodInfo.Invoke(instance, new object[] { this });
}
else
{
var interfaces = resolvedType.GetInterfaces().Where(HasInterface).ToList();
if (interfaces.Count > 0)
{
foreach (var @interface in interfaces)
{
var interfaceMethodInfo = @interface.GetMethod(mappingMethodName, argumentTypes);
interfaceMethodInfo?.Invoke(instance, new object[] { this });
}
}
}
}
}

View File

@ -48,4 +48,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
app.Run();
await app.RunWithTasksAsync();

View File

@ -45,4 +45,5 @@ builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
});
var app = builder.Build();
await app.RunAsync();
await app.RunWithTasksAsync();

View File

@ -63,7 +63,7 @@ eventBus.Subscribe<BackupRequestIntegrationEvent, BackupRequestedIntegrationEven
eventBus.Subscribe<BackupRestoreRequestIntegrationEvent, BackupRestoreRequestedIntegrationEventHandler>();
eventBus.Subscribe<IntegrationEvent, BackupDeleteScheldureRequestedIntegrationEventHandler>();
app.Run();
await app.RunWithTasksAsync();
public partial class Program

View File

@ -56,4 +56,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
app.Run();
await app.RunWithTasksAsync();

View File

@ -82,7 +82,7 @@ var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService
eventBus.Subscribe<NotifyInvokeSendMethodRequestedIntegrationEvent, NotifyInvokeSendMethodRequestedIntegrationEventHandler>();
eventBus.Subscribe<NotifySendMessageRequestedIntegrationEvent, NotifySendMessageRequestedIntegrationEventHandler>();
app.Run();
await app.RunWithTasksAsync();
public partial class Program
{

View File

@ -65,4 +65,4 @@ var app = builder.Build();
startup.Configure(app);
await app.RunAsync();
await app.RunWithTasksAsync();

View File

@ -57,7 +57,7 @@ var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService
eventBus.Subscribe<ASC.Core.Common.Notify.IntegrationEvents.Events.NotifySendTelegramMessageRequestedIntegrationEvent, TelegramSendMessageRequestedIntegrationEventHandler>();
app.Run();
await app.RunWithTasksAsync();
public partial class Program
{

View File

@ -58,4 +58,4 @@ var app = builder.Build();
startup.Configure(app);
await app.RunAsync();
await app.RunWithTasksAsync();

View File

@ -248,8 +248,8 @@ const withHotkeys = (Component) => {
deleteOperation: t("Translations:DeleteOperation"),
deleteFromTrash: t("Translations:DeleteFromTrash"),
deleteSelectedElem: t("Translations:DeleteSelectedElem"),
FileRemoved: t("Home:FileRemoved"),
FolderRemoved: t("Home:FolderRemoved"),
FileRemoved: t("Files:FileRemoved"),
FolderRemoved: t("Files:FolderRemoved"),
};
deleteAction(translations).catch((err) => toastr.error(err));
}

View File

@ -15,8 +15,7 @@ import { combineUrl, updateTempContent } from "@docspace/common/utils";
import { Provider as MobxProvider } from "mobx-react";
import ThemeProvider from "@docspace/components/theme-provider";
import store from "client/store";
import filesStores from "./store/index.Files";
import store from "SRC_DIR/store";
import config from "PACKAGE_FILE";
import { I18nextProvider, useTranslation } from "react-i18next";
@ -600,7 +599,7 @@ const ThemeProviderWrapper = inject(({ auth }) => {
})(observer(ThemeProvider));
export default () => (
<MobxProvider {...store} {...filesStores}>
<MobxProvider {...store}>
<I18nextProvider i18n={i18n}>
<ThemeProviderWrapper>
<ShellWrapper />

View File

@ -170,7 +170,7 @@ const ArticleMainButtonContent = (props) => {
id: "main-button_new-room",
className: "main-button_drop-down",
icon: "images/folder.locked.react.svg",
label: t("Home:NewRoom"),
label: t("Files:NewRoom"),
onClick: onCreateRoom,
action: "room",
key: "room",

View File

@ -113,7 +113,7 @@ const RenameEvent = ({
<Dialog
t={t}
visible={visible}
title={t("Home: Rename")}
title={t("Files:Rename")}
startValue={startValue}
onSave={onUpdate}
onCancel={onCancel}

View File

@ -140,11 +140,12 @@ class NavMenu extends React.Component {
history,
isDesktop,
preparationPortalDialogVisible,
isFrame,
showHeader,
} = this.props;
const isAsideAvailable = !!asideContent;
const hideHeader =
isDesktop || history.location.pathname === "/products/files/private";
const hideHeader = isDesktop || (!showHeader && isFrame);
//console.log("NavMenu render", this.state, this.props);
const isPreparationPortal =
history.location.pathname === "/preparation-portal";
@ -221,7 +222,7 @@ NavMenu.defaultProps = {
const NavMenuWrapper = inject(({ auth, backup }) => {
const { settingsStore, isAuthenticated, isLoaded, language } = auth;
const { isDesktopClient: isDesktop } = settingsStore;
const { isDesktopClient: isDesktop, frameConfig, isFrame } = settingsStore;
const { preparationPortalDialogVisible } = backup;
return {
isAuthenticated,
@ -229,6 +230,8 @@ const NavMenuWrapper = inject(({ auth, backup }) => {
isDesktop,
language,
preparationPortalDialogVisible,
showHeader: frameConfig?.showHeader,
isFrame,
};
})(observer(withTranslation(["NavMenu", "Common"])(withRouter(NavMenu))));

View File

@ -83,7 +83,7 @@ const PureConnectDialogContainer = (props) => {
//const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate
if (title.match(folderFormValidation)) {
toastr.warning(t("Home:ContainsSpecCharacter"));
toastr.warning(t("Files:ContainsSpecCharacter"));
}
title = title.replace(folderFormValidation, "_");

View File

@ -59,8 +59,8 @@ const DeleteDialogComponent = (props) => {
deleteOperation: t("Translations:DeleteOperation"),
deleteFromTrash: t("Translations:DeleteFromTrash"),
deleteSelectedElem: t("Translations:DeleteSelectedElem"),
FileRemoved: t("Home:FileRemoved"),
FolderRemoved: t("Home:FolderRemoved"),
FileRemoved: t("Files:FileRemoved"),
FolderRemoved: t("Files:FolderRemoved"),
};
if (!selection.length) return;
@ -156,6 +156,7 @@ const DeleteDialog = withTranslation([
"DeleteDialog",
"Common",
"Translations",
"Files",
])(DeleteDialogComponent);
export default inject(

View File

@ -161,7 +161,7 @@ const OperationsPanelComponent = (props) => {
? t("Common:Restore")
: isCopy
? t("Translations:Copy")
: t("Home:MoveTo")
: t("Files:MoveTo")
}
buttonName={
isRecycleBin

View File

@ -2,8 +2,7 @@ import React from "react";
import { Provider as MobxProvider, inject, observer } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import SelectFileDialog from "./index";
import stores from "../../../store/index.Files";
import store from "client/store";
import store from "SRC_DIR/store";
import i18n from "./i18n";
const { auth: authStore } = store;
@ -32,7 +31,7 @@ class SelectFileDialogWrapper extends React.Component {
render() {
return (
<MobxProvider auth={authStore} {...stores}>
<MobxProvider {...store}>
<I18nextProvider i18n={i18n}>
<SelectFileWrapper {...this.props} />
</I18nextProvider>

View File

@ -1,8 +1,7 @@
import React from "react";
import { Provider as MobxProvider } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import stores from "../../../store/index.Files";
import store from "client/store";
import store from "SRC_DIR/store";
import SelectFileInput from "./index";
import i18n from "./i18n";
const { auth: authStore } = store;
@ -16,7 +15,7 @@ class SelectFileInputWrapper extends React.Component {
render() {
return (
<MobxProvider auth={authStore} {...stores}>
<MobxProvider {...store}>
<I18nextProvider i18n={i18n}>
<SelectFileModalWrapper {...this.props} />
</I18nextProvider>

View File

@ -1,10 +1,10 @@
import React from "react";
import { Provider as MobxProvider, inject, observer } from "mobx-react";
import PropTypes from "prop-types";
import stores from "../../../store/index.Files";
import SelectFileDialog from "../SelectFileDialog";
import StyledComponent from "./StyledSelectFileInput";
import SimpleFileInput from "../../SimpleFileInput";
import store from "SRC_DIR/store";
class SelectFileInputBody extends React.PureComponent {
constructor(props) {
@ -88,7 +88,7 @@ const SelectFileInputBodyWrapper = inject(({ filesStore }) => {
class SelectFileInput extends React.Component {
render() {
return (
<MobxProvider {...stores}>
<MobxProvider {...store}>
<SelectFileInputBodyWrapper {...this.props} />
</MobxProvider>
);

View File

@ -1,8 +1,7 @@
import React from "react";
import { Provider as MobxProvider, inject, observer } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import stores from "../../../store/index.Files";
import store from "client/store";
import store from "SRC_DIR/store";
import SelectFolderDialog from "./index";
import i18n from "./i18n";
import { getFolder } from "@docspace/common/api/files";
@ -76,7 +75,7 @@ class SelectFolderModal extends React.Component {
render() {
return (
<MobxProvider auth={authStore} {...stores}>
<MobxProvider {...store}>
<I18nextProvider i18n={i18n}>
<SelectFolderModalWrapper {...this.props} />
</I18nextProvider>

View File

@ -1,10 +1,9 @@
import React from "react";
import { Provider as MobxProvider } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import stores from "../../../store/index.Files";
import store from "client/store";
import SelectFolderInput from "./index";
import i18n from "./i18n";
import store from "SRC_DIR/store";
const { auth: authStore } = store;
const SelectFolderModalWrapper = (props) => <SelectFolderInput {...props} />;
@ -16,7 +15,7 @@ class SelectFolderInputWrapper extends React.Component {
render() {
return (
<MobxProvider auth={authStore} {...stores}>
<MobxProvider {...store}>
<I18nextProvider i18n={i18n}>
<SelectFolderModalWrapper {...this.props} />
</I18nextProvider>

View File

@ -196,7 +196,7 @@ const FilesListBody = ({
<div className="select-file-dialog_empty-container">
<EmptyContainer
theme={theme}
headerText={t("Home:EmptyFolderHeader")}
headerText={t("Files:EmptyFolderHeader")}
imageSrc="/static/images/empty.screen.react.svg"
/>
</div>

View File

@ -2,10 +2,7 @@ import React, { useEffect } from "react";
import { Provider as MobxProvider, inject, observer } from "mobx-react";
import { getShareFiles } from "@docspace/common/api/files";
import SharingPanel from "../SharingPanel";
import stores from "../../../store/index.Files";
import store from "client/store";
import store from "SRC_DIR/store";
const { auth: authStore } = store;
const SharingDialog = ({
@ -69,7 +66,7 @@ class SharingModal extends React.Component {
render() {
return (
<MobxProvider auth={authStore} {...stores}>
<MobxProvider {...store}>
<SharingDialogWrapper {...this.props} />
</MobxProvider>
);

View File

@ -86,7 +86,7 @@ class UploadPanelComponent extends React.Component {
? t("Uploads")
: isUploadingAndConversion
? t("UploadAndConvert")
: t("Home:Convert");
: t("Files:Convert");
return (
<StyledAsidePanel visible={visible}>

View File

@ -1,9 +1,8 @@
import filesStore from "../store";
import store from "client/store";
import store from "SRC_DIR/store";
import { desktopConstants } from "@docspace/common/desktop";
export function encryptionUploadDialog(callback) {
const filter = filesStore.settingsStore.extsWebEncrypt
const filter = store.filesStore.settingsStore.extsWebEncrypt
.map((f) => "*" + f)
.join(" ");

View File

@ -1,4 +1,4 @@
import authStore from "@docspace/common/store/AuthStore";
import authStore from "SRC_DIR/store/AuthStore";
import { AppServerConfig, RoomsType } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { combineUrl, toUrlParams } from "@docspace/common/utils";

View File

@ -1,4 +1,4 @@
import authStore from "@docspace/common/store/AuthStore";
import authStore from "SRC_DIR/store/AuthStore";
import { toCommunityHostname } from "@docspace/common/utils";
import history from "@docspace/common/history";
import { useEffect, useState } from "react";

View File

@ -203,13 +203,17 @@ class FilesContent extends React.Component {
}
render() {
//const { /*, isDesktop*/ } = this.props;
const { showArticle, isFrame } = this.props;
return (
<>
<GlobalEvents />
<Panels />
<FilesArticle history={this.props.history} />
{isFrame ? (
showArticle && <FilesArticle history={this.props.history} />
) : (
<FilesArticle history={this.props.history} />
)}
<FilesSection />
</>
);
@ -217,16 +221,26 @@ class FilesContent extends React.Component {
}
const Files = inject(({ auth, filesStore }) => {
const {
frameConfig,
isFrame,
isDesktopClient,
encryptionKeys,
setEncryptionKeys,
isEncryptionSupport,
} = auth.settingsStore;
return {
isDesktop: auth.settingsStore.isDesktopClient,
isDesktop: isDesktopClient,
isFrame,
showArticle: frameConfig?.showArticle,
user: auth.userStore.user,
isAuthenticated: auth.isAuthenticated,
encryptionKeys: auth.settingsStore.encryptionKeys,
isEncryption: auth.settingsStore.isEncryptionSupport,
encryptionKeys: encryptionKeys,
isEncryption: isEncryptionSupport,
isLoaded: auth.isLoaded && filesStore.isLoaded,
setIsLoaded: filesStore.setIsLoaded,
setEncryptionKeys: auth.settingsStore.setEncryptionKeys,
setEncryptionKeys: setEncryptionKeys,
loadFilesInfo: async () => {
await filesStore.initFiles();
//auth.setProductVersion(config.version);

View File

@ -55,7 +55,9 @@ const SingleItem = (props) => {
<StyledProperties>
<div className="property">
<Text className="property-title">{t("Home:ByLastModifiedDate")}</Text>
<Text className="property-title">
{t("Files:ByLastModifiedDate")}
</Text>
<Text className="property-content">
{parseAndFormatDate(selectedItem.attributes.updatedAt)}
</Text>

View File

@ -101,13 +101,13 @@ const SingleItem = (props) => {
case FileType.Image:
return t("Common:Image");
case FileType.Spreadsheet:
return t("Home:Spreadsheet");
return t("Files:Spreadsheet");
case FileType.Presentation:
return t("Home:Presentation");
return t("Files:Presentation");
case FileType.Document:
return t("Home:Document");
return t("Files:Document");
default:
return t("Home:Folder");
return t("Files:Folder");
}
};
@ -147,7 +147,7 @@ const SingleItem = (props) => {
},
{
id: "ByLastModifiedDate",
title: t("Home:ByLastModifiedDate"),
title: t("Files:ByLastModifiedDate"),
content: styledText(parseAndFormatDate(item.updated)),
},
{
@ -162,7 +162,7 @@ const SingleItem = (props) => {
},
{
id: "ByCreationDate",
title: t("Home:ByCreationDate"),
title: t("Files:ByCreationDate"),
content: styledText(parseAndFormatDate(item.created)),
},
];

View File

@ -7,140 +7,6 @@ class FilesTableHeader extends React.Component {
constructor(props) {
super(props);
// const defaultColumns = [];
// if (isRooms) {
// const columns = [
// {
// key: "Name",
// title: t("Common:Name"),
// resizable: true,
// enable: true,
// default: true,
// sortBy: "AZ",
// minWidth: 210,
// onClick: this.onRoomsFilter,
// },
// {
// key: "Type",
// title: t("Common:Type"),
// enable: false,
// resizable: true,
// sortBy: "roomType",
// onChange: this.onColumnChange,
// onClick: this.onRoomsFilter,
// },
// {
// key: "Tags",
// title: t("Tags"),
// enable: true,
// resizable: true,
// sortBy: "Tags",
// onChange: this.onColumnChange,
// onClick: this.onRoomsFilter,
// },
// {
// key: "Owner",
// title: t("ByOwner"),
// enable: false,
// resizable: true,
// sortBy: "Author",
// onChange: this.onColumnChange,
// onClick: this.onRoomsFilter,
// },
// {
// key: "Activity",
// title: t("ByLastModifiedDate"),
// enable: true,
// resizable: true,
// sortBy: "DateAndTime",
// onChange: this.onColumnChange,
// onClick: this.onRoomsFilter,
// },
// ];
// defaultColumns.push(...columns);
// } else {
// const columns = [
// {
// key: "Name",
// title: t("Common:Name"),
// resizable: true,
// enable: true,
// default: true,
// sortBy: "AZ",
// minWidth: 210,
// onClick: this.onFilter,
// },
// {
// key: "Author",
// title: t("ByAuthor"),
// enable: false,
// resizable: true,
// sortBy: "Author",
// onClick: this.onFilter,
// onChange: this.onColumnChange,
// },
// {
// key: "Created",
// title: t("ByCreationDate"),
// enable: true,
// resizable: true,
// sortBy: "DateAndTimeCreation",
// onClick: this.onFilter,
// onChange: this.onColumnChange,
// },
// {
// key: "Modified",
// title: t("ByLastModifiedDate"),
// enable: true,
// resizable: true,
// sortBy: "DateAndTime",
// onClick: this.onFilter,
// onChange: this.onColumnChange,
// },
// {
// key: "Size",
// title: t("Common:Size"),
// enable: true,
// resizable: true,
// sortBy: "Size",
// onClick: this.onFilter,
// onChange: this.onColumnChange,
// },
// {
// key: "Type",
// title: t("Common:Type"),
// enable: true,
// resizable: true,
// sortBy: "Type",
// onClick: this.onFilter,
// onChange: this.onColumnChange,
// },
// {
// key: "QuickButtons",
// title: "",
// enable: true,
// defaultSize: 75,
// resizable: false,
// },
// ];
// personal && columns.splice(1, 1);
// defaultColumns.push(...columns);
// }
// const storageColumns = localStorage.getItem(tableStorageName);
// const splitColumns = storageColumns && storageColumns.split(",");
// const columns = this.getColumns(defaultColumns, splitColumns);
// const resetColumnsSize =
// (splitColumns && splitColumns.length !== columns.length) ||
// !splitColumns ||
// isRooms;
// const tableColumns = columns.map((c) => c.enable && c.key);
// this.setTableColumns(tableColumns);
this.getTableColumns();
this.isBeginScrolling = false;

View File

@ -9,7 +9,12 @@ import {
import axios from "axios";
import toastr from "@docspace/components/toast/toastr";
import Section from "@docspace/common/components/Section";
import { showLoader, hideLoader } from "@docspace/common/utils";
import {
showLoader,
hideLoader,
frameCallbackData,
frameCallCommand,
} from "@docspace/common/utils";
import FilesFilter from "@docspace/common/api/files/filter";
import { getGroup } from "@docspace/common/api/groups";
import { getUserById } from "@docspace/common/api/people";
@ -242,6 +247,8 @@ class PureHome extends React.Component {
setFirstLoad(false);
setAlreadyFetchingRooms(false);
});
window.addEventListener("message", this.handleMessage, false);
}
fetchDefaultFiles = () => {
@ -355,6 +362,115 @@ class PureHome extends React.Component {
}
}
componentWillUnmount() {
window.removeEventListener("message", this.handleMessage, false);
}
handleMessage = async (e) => {
const {
setFrameConfig,
user,
folders,
files,
selection,
filesList,
selectedFolderStore,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
} = this.props;
const eventData = typeof e.data === "string" ? JSON.parse(e.data) : e.data;
if (eventData.data) {
const { data, methodName } = eventData.data;
let res;
switch (methodName) {
case "setConfig":
res = await setFrameConfig(data);
break;
case "getFolderInfo":
res = selectedFolderStore;
break;
case "getFolders":
res = folders;
break;
case "getFiles":
res = files;
break;
case "getList":
res = filesList;
break;
case "getSelection":
res = selection;
break;
case "getUserInfo":
res = user;
break;
case "openModal": {
const { type, options } = data;
if (type === "CreateFile" || type === "CreateFolder") {
const item = new Event(Events.CREATE);
const payload = {
extension: options,
id: -1,
};
item.payload = payload;
window.dispatchEvent(item);
}
if (type === "CreateRoom") {
const room = new Event(Events.ROOM_CREATE);
window.dispatchEvent(room);
}
break;
}
case "createFile":
{
const { folderId, title, templateId, formId } = data;
res = await createFile(folderId, title, templateId, formId);
refreshFiles();
}
break;
case "createFolder":
{
const { parentFolderId, title } = data;
res = await createFolder(parentFolderId, title);
refreshFiles();
}
break;
case "createRoom":
{
const { title, type } = data;
res = await createRoom(title, type);
refreshFiles();
}
break;
case "setListView":
{
setViewAs(data);
}
break;
default:
res = "Wrong method";
}
frameCallbackData(res);
}
};
render() {
//console.log("Home render");
const {
@ -382,8 +498,16 @@ class PureHome extends React.Component {
checkedMaintenance,
setMaintenanceExist,
snackbarExist,
isFrame,
showTitle,
showFilter,
frameConfig,
} = this.props;
if (window.parent && !frameConfig) {
frameCallCommand("setConfig");
}
return (
<>
<MediaViewer />
@ -414,7 +538,11 @@ class PureHome extends React.Component {
firstLoad={firstLoad}
>
<Section.SectionHeader>
<SectionHeaderContent />
{isFrame ? (
showTitle && <SectionHeaderContent />
) : (
<SectionHeaderContent />
)}
</Section.SectionHeader>
<Section.SectionBar>
@ -428,7 +556,11 @@ class PureHome extends React.Component {
</Section.SectionBar>
<Section.SectionFilter>
<SectionFilterContent />
{isFrame ? (
showFilter && <SectionFilterContent />
) : (
<SectionFilterContent />
)}
</Section.SectionFilter>
<Section.SectionBody>
@ -492,6 +624,16 @@ export default inject(
getFileInfo,
gallerySelected,
setIsUpdatingRowItem,
folders,
files,
filesList,
selectedFolderStore,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
} = filesStore;
const {
@ -534,6 +676,19 @@ export default inject(
: null;
const { setToPreviewFile, playlist } = mediaViewerDataStore;
const {
checkedMaintenance,
setMaintenanceExist,
snackbarExist,
isHeaderVisible,
setHeaderVisible,
personal,
setFrameConfig,
frameConfig,
isFrame,
} = auth.settingsStore;
if (!firstLoad) {
if (isLoading) {
showLoader();
@ -552,9 +707,9 @@ export default inject(
isRecycleBinFolder,
isPrivacyFolder,
isVisitor: auth.userStore.user.isVisitor,
checkedMaintenance: auth.settingsStore.checkedMaintenance,
setMaintenanceExist: auth.settingsStore.setMaintenanceExist,
snackbarExist: auth.settingsStore.snackbarExist,
checkedMaintenance,
setMaintenanceExist,
snackbarExist,
expandedKeys,
primaryProgressDataVisible,
@ -589,15 +744,32 @@ export default inject(
setSelections,
startUpload,
uploadEmptyFolders,
isHeaderVisible: auth.settingsStore.isHeaderVisible,
setHeaderVisible: auth.settingsStore.setHeaderVisible,
personal: auth.settingsStore.personal,
isHeaderVisible,
setHeaderVisible,
personal,
setToPreviewFile,
playlist,
isMediaOrImage: settingsStore.isMediaOrImage,
getFileInfo,
gallerySelected,
setIsUpdatingRowItem,
setFrameConfig,
frameConfig,
isFrame,
showTitle: frameConfig?.showTitle,
showFilter: frameConfig?.showFilter,
user: auth.userStore.user,
folders,
files,
selection,
filesList,
selectedFolderStore,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
};
}
)(withRouter(observer(Home)));

View File

@ -1,35 +1,85 @@
import React, { lazy, Suspense } from "react";
import { Route, Switch } from "react-router-dom";
import React, { useEffect, useState } from "react";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import Loader from "@docspace/components/loader";
import { withTranslation } from "react-i18next";
import { isMobile } from "react-device-detect";
import { combineUrl } from "@docspace/common/utils";
import AppServerConfig from "@docspace/common/constants/AppServerConfig";
import AppLoader from "@docspace/common/components/AppLoader";
const ThirdPartyServices = lazy(() => import("./thirdPartyServicesSettings"));
import Submenu from "@docspace/components/submenu";
const PROXY_BASE_URL = combineUrl(
AppServerConfig.proxyURL,
"/portal-settings/integration"
);
import ThirdPartyServices from "./thirdPartyServicesSettings";
import PortalIntegration from "./portalIntegration";
import config from "PACKAGE_FILE";
const Integration = (props) => {
const { t, history } = props;
const [currentTab, setCurrentTab] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const integrationData = {
id: "portal-integration",
name: "Portal Integration",
content: <PortalIntegration />,
};
const data = [
{
id: "third-party-services",
name: t("ThirdPartyAuthorization"),
content: <ThirdPartyServices />,
},
];
if (!isMobile) data.push(integrationData);
const load = async () => {
const { loadBaseInfo } = props;
await loadBaseInfo();
const path = location.pathname;
const currentTab = data.findIndex((item) => path.includes(item.id));
if (currentTab !== -1) setCurrentTab(currentTab);
setIsLoading(true);
};
useEffect(() => {
load();
}, []);
const onSelect = (e) => {
history.push(
combineUrl(
AppServerConfig.proxyURL,
config.homepage,
`/portal-settings/integration/${e.id}`
)
);
};
if (!isLoading) return <AppLoader />;
const Integration = ({ match }) => {
return (
<Suspense
fallback={<Loader className="pageLoader" type="rombs" size="40px" />}
>
<Switch>
<Route
exact
path={[
combineUrl(PROXY_BASE_URL, "/third-party-services"),
combineUrl(AppServerConfig.proxyURL, "/integration"),
match.path,
]}
component={ThirdPartyServices}
/>
</Switch>
</Suspense>
<Submenu
data={data}
startSelect={currentTab}
onSelect={(e) => onSelect(e)}
/>
);
};
export default withRouter(Integration);
export default inject(({ setup }) => {
const { initSettings } = setup;
return {
loadBaseInfo: async () => {
await initSettings();
},
};
})(withTranslation("Settings")(withRouter(observer(Integration))));

View File

@ -0,0 +1,456 @@
import React, { useState, useEffect } from "react";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import Box from "@docspace/components/box";
import TextInput from "@docspace/components/text-input";
import Textarea from "@docspace/components/textarea";
import Label from "@docspace/components/label";
import Checkbox from "@docspace/components/checkbox";
import Button from "@docspace/components/button";
import ComboBox from "@docspace/components/combobox";
import Heading from "@docspace/components/heading";
import toastr from "@docspace/components/toast/toastr";
import { tablet } from "@docspace/components/utils/device";
import { objectToGetParams, loadScript } from "@docspace/common/utils";
import { inject, observer } from "mobx-react";
const Controls = styled(Box)`
width: 500px;
display: flex;
flex-direction: column;
gap: 16px;
@media ${tablet} {
width: 100%;
}
.label {
min-width: fit-content;
}
`;
const ControlsGroup = styled(Box)`
display: flex;
flex-direction: column;
gap: 8px;
`;
const Frame = styled(Box)`
margin-top: 16px;
> div {
border: 1px dashed gray;
border-radius: 3px;
min-width: 100%;
min-height: 400px;
}
`;
const Buttons = styled(Box)`
margin-top: 16px;
button {
margin-right: 16px;
}
`;
const Container = styled(Box)`
width: 100%;
display: flex;
gap: 16px;
`;
const Preview = styled(Box)`
width: 50%;
flex-direction: row;
.frameStyle {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
`;
const PortalIntegration = (props) => {
const { t, setDocumentTitle } = props;
setDocumentTitle(`Portal integration`);
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
const dataSortBy = [
{ key: "DateAndTime", label: "Last modified date", default: true },
{ key: "AZ", label: "Title" },
{ key: "Type", label: "Type" },
{ key: "Size", label: "Size" },
{ key: "DateAndTimeCreation", label: "Creation date" },
{ key: "Author", label: "Author" },
];
const dataFilterType = [
{ key: 0, label: "None", default: true },
{ key: 1, label: "Files" },
{ key: 2, label: "Folders" },
{ key: 3, label: "Documents" },
{ key: 4, label: "Presentations" },
{ key: 5, label: "Spreadsheets" },
{ key: 7, label: "Images" },
{ key: 8, label: "By user" },
{ key: 9, label: "By department" },
{ key: 10, label: "Archive" },
{ key: 11, label: "By Extension" },
{ key: 12, label: "Media" },
];
const dataSortOrder = [
{ key: "descending", label: "Descending", default: true },
{ key: "ascending", label: "Ascending" },
];
const dataDisplayType = [
{ key: "row", label: "Row", default: true },
{ key: "table", label: "Table" },
{ key: "tile", label: "Tile" },
];
const [config, setConfig] = useState({
width: "100%",
height: "400px",
frameId: "ds-frame",
showHeader: false,
showTitle: true,
showArticle: false,
showFilter: false,
});
const [sortBy, setSortBy] = useState(dataSortBy[0]);
const [sortOrder, setSortOrder] = useState(dataSortOrder[0]);
const [filterType, setFilterType] = useState(dataFilterType[0]);
const [displayType, setDisplayType] = useState(dataDisplayType[0]);
const [withSubfolders, setWithSubfolders] = useState(false);
const params = objectToGetParams(config);
const frameId = config.frameId || "ds-frame";
const destroyFrame = () => {
DocSpace.destroyFrame();
};
const loadFrame = () => {
const script = document.getElementById("integration");
if (script) {
destroyFrame();
script.remove();
}
const params = objectToGetParams(config);
loadScript(`${scriptUrl}${params}`, "integration");
};
const onChangeWidth = (e) => {
setConfig((config) => {
return { ...config, width: e.target.value };
});
};
const onChangeHeight = (e) => {
setConfig((config) => {
return { ...config, height: e.target.value };
});
};
const onChangeFolderId = (e) => {
setConfig((config) => {
return { ...config, folder: e.target.value };
});
};
const onChangeFrameId = (e) => {
setConfig((config) => {
return { ...config, frameId: e.target.value };
});
};
const onChangeWithSubfolders = (e) => {
setConfig((config) => {
return { ...config, withSubfolders: !withSubfolders };
});
setWithSubfolders(!withSubfolders);
};
const onChangeSortBy = (item) => {
setConfig((config) => {
return { ...config, sortby: item.key };
});
setSortBy(item);
};
const onChangeSortOrder = (item) => {
setConfig((config) => {
return { ...config, sortorder: item.key };
});
setSortOrder(item);
};
const onChangeFilterType = (item) => {
setConfig((config) => {
return { ...config, filterType: item.key };
});
setFilterType(item);
};
const onChangeDisplayType = (item) => {
setConfig((config) => {
return { ...config, viewAs: item.key };
});
setDisplayType(item);
};
const onChangeShowHeader = (e) => {
setConfig((config) => {
return { ...config, showHeader: !config.showHeader };
});
};
const onChangeShowTitle = () => {
setConfig((config) => {
return { ...config, showTitle: !config.showTitle };
});
};
const onChangeShowArticle = (e) => {
setConfig((config) => {
return { ...config, showArticle: !config.showArticle };
});
};
const onChangeShowFilter = (e) => {
setConfig((config) => {
return { ...config, showFilter: !config.showFilter };
});
};
const onChangeCount = (e) => {
setConfig((config) => {
return { ...config, count: e.target.value };
});
};
const onChangePage = (e) => {
setConfig((config) => {
return { ...config, page: e.target.value };
});
};
const onChangeSearch = (e) => {
setConfig((config) => {
return { ...config, search: e.target.value };
});
};
const onChangeAuthor = (e) => {
setConfig((config) => {
return { ...config, authorType: e.target.value };
});
};
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
return (
<Container>
<Controls>
<Heading level={1} size="small">
Frame options
</Heading>
<ControlsGroup>
<Label className="label" text="Frame id" />
<TextInput
scale={true}
onChange={onChangeFrameId}
placeholder="Frame id"
value={config.frameId}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Frame width" />
<TextInput
scale={true}
onChange={onChangeWidth}
placeholder="Frame width"
value={config.width}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Frame height" />
<TextInput
scale={true}
onChange={onChangeHeight}
placeholder="Frame height"
value={config.height}
/>
</ControlsGroup>
{/* <ControlsGroup>
<Label className="label" text="Display mode: " />
<ComboBox
scale={true}
onSelect={onChangeDisplayType}
options={dataDisplayType}
scaled={true}
selectedOption={displayType}
displaySelectedOption
/>
</ControlsGroup> */}
<Checkbox
label="Show header"
onChange={onChangeShowHeader}
isChecked={config.showHeader}
/>
<Checkbox
label="Show title"
onChange={onChangeShowTitle}
isChecked={config.showTitle}
/>
<Checkbox
label="Show article"
onChange={onChangeShowArticle}
isChecked={config.showArticle}
/>
<Checkbox
label="Show filter"
onChange={onChangeShowFilter}
isChecked={config.showFilter}
/>
<Heading level={1} size="small">
Filter options
</Heading>
<ControlsGroup>
<Label className="label" text="Folder id" />
<TextInput
scale={true}
onChange={onChangeFolderId}
placeholder="Folder id"
value={config.folder}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Items count" />
<TextInput
scale={true}
onChange={onChangeCount}
placeholder="Items count"
value={config.count}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Page" />
<TextInput
scale={true}
onChange={onChangePage}
placeholder="Page"
value={config.page}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Search term" />
<Box style={{ flexDirection: "row", display: "flex", gap: "16px" }}>
<TextInput
scale={true}
onChange={onChangeSearch}
placeholder="Search term"
value={config.search}
/>
<Checkbox
label="With subfolders"
onChange={onChangeWithSubfolders}
isChecked={withSubfolders}
/>
</Box>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Author" />
<TextInput
scale={true}
onChange={onChangeAuthor}
placeholder="Author"
value={config.authorType}
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Filter type:" />
<ComboBox
onSelect={onChangeFilterType}
options={dataFilterType}
scaled={true}
selectedOption={filterType}
displaySelectedOption
directionY="top"
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Sort by:" />
<ComboBox
onSelect={onChangeSortBy}
options={dataSortBy}
scaled={true}
selectedOption={sortBy}
displaySelectedOption
directionY="top"
/>
</ControlsGroup>
<ControlsGroup>
<Label className="label" text="Sort order:" />
<ComboBox
onSelect={onChangeSortOrder}
options={dataSortOrder}
scaled={true}
selectedOption={sortOrder}
displaySelectedOption
directionY="top"
/>
</ControlsGroup>
</Controls>
<Preview>
<Frame>
<Box id={frameId} className="frameStyle">
Frame content
</Box>
</Frame>
<Buttons>
<Button primary size="normal" label="Preview" onClick={loadFrame} />
<Button
primary
size="normal"
label="Destroy"
onClick={destroyFrame}
/>
</Buttons>
<Heading level={1} size="xsmall">
Paste this code block on page:
</Heading>
<Textarea value={codeBlock} />
</Preview>
</Container>
);
};
export default inject(({ setup, auth }) => {
const { settingsStore, setDocumentTitle } = auth;
const { theme } = settingsStore;
return {
theme,
setDocumentTitle,
};
})(withTranslation(["Settings", "Common"])(observer(PortalIntegration)));

View File

@ -61,6 +61,8 @@ const WhiteLabel = lazy(() =>
const Branding = lazy(() => import("./categories/common/branding"));
const Integration = lazy(() => import("./categories/integration"));
const PROXY_BASE_URL = combineUrl(AppServerConfig.proxyURL, "/portal-settings");
const COMMON_URLS = [
@ -120,10 +122,12 @@ const SESSION_LIFETIME_PAGE_URL = combineUrl(
);
const ADMINS_URL = combineUrl(PROXY_BASE_URL, "/security/access-rights/admins");
const THIRD_PARTY_URL = combineUrl(
PROXY_BASE_URL,
"/integration/third-party-services"
);
const INTEGRATION_URLS = [
combineUrl(PROXY_BASE_URL, "/integration/third-party-services"),
combineUrl(PROXY_BASE_URL, "/integration/portal-integration"),
];
const DATA_MANAGEMENT_URL = combineUrl(
PROXY_BASE_URL,
"/datamanagement/backup"
@ -184,7 +188,7 @@ const Settings = (props) => {
component={SessionLifetimePage}
/>
<Route exact path={THIRD_PARTY_URL} component={ThirdPartyServices} />
<Route exact path={INTEGRATION_URLS} component={Integration} />
<Route
exact
path={DATA_MANAGEMENT_URL}

View File

@ -128,6 +128,13 @@ export const settingsTree = [
tKey: "ThirdPartyAuthorization",
isCategory: true,
},
{
key: "3-1",
icon: "",
link: "portal-integration",
tKey: "PortalIntegration",
isCategory: true,
},
],
},
{

View File

@ -168,7 +168,7 @@ class ConnectClouds extends React.Component {
"data-provider-id": item.provider_id,
"data-provider-key": item.provider_key,
icon: "images/folder.react.svg",
label: t("Home:Open"),
label: t("Files:Open"),
onClick: this.openLocation,
disabled: !isMobile,
},

View File

@ -1,16 +1,22 @@
import { makeAutoObservable } from "mobx";
import api from "../api";
import { setWithCredentialsStatus } from "../api/client";
import history from "../history";
import api from "@docspace/common/api";
import { setWithCredentialsStatus } from "@docspace/common/api/client";
//import history from "../history";
import SettingsStore from "./SettingsStore";
import SettingsStore from "./PortalSettingsStore";
import UserStore from "./UserStore";
import TfaStore from "./TfaStore";
import InfoPanelStore from "./InfoPanelStore";
import { logout as logoutDesktop, desktopConstants } from "../desktop";
import { combineUrl, isAdmin } from "../utils";
import { AppServerConfig, LANGUAGE, TenantStatus } from "../constants";
const { proxyURL } = AppServerConfig;
import {
logout as logoutDesktop,
desktopConstants,
} from "@docspace/common/desktop";
import { /*combineUrl,*/ isAdmin } from "@docspace/common/utils";
import {
/*AppServerConfig,*/ LANGUAGE,
TenantStatus,
} from "@docspace/common/constants";
//const { proxyURL } = AppServerConfig;
class AuthStore {
userStore = null;
@ -104,7 +110,7 @@ class AuthStore {
if (response.tfa && response.confirmUrl) {
const url = response.confirmUrl.replace(window.location.origin, "");
return Promise.resolve({ url, user, hash });
return url;
}
setWithCredentialsStatus(true);
@ -113,7 +119,7 @@ class AuthStore {
this.init();
return Promise.resolve({ url: this.settingsStore.defaultPage });
return this.settingsStore.defaultPage;
} catch (e) {
return Promise.reject(e);
}
@ -158,33 +164,16 @@ class AuthStore {
this.settingsStore = new SettingsStore();
};
logout = async (redirectToLogin = true, redirectPath = null) => {
logout = async () => {
await api.user.logout();
//console.log("Logout response ", response);
setWithCredentialsStatus(false);
const { isDesktopClient: isDesktop, personal } = this.settingsStore;
const { isDesktopClient: isDesktop } = this.settingsStore;
isDesktop && logoutDesktop();
if (redirectToLogin) {
if (redirectPath) {
return window.location.replace(redirectPath);
}
if (personal) {
return window.location.replace("/");
} else {
this.reset(true);
this.userStore.setUser(null);
this.init();
return history.push(combineUrl(proxyURL, "/login"));
}
} else {
this.reset();
this.init();
}
};
get isAuthenticated() {

View File

@ -1,5 +1,5 @@
import { makeAutoObservable, runInAction } from "mobx";
import authStore from "@docspace/common/store/AuthStore";
import authStore from "SRC_DIR/store/AuthStore";
import api from "@docspace/common/api";
class CommonStore {

View File

@ -931,8 +931,8 @@ class ContextOptionsStore {
deleteOperation: t("Translations:DeleteOperation"),
deleteFromTrash: t("Translations:DeleteFromTrash"),
deleteSelectedElem: t("Translations:DeleteSelectedElem"),
FileRemoved: t("Home:FileRemoved"),
FolderRemoved: t("Home:FolderRemoved"),
FileRemoved: t("Files:FileRemoved"),
FolderRemoved: t("Files:FolderRemoved"),
};
this.filesActionsStore

View File

@ -1344,8 +1344,8 @@ class FilesActionStore {
deleteOperation: t("Translations:DeleteOperation"),
deleteFromTrash: t("Translations:DeleteFromTrash"),
deleteSelectedElem: t("Translations:DeleteSelectedElem"),
FileRemoved: t("Home:FileRemoved"),
FolderRemoved: t("Home:FolderRemoved"),
FileRemoved: t("Files:FileRemoved"),
FolderRemoved: t("Files:FolderRemoved"),
};
this.deleteAction(translations).catch((err) =>

View File

@ -344,6 +344,13 @@ class FilesStore {
};
}
reset = () => {
this.isLoaded = false;
this.isLoading = false;
this.firstLoad = false;
this.isInit = false;
};
initFiles = () => {
if (this.isInit) return;

View File

@ -3,14 +3,14 @@ import {
getInvitationLinks,
getShortenedLink,
} from "@docspace/common/api/portal";
import store from "client/store";
const { auth: authStore } = store;
class InviteLinksStore {
userLink = null;
guestLink = null;
authStore = null;
constructor() {
constructor(authStore) {
this.authStore = authStore;
makeAutoObservable(this);
}
@ -22,7 +22,7 @@ class InviteLinksStore {
};
getPortalInviteLinks = async () => {
const isViewerAdmin = authStore.isAdmin;
const isViewerAdmin = this.authStore.isAdmin;
if (!isViewerAdmin) return Promise.resolve();

View File

@ -30,6 +30,14 @@ class LoadingStore {
setLoadedProfile = (profileLoaded) => {
this.profileLoaded = profileLoaded;
};
reset = () => {
this.isLoading = false;
this.isLoaded = false;
this.isRefresh = false;
this.firstLoad = true;
this.profileLoaded = true;
};
}
export default LoadingStore;

View File

@ -9,13 +9,12 @@ import SelectionStore from "./SelectionPeopleStore";
import HeaderMenuStore from "./HeaderMenuStore";
import AvatarEditorStore from "./AvatarEditorStore";
import InviteLinksStore from "./InviteLinksStore";
import store from "client/store";
import DialogStore from "./DialogStore";
import LoadingStore from "./LoadingStore";
import { isMobile } from "react-device-detect";
const { auth: authStore } = store;
class PeopleStore {
authStore = null;
groupsStore = null;
usersStore = null;
targetUserStore = null;
@ -31,7 +30,8 @@ class PeopleStore {
isInit = false;
viewAs = isMobile ? "row" : "table";
constructor() {
constructor(authStore) {
this.authStore = authStore;
this.groupsStore = new GroupsStore(this);
this.usersStore = new UsersStore(this);
this.targetUserStore = new TargetUserStore(this);
@ -41,7 +41,7 @@ class PeopleStore {
this.selectionStore = new SelectionStore(this);
this.headerMenuStore = new HeaderMenuStore(this);
this.avatarEditorStore = new AvatarEditorStore(this);
this.inviteLinksStore = new InviteLinksStore(this);
this.inviteLinksStore = new InviteLinksStore(authStore);
this.dialogStore = new DialogStore();
this.loadingStore = new LoadingStore();
@ -49,16 +49,21 @@ class PeopleStore {
}
get isPeoplesAdmin() {
return authStore.isAdmin;
return this.authStore.isAdmin;
}
reset = () => {
this.loadingStore.reset();
this.isInit = false;
};
init = async () => {
if (this.isInit) return;
this.isInit = true;
//authStore.settingsStore.setModuleInfo(config.homepage, config.id);
//this.authStore.settingsStore.setModuleInfo(config.homepage, config.id);
await authStore.settingsStore.getPortalPasswordSettings();
await this.authStore.settingsStore.getPortalPasswordSettings();
this.loadingStore.setIsLoaded(true);
};
@ -79,7 +84,10 @@ class PeopleStore {
};
getHeaderMenu = (t) => {
const { userCaption, guestCaption } = authStore.settingsStore.customNames;
const {
userCaption,
guestCaption,
} = this.authStore.settingsStore.customNames;
const {
hasUsersToMakeEmployees,
hasUsersToMakeGuests,

View File

@ -1,11 +1,11 @@
import { makeAutoObservable } from "mobx";
import api from "../api";
import { LANGUAGE, TenantStatus } from "../constants";
import { combineUrl } from "../utils";
import FirebaseHelper from "../utils/firebase";
import { AppServerConfig, ThemeKeys } from "../constants";
import { version } from "../package.json";
import SocketIOHelper from "../utils/socket";
import api from "@docspace/common/api";
import { LANGUAGE, TenantStatus } from "@docspace/common/constants";
import { combineUrl } from "@docspace/common/utils";
import FirebaseHelper from "@docspace/common/utils/firebase";
import { AppServerConfig, ThemeKeys } from "@docspace/common/constants";
import { version } from "PACKAGE_FILE";
import SocketIOHelper from "@docspace/common/utils/socket";
import { Dark, Base } from "@docspace/components/themes";
@ -127,6 +127,7 @@ class SettingsStore {
tenantStatus = null;
helpLink = null;
hotkeyPanelVisible = false;
frameConfig = null;
constructor() {
makeAutoObservable(this);
@ -538,6 +539,15 @@ class SettingsStore {
setHotkeyPanelVisible = (hotkeyPanelVisible) => {
this.hotkeyPanelVisible = hotkeyPanelVisible;
};
setFrameConfig = (frameConfig) => {
this.frameConfig = frameConfig;
return frameConfig;
};
get isFrame() {
return this.frameConfig?.name === window.name;
}
}
export default SettingsStore;

View File

@ -2,14 +2,13 @@ import { makeAutoObservable } from "mobx";
import { combineUrl } from "@docspace/common/utils";
import { AppServerConfig } from "@docspace/common/constants";
import history from "@docspace/common/history";
import authStore from "@docspace/common/store/AuthStore";
import { isDesktop, isTablet, isMobile } from "react-device-detect";
const { proxyURL } = AppServerConfig;
const PROXY_HOMEPAGE_URL = combineUrl(proxyURL, "/");
const PROFILE_SELF_URL = combineUrl(PROXY_HOMEPAGE_URL, "/accounts/view/@self");
const PROFILE_MY_URL = combineUrl(PROXY_HOMEPAGE_URL, "/my");
//const PROFILE_MY_URL = combineUrl(PROXY_HOMEPAGE_URL, "/my");
const ABOUT_URL = combineUrl(PROXY_HOMEPAGE_URL, "/about");
const PAYMENTS_URL = combineUrl(PROXY_HOMEPAGE_URL, "/payments");
const HELP_URL = "https://onlyoffice.com/";
@ -18,11 +17,16 @@ const VIDEO_GUIDES_URL = "https://onlyoffice.com/";
class ProfileActionsStore {
authStore = null;
filesStore = null;
peopleStore = null;
isAboutDialogVisible = false;
isDebugDialogVisible = false;
constructor() {
constructor(authStore, filesStore, peopleStore) {
this.authStore = authStore;
this.filesStore = filesStore;
this.peopleStore = peopleStore;
makeAutoObservable(this);
}
@ -80,8 +84,18 @@ class ProfileActionsStore {
}
};
onLogoutClick = () => {
this.authStore.logout && this.authStore.logout();
onLogoutClick = async () => {
await this.authStore.logout();
this.authStore.reset();
this.filesStore.reset();
this.peopleStore.reset();
this.authStore.init();
history.push("/login");
};
onDebugClick = () => {

View File

@ -4,8 +4,6 @@ import {
EmployeeActivationStatus,
} from "@docspace/common/constants";
import { getUserStatus } from "../helpers/people-helpers";
import store from "client/store";
const { auth: authStore } = store;
class SelectionStore {
selection = [];
@ -115,7 +113,7 @@ class SelectionStore {
!x.isOwner &&
x.isVisitor &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
});
return !!users.length;
@ -128,7 +126,7 @@ class SelectionStore {
!x.isOwner &&
x.isVisitor &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
});
return users.map((u) => u.id);
@ -141,7 +139,7 @@ class SelectionStore {
!x.isOwner &&
!x.isVisitor &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
});
return !!users.length;
@ -154,7 +152,7 @@ class SelectionStore {
!x.isOwner &&
!x.isVisitor &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
});
return users.map((u) => u.id);
@ -165,7 +163,7 @@ class SelectionStore {
(x) =>
!x.isOwner &&
x.status !== EmployeeStatus.Active &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
return !!users.length;
}
@ -175,7 +173,7 @@ class SelectionStore {
(x) =>
!x.isOwner &&
x.status !== EmployeeStatus.Active &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
return users.map((u) => u.id);
}
@ -185,7 +183,7 @@ class SelectionStore {
(x) =>
!x.isOwner &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
return !!users.length;
}
@ -195,7 +193,7 @@ class SelectionStore {
(x) =>
!x.isOwner &&
x.status !== EmployeeStatus.Disabled &&
x.id !== authStore.userStore.user.id
x.id !== this.peopleStore.authStore.userStore.user.id
);
return users.map((u) => u.id);
}

View File

@ -2,8 +2,6 @@ import api from "@docspace/common/api";
import { makeAutoObservable } from "mobx";
const { Filter } = api;
import SelectionStore from "./SelectionStore";
//import CommonStore from "./CommonStore";
import authStore from "@docspace/common/store/AuthStore";
import { combineUrl } from "@docspace/common/utils";
import { AppServerConfig } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
@ -40,7 +38,7 @@ class SettingsSetupStore {
commonThirdPartyList: [],
};
constructor() {
constructor(authStore) {
this.selectionStore = new SelectionStore(this);
this.authStore = authStore;
makeAutoObservable(this);
@ -50,12 +48,12 @@ class SettingsSetupStore {
if (this.isInit) return;
this.isInit = true;
if (authStore.isAuthenticated) {
await authStore.settingsStore.getPortalPasswordSettings();
await authStore.tfaStore.getTfaType();
await authStore.settingsStore.getIpRestrictionsEnable();
await authStore.settingsStore.getIpRestrictions();
await authStore.settingsStore.getSessionLifetime();
if (this.authStore.isAuthenticated) {
await this.authStore.settingsStore.getPortalPasswordSettings();
await this.authStore.tfaStore.getTfaType();
await this.authStore.settingsStore.getIpRestrictionsEnable();
await this.authStore.settingsStore.getIpRestrictions();
await this.authStore.settingsStore.getSessionLifetime();
}
};

View File

@ -1,9 +1,6 @@
import api from "@docspace/common/api";
import { LANGUAGE } from "@docspace/common/constants";
import { makeAutoObservable } from "mobx";
import store from "client/store";
const { auth: authStore } = store;
class TargetUserStore {
targetUser = null;
@ -17,8 +14,8 @@ class TargetUserStore {
get getDisableProfileType() {
const res =
authStore.userStore.user.id === this.targetUser.id ||
!authStore.isAdmin ||
this.peopleStore.authStore.userStore.user.id === this.targetUser.id ||
!this.peopleStore.authStore.isAdmin ||
this.peopleStore.isPeoplesAdmin
? false
: true;
@ -29,22 +26,19 @@ class TargetUserStore {
get isMe() {
return (
this.targetUser &&
this.targetUser.userName === authStore.userStore.user.userName
this.targetUser.userName ===
this.peopleStore.authStore.userStore.user.userName
);
}
getTargetUser = async (userName) => {
/*if (authStore.userStore.user.userName === userName) {
return this.setTargetUser(authStore.userStore.user);
} else {*/
const user = await api.people.getUser(userName);
if (user?.userName === authStore.userStore.user.userName) {
if (user?.userName === this.peopleStore.authStore.userStore.user.userName) {
const tipsSubscription = await api.settings.getTipsSubscription();
this.tipsSubscription = tipsSubscription;
}
this.setTargetUser(user);
return user;
//}
};
setTargetUser = (user) => {
@ -63,7 +57,7 @@ class TargetUserStore {
);
const res = await api.people.updateUser(member);
if (!res.theme) res.theme = authStore.userStore.user.theme;
if (!res.theme) res.theme = this.peopleStore.authStore.userStore.user.theme;
this.setTargetUser(res);
return Promise.resolve(res);
@ -80,11 +74,10 @@ class TargetUserStore {
updateProfileCulture = async (id, culture) => {
const res = await api.people.updateUserCulture(id, culture);
authStore.userStore.setUser(res);
this.peopleStore.authStore.userStore.setUser(res);
this.setTargetUser(res);
//caches.delete("api-cache");
//await authStore.settingsStore.init();
localStorage.setItem(LANGUAGE, culture);
};

View File

@ -1,6 +1,6 @@
import { makeAutoObservable } from "mobx";
import api from "../api";
import history from "../history";
import api from "@docspace/common/api";
//import history from "../history";
class TfaStore {
tfaSettings = null;

View File

@ -1,5 +1,5 @@
import { makeAutoObservable } from "mobx";
import api from "../api";
import api from "@docspace/common/api";
class UserStore {
user = null;

View File

@ -6,8 +6,7 @@ import {
} from "@docspace/common/constants";
import { isMobileOnly } from "react-device-detect";
const { Filter } = api;
import store from "client/store";
const { auth: authStore } = store;
class UsersStore {
users = [];
providers = [];
@ -237,9 +236,9 @@ class UsersStore {
const statusType = this.getStatusType(user);
const role = this.getUserRole(user);
const isMySelf =
authStore.userStore.user &&
user.userName === authStore.userStore.user.userName;
const isViewerAdmin = authStore.isAdmin;
this.peopleStore.authStore.userStore.user &&
user.userName === this.peopleStore.authStore.userStore.user.userName;
const isViewerAdmin = this.peopleStore.authStore.isAdmin;
const options = this.getUserContextOptions(
isMySelf,

View File

@ -1,113 +0,0 @@
import FilesStore from "./FilesStore";
import SelectedFolderStore from "./SelectedFolderStore";
import TreeFoldersStore from "./TreeFoldersStore";
import thirdPartyStore from "./ThirdPartyStore";
import SettingsStore from "./SettingsStore";
import FilesActionsStore from "./FilesActionsStore";
import MediaViewerDataStore from "./MediaViewerDataStore";
import UploadDataStore from "./UploadDataStore";
import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
import VersionHistoryStore from "./VersionHistoryStore";
import DialogsStore from "./DialogsStore";
import selectFolderDialogStore from "./SelectFolderDialogStore";
import ContextOptionsStore from "./ContextOptionsStore";
import HotkeyStore from "./HotkeyStore";
import store from "client/store";
import selectFileDialogStore from "./SelectFileDialogStore";
import TagsStore from "./TagsStore";
const tagsStore = new TagsStore();
const selectedFolderStore = new SelectedFolderStore(store.auth.settingsStore);
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore);
const settingsStore = new SettingsStore(thirdPartyStore, treeFoldersStore);
const filesStore = new FilesStore(
store.auth,
store.auth.settingsStore,
store.auth.userStore,
selectedFolderStore,
treeFoldersStore,
settingsStore,
selectFolderDialogStore,
selectFileDialogStore
);
const mediaViewerDataStore = new MediaViewerDataStore(
filesStore,
settingsStore
);
const secondaryProgressDataStore = new SecondaryProgressDataStore();
const primaryProgressDataStore = new PrimaryProgressDataStore();
const versionHistoryStore = new VersionHistoryStore(filesStore);
const dialogsStore = new DialogsStore(
store.auth,
treeFoldersStore,
filesStore,
selectedFolderStore,
versionHistoryStore
);
const uploadDataStore = new UploadDataStore(
treeFoldersStore,
selectedFolderStore,
filesStore,
secondaryProgressDataStore,
primaryProgressDataStore,
dialogsStore,
settingsStore
);
const filesActionsStore = new FilesActionsStore(
store.auth,
uploadDataStore,
treeFoldersStore,
filesStore,
selectedFolderStore,
settingsStore,
dialogsStore,
mediaViewerDataStore
);
const contextOptionsStore = new ContextOptionsStore(
store.auth,
dialogsStore,
filesActionsStore,
filesStore,
mediaViewerDataStore,
treeFoldersStore,
uploadDataStore,
versionHistoryStore,
settingsStore
);
const hotkeyStore = new HotkeyStore(
filesStore,
dialogsStore,
settingsStore,
filesActionsStore,
treeFoldersStore,
uploadDataStore
);
const stores = {
filesStore,
settingsStore,
mediaViewerDataStore,
versionHistoryStore,
uploadDataStore,
dialogsStore,
treeFoldersStore,
selectedFolderStore,
filesActionsStore,
selectFolderDialogStore,
contextOptionsStore,
hotkeyStore,
selectFileDialogStore,
tagsStore,
};
export default stores;

View File

@ -1,118 +0,0 @@
import FilesStore from "./FilesStore";
import SelectedFolderStore from "./SelectedFolderStore";
import TreeFoldersStore from "./TreeFoldersStore";
import thirdPartyStore from "./ThirdPartyStore";
import SettingsStore from "./SettingsStore";
import FilesActionsStore from "./FilesActionsStore";
import MediaViewerDataStore from "./MediaViewerDataStore";
import UploadDataStore from "./UploadDataStore";
import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
import VersionHistoryStore from "./VersionHistoryStore";
import DialogsStore from "./DialogsStore";
import selectFolderDialogStore from "./SelectFolderDialogStore";
import ContextOptionsStore from "./ContextOptionsStore";
import HotkeyStore from "./HotkeyStore";
import store from "client/store";
import selectFileDialogStore from "./SelectFileDialogStore";
import TagsStore from "./TagsStore";
import PeopleStore from "./PeopleStore";
const peopleStore = new PeopleStore();
const tagsStore = new TagsStore();
const selectedFolderStore = new SelectedFolderStore(store.auth.settingsStore);
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore);
const settingsStore = new SettingsStore(thirdPartyStore, treeFoldersStore);
const filesStore = new FilesStore(
store.auth,
store.auth.settingsStore,
store.auth.userStore,
selectedFolderStore,
treeFoldersStore,
settingsStore,
selectFolderDialogStore,
selectFileDialogStore
);
const mediaViewerDataStore = new MediaViewerDataStore(
filesStore,
settingsStore
);
const secondaryProgressDataStore = new SecondaryProgressDataStore();
const primaryProgressDataStore = new PrimaryProgressDataStore();
const versionHistoryStore = new VersionHistoryStore(filesStore);
const dialogsStore = new DialogsStore(
store.auth,
treeFoldersStore,
filesStore,
selectedFolderStore,
versionHistoryStore
);
const uploadDataStore = new UploadDataStore(
treeFoldersStore,
selectedFolderStore,
filesStore,
secondaryProgressDataStore,
primaryProgressDataStore,
dialogsStore,
settingsStore
);
const filesActionsStore = new FilesActionsStore(
store.auth,
uploadDataStore,
treeFoldersStore,
filesStore,
selectedFolderStore,
settingsStore,
dialogsStore,
mediaViewerDataStore
);
const contextOptionsStore = new ContextOptionsStore(
store.auth,
dialogsStore,
filesActionsStore,
filesStore,
mediaViewerDataStore,
treeFoldersStore,
uploadDataStore,
versionHistoryStore,
settingsStore
);
const hotkeyStore = new HotkeyStore(
filesStore,
dialogsStore,
settingsStore,
filesActionsStore,
treeFoldersStore,
uploadDataStore
);
const stores = {
filesStore,
settingsStore,
mediaViewerDataStore,
versionHistoryStore,
uploadDataStore,
dialogsStore,
treeFoldersStore,
selectedFolderStore,
filesActionsStore,
selectFolderDialogStore,
contextOptionsStore,
hotkeyStore,
selectFileDialogStore,
tagsStore,
peopleStore,
};
export default stores;

View File

@ -1,4 +1,4 @@
import authStore from "@docspace/common/store/AuthStore";
import authStore from "./AuthStore";
import PaymentStore from "./PaymentStore";
import WizardStore from "./WizardStore";
import SettingsSetupStore from "./SettingsSetupStore";
@ -7,15 +7,114 @@ import BackupStore from "./BackupStore";
import CommonStore from "./CommonStore";
import BannerStore from "./BannerStore";
import ProfileActionsStore from "./ProfileActionsStore";
import FilesStore from "./FilesStore";
import SelectedFolderStore from "./SelectedFolderStore";
import TreeFoldersStore from "./TreeFoldersStore";
import thirdPartyStore from "./ThirdPartyStore";
import SettingsStore from "./SettingsStore";
import FilesActionsStore from "./FilesActionsStore";
import MediaViewerDataStore from "./MediaViewerDataStore";
import UploadDataStore from "./UploadDataStore";
import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
import VersionHistoryStore from "./VersionHistoryStore";
import DialogsStore from "./DialogsStore";
import selectFolderDialogStore from "./SelectFolderDialogStore";
import ContextOptionsStore from "./ContextOptionsStore";
import HotkeyStore from "./HotkeyStore";
import selectFileDialogStore from "./SelectFileDialogStore";
import TagsStore from "./TagsStore";
import PeopleStore from "./PeopleStore";
const paymentStore = new PaymentStore();
const wizardStore = new WizardStore();
const setupStore = new SettingsSetupStore();
const setupStore = new SettingsSetupStore(authStore);
const confirmStore = new ConfirmStore();
const backupStore = new BackupStore();
const commonStore = new CommonStore();
const bannerStore = new BannerStore();
const profileActionsStore = new ProfileActionsStore();
const peopleStore = new PeopleStore(authStore);
const tagsStore = new TagsStore();
const selectedFolderStore = new SelectedFolderStore(authStore.settingsStore);
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore);
const settingsStore = new SettingsStore(thirdPartyStore, treeFoldersStore);
const filesStore = new FilesStore(
authStore,
authStore.settingsStore,
authStore.userStore,
selectedFolderStore,
treeFoldersStore,
settingsStore,
selectFolderDialogStore,
selectFileDialogStore
);
const mediaViewerDataStore = new MediaViewerDataStore(
filesStore,
settingsStore
);
const secondaryProgressDataStore = new SecondaryProgressDataStore();
const primaryProgressDataStore = new PrimaryProgressDataStore();
const versionHistoryStore = new VersionHistoryStore(filesStore);
const dialogsStore = new DialogsStore(
authStore,
treeFoldersStore,
filesStore,
selectedFolderStore,
versionHistoryStore
);
const uploadDataStore = new UploadDataStore(
treeFoldersStore,
selectedFolderStore,
filesStore,
secondaryProgressDataStore,
primaryProgressDataStore,
dialogsStore,
settingsStore
);
const filesActionsStore = new FilesActionsStore(
authStore,
uploadDataStore,
treeFoldersStore,
filesStore,
selectedFolderStore,
settingsStore,
dialogsStore,
mediaViewerDataStore
);
const contextOptionsStore = new ContextOptionsStore(
authStore,
dialogsStore,
filesActionsStore,
filesStore,
mediaViewerDataStore,
treeFoldersStore,
uploadDataStore,
versionHistoryStore,
settingsStore
);
const hotkeyStore = new HotkeyStore(
filesStore,
dialogsStore,
settingsStore,
filesActionsStore,
treeFoldersStore,
uploadDataStore
);
const profileActionsStore = new ProfileActionsStore(
authStore,
filesStore,
peopleStore
);
const store = {
auth: authStore,
@ -27,6 +126,25 @@ const store = {
common: commonStore,
bannerStore: bannerStore,
profileActionsStore: profileActionsStore,
filesStore,
settingsStore,
mediaViewerDataStore,
versionHistoryStore,
uploadDataStore,
dialogsStore,
treeFoldersStore,
selectedFolderStore,
filesActionsStore,
selectFolderDialogStore,
contextOptionsStore,
hotkeyStore,
selectFileDialogStore,
tagsStore,
peopleStore,
};
export default store;

View File

@ -1,2 +0,0 @@
import authStore from "./AuthStore";
export default { authStore };

View File

@ -151,7 +151,6 @@ export function isMe(user, userName) {
}
export function isAdmin(currentUser, currentProductId) {
return (
currentUser.isAdmin ||
currentUser.isOwner ||
@ -378,3 +377,23 @@ export function assign(obj, keyPath, value) {
}
obj[keyPath[lastKeyIndex]] = value;
}
export const frameCallbackData = (data) => {
window.parent.postMessage(
JSON.stringify({
type: "onMethodReturn",
methodReturnData: data,
}),
"*"
);
};
export const frameCallCommand = (command) => {
window.parent.postMessage(
JSON.stringify({
type: "onCallCommand",
commandName: command,
}),
"*"
);
};

View File

@ -224,6 +224,7 @@ class TableHeader extends React.Component {
resetColumnsSize,
sectionWidth,
infoPanelVisible,
columns,
} = this.props;
if (!infoPanelVisible && this.state.hideColumns) {
@ -273,6 +274,11 @@ class TableHeader extends React.Component {
? storageSize.split(" ")
: container.style.gridTemplateColumns.split(" ");
// columns.length + 1 - its settings column
if (tableContainer.length !== columns.length + 1) {
return this.resetColumns(true);
}
const containerWidth = +container.clientWidth;
const oldWidth =

View File

@ -2,6 +2,7 @@ import styled, { css } from "styled-components";
import { ReactSVG } from "react-svg";
import Text from "../text";
import Base from "../themes/base";
const StyledTag = styled.div`
width: fit-content;
@ -17,7 +18,11 @@ const StyledTag = styled.div`
margin-right: 4px;
background: ${(props) =>
props.isDisabled ? "#F8F9F9" : props.isNewTag ? "#ECEEF1" : "#F3F4F4"};
props.isDisabled
? props.theme.tag.disabledBackground
: props.isNewTag
? props.theme.tag.newTagBackground
: props.theme.tag.background};
border-radius: 6px;
@ -38,11 +43,13 @@ const StyledTag = styled.div`
cursor: pointer;
&:hover {
background: #eceef1;
background: ${(props) => props.theme.tag.hoverBackground};
}
`}
`;
StyledTag.defaultProps = { theme: Base };
const StyledDropdownIcon = styled(ReactSVG)`
display: flex;
align-items: center;

View File

@ -2739,6 +2739,13 @@ const Base = {
color: grayMain,
},
},
tag: {
background: "#f3f4f4",
hoverBackground: "#eceef1",
disabledBackground: "#f8f9f9",
newTagBackground: "#eceef1",
},
};
export default Base;

View File

@ -2749,6 +2749,13 @@ const Dark = {
color: "#C4C4C4",
},
},
tag: {
background: "#3D3D3D",
hoverBackground: "#333333",
disabledBackground: "#858585",
newTagBackground: "#333333",
},
};
export default Dark;

View File

@ -41,7 +41,7 @@ export const getFavicon = (documentType) => {
export const initDocEditor = async (req) => {
if (!req) return false;
let personal = IS_PERSONAL || null;
const { headers, url, query } = req;
const { headers, url, query, type } = req;
const { version, desktop: isDesktop } = query;
let error = null;
initSSR(headers);
@ -101,6 +101,10 @@ export const initDocEditor = async (req) => {
config.editorConfig.mode = "view";
}
if (type) {
config.type = type;
}
const actionLink = config?.editorConfig?.actionLink || null;
return {

View File

@ -219,9 +219,9 @@ const Form = (props) => {
//errorText && setErrorText("");
let hasError = false;
const userName = identifier.trim();
const user = identifier.trim();
if (!userName) {
if (!user) {
hasError = true;
setIdentifierValid(false);
setIsEmailErrorShow(true);
@ -243,15 +243,18 @@ const Form = (props) => {
isDesktop && checkPwd();
const session = !isChecked;
login(userName, hash, session)
.then((res) => {
const { url, user, hash } = res;
login(user, hash, session)
.then((url) => {
const redirectPath = localStorage.getItem("redirectPath");
if (redirectPath) {
localStorage.removeItem("redirectPath");
window.location.href = redirectPath;
} else history.push(url, { user, hash });
return;
}
window.location.replace(url); //TODO: save { user, hash } for tfa
//history.push(url, { user, hash });
})
.catch((error) => {
setIsEmailErrorShow(true);

View File

@ -639,7 +639,10 @@ public class SharePointProviderInfo : IProviderInfo
public void Dispose()
{
_clientContext.Dispose();
if (_clientContext != null)
{
_clientContext.Dispose();
}
}
private void SetFolderType(Folder<string> folder, bool isRoot)

View File

@ -63,4 +63,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
app.Run();
await app.RunWithTasksAsync();

View File

@ -115,7 +115,7 @@ var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService
eventBus.Subscribe<ThumbnailRequestedIntegrationEvent, ThumbnailRequestedIntegrationEventHandler>();
app.Run();
await app.RunWithTasksAsync();
public partial class Program
{

View File

@ -54,4 +54,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
await app.RunAsync();
await app.RunWithTasksAsync();

317
public/scripts/api.js Normal file
View File

@ -0,0 +1,317 @@
(function () {
const defaultConfig = {
src: `${window.location.protocol}//${window.location.hostname}:8092`,
rootPath: "/rooms/personal/",
width: "100%",
height: "100%",
name: "frameDocSpace",
type: "desktop", // TODO: ["desktop", "mobile"]
frameId: "ds-frame",
mode: "manager", //TODO: ["manager", "editor", "viewer", "file selector", "folder selector", "user picker"]
fileId: null,
editorType: "embedded", //TODO: ["desktop", "embedded"]
showHeader: false,
showArticle: false,
showTitle: true,
showFilter: false,
destroyText: "Frame container",
viewAs: "row", //TODO: ["row", "table", "tile"]
filter: {
folder: "@my",
count: 25,
page: 0,
sortorder: "descending", //TODO: ["descending", "ascending"]
sortby: "DateAndTime", //TODO: ["DateAndTime", "AZ", "Type", "Size", "DateAndTimeCreation", "Author"]
search: "",
filterType: null,
authorType: null,
withSubfolders: true,
},
keysForReload: [
"src",
"rootPath",
"width",
"height",
"name",
"frameId",
"fileId",
"type",
"editorType",
],
};
const getConfigFromParams = () => {
const src = document.currentScript.src;
if (!src || !src.length) return null;
const searchUrl = src.split("?")[1];
let object = {};
if (searchUrl && searchUrl.length) {
object = JSON.parse(
`{"${searchUrl.replace(/&/g, '","').replace(/=/g, '":"')}"}`,
(k, v) => (v === "true" ? true : v === "false" ? false : v)
);
object.filter = defaultConfig.filter;
for (prop in object) {
if (prop in defaultConfig.filter) {
object.filter[prop] = object[prop];
delete object[prop];
}
}
}
return { ...defaultConfig, ...object };
};
class DocSpace {
#iframe;
#isConnected = false;
#callbacks = [];
#tasks = [];
constructor(config) {
this.config = config;
}
#oneOfExistInObject = (array, object) => {
return Object.keys(object).some((k) => array.includes(k));
};
#createIframe = (config) => {
const iframe = document.createElement("iframe");
let path = "";
switch (config.mode) {
case "manager": {
if (config.filter) {
const filterString = new URLSearchParams(config.filter).toString();
path = `${config.rootPath}filter?${filterString}`;
}
break;
}
case "editor": {
path = `/doceditor/?fileId=${config.fileId}&type=${config.editorType}`;
break;
}
case "viewer": {
path = `/doceditor/?fileId=${config.fileId}&type=${config.editorType}&action=view`;
break;
}
default:
path = config.rootPath;
}
iframe.src = config.src + path;
iframe.width = config.width;
iframe.height = config.height;
iframe.name = config.name;
iframe.id = config.frameId;
iframe.align = "top";
iframe.frameBorder = 0;
iframe.allowFullscreen = true;
iframe.setAttribute("allowfullscreen", "");
iframe.setAttribute("onmousewheel", "");
iframe.setAttribute("allow", "autoplay");
if (config.type == "mobile") {
iframe.style.position = "fixed";
iframe.style.overflow = "hidden";
document.body.style.overscrollBehaviorY = "contain";
}
return iframe;
};
#sendMessage = (message) => {
let mes = {
frameId: this.config.frameId,
type: "",
data: message,
};
if (this.#iframe)
this.#iframe.contentWindow.postMessage(
JSON.stringify(mes),
this.config.src
);
};
#onMessage = (e) => {
if (typeof e.data == "string") {
let frameData = {};
try {
frameData = JSON.parse(e.data);
} catch (err) {
frameData = {};
}
switch (frameData.type) {
case "onMethodReturn": {
if (this.#callbacks.length > 0) {
const callback = this.#callbacks.shift();
callback && callback(frameData.methodReturnData);
}
if (this.#tasks.length > 0) {
this.#sendMessage(this.#tasks.shift());
}
break;
}
case "onCallCommand": {
this[frameData.commandName].call(this);
break;
}
default:
break;
}
}
};
#executeMethod = (methodName, params, callback) => {
if (!this.#isConnected) {
console.log("Message bus is not connected with frame");
return;
}
this.#callbacks.push(callback);
const message = {
type: "method",
methodName,
data: params,
};
if (this.#callbacks.length !== 1) {
this.#tasks.push(message);
return;
}
this.#sendMessage(message);
};
initFrame(frameConfig) {
this.config = { ...this.config, ...frameConfig };
const target = document.getElementById(this.config.frameId);
if (target) {
this.#iframe = this.#createIframe(this.config);
target.parentNode &&
target.parentNode.replaceChild(this.#iframe, target);
window.addEventListener("message", this.#onMessage, false);
this.#isConnected = true;
}
}
destroyFrame() {
const target = document.createElement("div");
target.setAttribute("id", this.config.frameId);
target.innerHTML = this.config.destroyText;
if (this.#iframe) {
window.removeEventListener("message", this.#onMessage, false);
this.#isConnected = false;
this.#iframe.parentNode &&
this.#iframe.parentNode.replaceChild(target, this.#iframe);
}
}
#getMethodPromise = (methodName, params = null, withReload = false) => {
return new Promise((resolve) => {
if (withReload) {
this.initFrame(this.config);
resolve(this.config);
} else {
this.#executeMethod(methodName, params, (data) => resolve(data));
}
});
};
getFolderInfo() {
return this.#getMethodPromise("getFolderInfo");
}
getSelection() {
return this.#getMethodPromise("getSelection");
}
getFiles() {
return this.#getMethodPromise("getFiles");
}
getFolders() {
return this.#getMethodPromise("getFolders");
}
getList() {
return this.#getMethodPromise("getList");
}
getUserInfo() {
return this.#getMethodPromise("getUserInfo");
}
getConfig() {
return this.config;
}
setConfig(newConfig = {}, reload = false) {
if (this.#oneOfExistInObject(this.config.keysForReload, newConfig))
reload = true;
this.config = { ...this.config, ...newConfig };
return this.#getMethodPromise("setConfig", this.config, reload);
}
openModal(type, options) {
return this.#getMethodPromise("openModal", { type, options });
}
createFile(folderId, title, templateId, formId) {
return this.#getMethodPromise("createFile", {
folderId,
title,
templateId,
formId,
});
}
createFolder(parentFolderId, title) {
return this.#getMethodPromise("createFolder", {
parentFolderId,
title,
});
}
createRoom(title, type) {
return this.#getMethodPromise("createRoom", {
title,
type,
});
}
setListView(type) {
return this.#getMethodPromise("setItemsView", type);
}
}
const config = getConfigFromParams();
window.DocSpace = new DocSpace(config);
window.DocSpace.initFrame();
})();

View File

@ -56,4 +56,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
await app.RunAsync();
await app.RunWithTasksAsync();

View File

@ -25,7 +25,7 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
global using ASC.Web.HealthChecks.UI;
global using ASC.Api.Core.Extensions;
global using Microsoft.AspNetCore.Diagnostics.HealthChecks;
global using Microsoft.Extensions.Diagnostics.HealthChecks;

View File

@ -24,6 +24,7 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
var options = new WebApplicationOptions
{
Args = args,
@ -43,4 +44,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
app.Run();
await app.RunWithTasksAsync();

View File

@ -55,4 +55,4 @@ var app = builder.Build();
startup.Configure(app, app.Environment);
app.Run();
await app.RunWithTasksAsync();