Merge branch 'develop' of github.com:ONLYOFFICE/AppServer into develop

This commit is contained in:
Ilya Oleshko 2021-04-19 18:53:32 +03:00
commit 434ce42f5f
147 changed files with 1496 additions and 1155 deletions

View File

@ -42,12 +42,14 @@ namespace ASC.Api.Core
private static int MaxCount = 1000;
public IHttpContextAccessor HttpContextAccessor { get; set; }
public Tenant tenant;
public Tenant Tenant { get { return tenant ??= TenantManager.GetCurrentTenant(HttpContextAccessor.HttpContext); } }
public Tenant Tenant { get { return tenant ??= TenantManager.GetCurrentTenant(HttpContextAccessor?.HttpContext); } }
public ApiContext(IHttpContextAccessor httpContextAccessor, SecurityContext securityContext, TenantManager tenantManager)
{
if (httpContextAccessor == null || httpContextAccessor.HttpContext == null) return;
SecurityContext = securityContext;
TenantManager = tenantManager;
HttpContextAccessor = httpContextAccessor;
if (httpContextAccessor.HttpContext == null) return;
Count = MaxCount;
var query = HttpContextAccessor.HttpContext.Request.Query;
@ -85,9 +87,6 @@ namespace ASC.Api.Core
{
UpdatedSince = Convert.ToDateTime(updatedSince);
}
SecurityContext = securityContext;
TenantManager = tenantManager;
}
public string[] Fields { get; set; }

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:65458/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.Api.Core": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:65459/"
}
}
}

View File

@ -4,6 +4,8 @@ using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using ASC.Common.Utils;
using Autofac;
using Autofac.Configuration;
@ -82,13 +84,13 @@ namespace ASC.Common.DependencyInjection
if (!Path.IsPathRooted(folder))
{
if (currentDir.EndsWith(Path.Combine(Path.GetFileName(folder), Assembly.GetEntryAssembly().GetName().Name, subfolder)))
if (currentDir.EndsWith(CrossPlatform.PathCombine(Path.GetFileName(folder), Assembly.GetEntryAssembly().GetName().Name, subfolder)))
{
productsDir = Path.GetFullPath(Path.Combine("..", ".."));
productsDir = Path.GetFullPath(CrossPlatform.PathCombine("..", ".."));
}
else
{
productsDir = Path.GetFullPath(Path.Combine(currentDir, folder));
productsDir = Path.GetFullPath(CrossPlatform.PathCombine(currentDir, folder));
}
}
else
@ -129,8 +131,8 @@ namespace ASC.Common.DependencyInjection
string GetFullPath(string n)
{
var productPath = Path.Combine(productsDir, n, subfolder);
return GetPath(Path.Combine(productPath, "bin"), n, SearchOption.AllDirectories) ?? GetPath(productPath, n, SearchOption.TopDirectoryOnly);
var productPath = CrossPlatform.PathCombine(productsDir, n, subfolder);
return GetPath(CrossPlatform.PathCombine(productPath, "bin"), n, SearchOption.AllDirectories) ?? GetPath(productPath, n, SearchOption.TopDirectoryOnly);
}
static string GetPath(string dirPath, string dll, SearchOption searchOption)
@ -155,7 +157,7 @@ namespace ASC.Common.DependencyInjection
public Assembly Resolving(AssemblyLoadContext context, AssemblyName assemblyName)
{
var path = Path.Combine(Path.GetDirectoryName(ResolvePath), $"{assemblyName.Name}.dll");
var path = CrossPlatform.PathCombine(Path.GetDirectoryName(ResolvePath), $"{assemblyName.Name}.dll");
if (!File.Exists(path)) return null;

View File

@ -384,7 +384,7 @@ namespace ASC.Common.Logging
Configuration = configuration;
ConfigurationExtension = configurationExtension;
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(Path.Combine(Configuration["pathToConf"], "nlog.config"));
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(CrossPlatform.PathCombine(Configuration["pathToConf"], "nlog.config"));
LogManager.ThrowConfigExceptions = false;
var settings = ConfigurationExtension.GetSetting<NLogSettings>("log");

View File

@ -29,6 +29,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using ASC.Common.Utils;
using NLog;
using NLog.Common;
using NLog.Targets;
@ -87,7 +89,7 @@ namespace ASC.Common.Logging
return;
if (!Path.IsPathRooted(dirPath))
dirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dirPath);
dirPath = CrossPlatform.PathCombine(AppDomain.CurrentDomain.BaseDirectory, dirPath);
var directory = new DirectoryInfo(dirPath);

View File

@ -0,0 +1,53 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.IO;
using System.Linq;
namespace ASC.Common.Utils
{
public static class CrossPlatform
{
public static string PathCombine(string basePath, params string[] additional)
{
var splits = additional.Select(s => s.Split(pathSplitCharacters)).ToArray();
var totalLength = splits.Sum(arr => arr.Length);
var segments = new string[totalLength + 1];
segments[0] = basePath;
var i = 0;
foreach (var split in splits)
{
foreach (var value in split)
{
i++;
segments[i] = value;
}
}
return Path.Combine(segments);
}
static char[] pathSplitCharacters = new char[] { '/', '\\' };
}
}

View File

@ -54,7 +54,8 @@ namespace ASC.Security.Cryptography
private readonly ILog log;
private static readonly DateTime _from = new DateTime(2010, 01, 01, 0, 0, 0, DateTimeKind.Utc);
internal readonly TimeSpan ValidInterval;
internal readonly TimeSpan ValidEmailKeyInterval;
internal readonly TimeSpan ValidAuthKeyInterval;
private MachinePseudoKeys MachinePseudoKeys { get; }
private TenantManager TenantManager { get; }
@ -67,8 +68,13 @@ namespace ASC.Security.Cryptography
{
validInterval = TimeSpan.FromDays(7);
}
if (!TimeSpan.TryParse(configuration["auth:validinterval"], out var authValidInterval))
{
validInterval = TimeSpan.FromDays(7);
}
ValidInterval = validInterval;
ValidEmailKeyInterval = validInterval;
ValidAuthKeyInterval = authValidInterval;
log = options.CurrentValue;
}
@ -232,26 +238,31 @@ namespace ASC.Security.Cryptography
switch (type)
{
case ConfirmType.EmpInvite:
checkKeyResult = Provider.ValidateEmailKey(email + type + (int)emplType, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey(email + type + (int)emplType, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.LinkInvite:
checkKeyResult = Provider.ValidateEmailKey(type.ToString() + (int)emplType, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey(type.ToString() + (int)emplType, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.PortalOwnerChange:
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD.HasValue, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD.HasValue, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.EmailChange:
checkKeyResult = Provider.ValidateEmailKey(email + type + AuthContext.CurrentAccount.ID, key, Provider.ValidInterval);
checkKeyResult = Provider.ValidateEmailKey(email + type + AuthContext.CurrentAccount.ID, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.PasswordChange:
var hash = Authentication.GetUserPasswordStamp(UserManager.GetUserByEmail(email).ID).ToString("s");
checkKeyResult = Provider.ValidateEmailKey(email + type + hash, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey(email + type + hash, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.Activation:
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.ProfileRemove:
// validate UiD
if (p == 1)
@ -261,13 +272,22 @@ namespace ASC.Security.Cryptography
return ValidationResult.Invalid;
}
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD, key, Provider.ValidInterval);
checkKeyResult = Provider.ValidateEmailKey(email + type + uiD, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.Wizard:
checkKeyResult = Provider.ValidateEmailKey("" + type, key, Provider.ValidInterval);
break;
checkKeyResult = Provider.ValidateEmailKey("" + type, key, Provider.ValidEmailKeyInterval);
break;
case ConfirmType.PhoneActivation:
case ConfirmType.PhoneAuth:
case ConfirmType.TfaActivation:
case ConfirmType.TfaAuth:
checkKeyResult = Provider.ValidateEmailKey(email + type, key, Provider.ValidAuthKeyInterval);
break;
default:
checkKeyResult = Provider.ValidateEmailKey(email + type, key, Provider.ValidInterval);
checkKeyResult = Provider.ValidateEmailKey(email + type, key, Provider.ValidEmailKeyInterval);
break;
}

View File

@ -29,6 +29,7 @@ using System.IO;
using System.Security.Cryptography;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Core.Encryption;
using Microsoft.Extensions.Configuration;
@ -292,12 +293,12 @@ namespace ASC.Data.Encryption
{
var dir = string.IsNullOrEmpty(TempDir) ? Path.GetDirectoryName(filePath) : TempDir;
var name = Path.GetFileNameWithoutExtension(filePath);
var result = Path.Combine(dir, string.Format("{0}_{1}{2}", Storage, name, ext));
var result = CrossPlatform.PathCombine(dir, string.Format("{0}_{1}{2}", Storage, name, ext));
var index = 1;
while (File.Exists(result))
{
result = Path.Combine(dir, string.Format("{0}_{1}({2}){3}", Storage, name, index++, ext));
result = CrossPlatform.PathCombine(dir, string.Format("{0}_{1}({2}){3}", Storage, name, index++, ext));
}
return result;

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64832/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.Data.Reassigns": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:64833/"
}
}
}

View File

@ -32,6 +32,7 @@ using System.Linq;
using System.Web;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Data.Storage.Configuration;
using ASC.Security.Cryptography;
@ -305,7 +306,7 @@ namespace ASC.Data.Storage
var filePaths = ListFilesRelative(domain, path, pattern, recursive);
return Array.ConvertAll(
filePaths,
x => GetUri(domain, Path.Combine(PathUtils.Normalize(path), x)));
x => GetUri(domain, CrossPlatform.PathCombine(PathUtils.Normalize(path), x)));
}
public bool IsFile(string path)

View File

@ -30,6 +30,7 @@ using System.IO;
using System.Linq;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
@ -177,7 +178,7 @@ namespace ASC.Core.ChunkedUploader
private string GetPathWithId(string id)
{
return Path.Combine(StoragePath, id + ".session");
return CrossPlatform.PathCombine(StoragePath, id + ".session");
}
}
}

View File

@ -30,6 +30,7 @@ using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ASC.Common.Utils;
using ASC.Common.Web;
using Microsoft.AspNetCore.Builder;
@ -103,12 +104,12 @@ namespace ASC.Data.Storage.DiscStorage
{
var pathInfo = GetRouteValue("pathInfo").Replace('/', Path.DirectorySeparatorChar);
var path = Path.Combine(physPath, pathInfo);
var path = CrossPlatform.PathCombine(physPath, pathInfo);
var tenant = GetRouteValue("0");
if (string.IsNullOrEmpty(tenant))
{
tenant = Path.Combine(GetRouteValue("t1"), GetRouteValue("t2"), GetRouteValue("t3"));
tenant = CrossPlatform.PathCombine(GetRouteValue("t1"), GetRouteValue("t2"), GetRouteValue("t3"));
}
path = path.Replace("{0}", tenant);

View File

@ -31,6 +31,7 @@ using System.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Encryption;
using ASC.Data.Storage.Configuration;
@ -647,7 +648,7 @@ namespace ASC.Data.Storage.DiscStorage
// Copy each file into it's new directory.
foreach (var fi in source.GetFiles())
{
var fp = Path.Combine(target.ToString(), fi.Name);
var fp = CrossPlatform.PathCombine(target.ToString(), fi.Name);
fi.CopyTo(fp, true);
var size = Crypt.GetFileSize(fp);
QuotaUsedAdd(newdomain, size);
@ -698,7 +699,7 @@ namespace ASC.Data.Storage.DiscStorage
{
var pathMap = GetPath(domain);
//Build Dir
var target = Path.Combine(pathMap.PhysicalPath, PathUtils.Normalize(path));
var target = CrossPlatform.PathCombine(pathMap.PhysicalPath, PathUtils.Normalize(path));
ValidatePath(target);
return target;
}

View File

@ -25,8 +25,10 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using ASC.Common.Utils;
namespace ASC.Data.Storage.DiscStorage
{
internal class MappedPath
@ -44,7 +46,7 @@ namespace ASC.Data.Storage.DiscStorage
tenant = tenant.Trim('/');
ppath = PathUtils.ResolvePhysicalPath(ppath, storageConfig);
PhysicalPath = ppath.IndexOf('{') == -1 && appendTenant ? Path.Combine(ppath, tenant) : string.Format(ppath, tenant);
PhysicalPath = ppath.IndexOf('{') == -1 && appendTenant ? CrossPlatform.PathCombine(ppath, tenant) : string.Format(ppath, tenant);
}
public MappedPath AppendDomain(string domain)
@ -52,7 +54,7 @@ namespace ASC.Data.Storage.DiscStorage
domain = domain.Replace('.', '_'); //Domain prep. Remove dots
return new MappedPath(PathUtils)
{
PhysicalPath = Path.Combine(PhysicalPath, PathUtils.Normalize(domain, true)),
PhysicalPath = CrossPlatform.PathCombine(PhysicalPath, PathUtils.Normalize(domain, true)),
};
}
}

View File

@ -29,6 +29,7 @@ using System.Collections.Generic;
using System.IO;
using ASC.Common;
using ASC.Common.Utils;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
@ -113,7 +114,7 @@ namespace ASC.Data.Storage
if (!Path.IsPathRooted(physPath))
{
physPath = Path.GetFullPath(Path.Combine(HostEnvironment.ContentRootPath, physPath.Trim(Path.DirectorySeparatorChar)));
physPath = Path.GetFullPath(CrossPlatform.PathCombine(HostEnvironment.ContentRootPath, physPath.Trim(Path.DirectorySeparatorChar)));
}
return physPath;
}

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:63105/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.Data.Storage": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:63106/"
}
}
}

View File

@ -35,6 +35,7 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Threading.Progress;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
@ -269,7 +270,7 @@ namespace ASC.Data.Storage
foreach (var file in directoryFiles)
{
var filePath = file.Substring(mappedPath.TrimEnd('/').Length);
tasks.Add(StaticUploader.UploadFileAsync(Path.Combine(relativePath, filePath), file, (res) => StepDone()));
tasks.Add(StaticUploader.UploadFileAsync(CrossPlatform.PathCombine(relativePath, filePath), file, (res) => StepDone()));
}
await Task.WhenAll(tasks);
@ -280,7 +281,7 @@ namespace ASC.Data.Storage
foreach (var file in directoryFiles)
{
var filePath = file.Substring(mappedPath.TrimEnd('/').Length);
StaticUploader.UploadFileAsync(Path.Combine(relativePath, filePath), file, (res) => StepDone()).Wait();
StaticUploader.UploadFileAsync(CrossPlatform.PathCombine(relativePath, filePath), file, (res) => StepDone()).Wait();
}
}
}

View File

@ -34,6 +34,7 @@ using System.Threading.Tasks;
using System.Web;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Security.Cryptography;
@ -75,7 +76,7 @@ namespace ASC.Data.Storage.DiscStorage
}
var storage = storageFactory.GetStorage(tenantManager.GetCurrentTenant().TenantId.ToString(CultureInfo.InvariantCulture), _module);
var path = Path.Combine(_path, GetRouteValue("pathInfo").Replace('/', Path.DirectorySeparatorChar));
var path = CrossPlatform.PathCombine(_path, GetRouteValue("pathInfo").Replace('/', Path.DirectorySeparatorChar));
var header = context.Request.Query[Constants.QUERY_HEADER].FirstOrDefault() ?? "";
var auth = context.Request.Query[Constants.QUERY_AUTH].FirstOrDefault() ?? "";

View File

@ -33,6 +33,7 @@ using System.Net;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.Data.Storage.Configuration;
@ -219,7 +220,7 @@ namespace ASC.Data.Storage
if (Uri.IsWellFormedUriString(path, UriKind.Relative) && HttpContextAccessor?.HttpContext != null)
{
//Local
Existing[path] = File.Exists(Path.Combine(HostEnvironment.ContentRootPath, path));
Existing[path] = File.Exists(CrossPlatform.PathCombine(HostEnvironment.ContentRootPath, path));
}
if (Uri.IsWellFormedUriString(path, UriKind.Absolute))
{

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:58519/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.FederatedLogin": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:58520/"
}
}
}

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56421/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.Notify.Textile": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:56422/"
}
}
}

View File

@ -19,6 +19,8 @@
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
<Compile Remove="Properties\**" />
<EmbeddedResource Remove="Properties\**" />
<None Remove="Properties\**" />
</ItemGroup>
</Project>

View File

@ -13,8 +13,11 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
<Compile Remove="VoxImplant\**" />
<EmbeddedResource Remove="Properties\**" />
<EmbeddedResource Remove="VoxImplant\**" />
<None Remove="Properties\**" />
<None Remove="VoxImplant\**" />
</ItemGroup>
@ -31,10 +34,6 @@
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\CachedVoipItem.proto" />
</ItemGroup>

View File

@ -27,6 +27,8 @@
using System.Collections.Generic;
using System.IO;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@ -56,7 +58,7 @@ namespace ASC.ApiSystem
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostingContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostingContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);

View File

@ -1,33 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5010",
"sslPort": 0
}
},
{
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "apisystem",
"log__dir": "../../../Logs"
}
},
"ASC.ApiSystem": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "http://localhost:5010",
"launchUrl": "http://localhost:5010/portal/test",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "apisystem",
"log__dir": "../../../Logs"
"log__dir": "../../../Logs",
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5010"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"launchUrl": "http://localhost:5010/portal/test",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "apisystem",
"log__dir": "../../../Logs",
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5010"
},
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59977/",
"sslPort": 44344
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASC.AuditTrail": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

View File

@ -34,7 +34,8 @@ using System.Threading;
using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Utils;
namespace ASC.Data.Backup
{
[Scope]
@ -103,7 +104,7 @@ namespace ASC.Data.Backup
{
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = string.Compare(Path.GetExtension(config), ".config", true) == 0 ? config : Path.Combine(config, "Web.config")
ExeConfigFilename = string.Compare(Path.GetExtension(config), ".config", true) == 0 ? config : CrossPlatform.PathCombine(config, "Web.config")
};
return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
}

View File

@ -11,6 +11,7 @@ using System.Xml.XPath;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Backup.EF.Context;
using Microsoft.EntityFrameworkCore;
@ -37,7 +38,7 @@ namespace ASC.Data.Backup
var file = connectionString.ElementInformation.Source;
if ("web.connections.config".Equals(Path.GetFileName(file), StringComparison.InvariantCultureIgnoreCase))
{
file = Path.Combine(Path.GetDirectoryName(file), "Web.config");
file = CrossPlatform.PathCombine(Path.GetDirectoryName(file), "Web.config");
}
var xconfig = XDocument.Load(file);
var provider = xconfig.XPathSelectElement("/configuration/system.data/DbProviderFactories/add[@invariant='" + connectionString.ProviderName + "']");

View File

@ -32,6 +32,7 @@ using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
@ -148,7 +149,7 @@ namespace ASC.Data.Backup
private string GetBackupPath(FileBackupInfo backupInfo)
{
return Path.Combine(backupInfo.Module, Path.Combine(backupInfo.Domain, backupInfo.Path.Replace('/', '\\')));
return CrossPlatform.PathCombine(backupInfo.Module, CrossPlatform.PathCombine(backupInfo.Domain, backupInfo.Path.Replace('/', '\\')));
}

View File

@ -28,6 +28,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using ASC.Common.Utils;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;
@ -65,7 +67,7 @@ namespace ASC.Data.Backup
public ZipReadOperator(string targetFile)
{
tmpdir = Path.Combine(Path.GetDirectoryName(targetFile), Path.GetFileNameWithoutExtension(targetFile).Replace('>', '_').Replace(':', '_').Replace('?', '_'));
tmpdir = CrossPlatform.PathCombine(Path.GetDirectoryName(targetFile), Path.GetFileNameWithoutExtension(targetFile).Replace('>', '_').Replace(':', '_').Replace('?', '_'));
Entries = new List<string>();
using var stream = File.OpenRead(targetFile);
@ -82,7 +84,7 @@ namespace ASC.Data.Backup
fullPath = streamReader.ReadToEnd().TrimEnd(char.MinValue);
}
fullPath = Path.Combine(tmpdir, fullPath);
fullPath = CrossPlatform.PathCombine(tmpdir, fullPath);
if (!Directory.Exists(Path.GetDirectoryName(fullPath)))
{
@ -111,7 +113,7 @@ namespace ASC.Data.Backup
public Stream GetEntry(string key)
{
var filePath = Path.Combine(tmpdir, key);
var filePath = CrossPlatform.PathCombine(tmpdir, key);
return File.Exists(filePath) ? File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read) : null;
}

View File

@ -2,6 +2,8 @@
using System.IO;
using System.Threading.Tasks;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@ -26,7 +28,7 @@ namespace ASC.Data.Backup
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,31 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5012/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "backup",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Data.Backup": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"launchUrl": "http://localhost:5012/api/2.0/backup/backuptmp",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "backup",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5012"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"launchUrl": "http://localhost:5012/api/2.0/backup/backuptmp",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "backup",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5012"
},
"applicationUrl": "http://localhost:5012/"
"distributionName": "Ubuntu-20.04"
}
}
}
}

View File

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using ASC.Common.Utils;
namespace ASC.Data.Backup.Service
{
public class BackupSettings
@ -52,7 +54,7 @@ namespace ASC.Data.Backup.Service
}
if (Elements.Count == 0)
{
return Path.Combine("..", "..", "WebStudio");
return CrossPlatform.PathCombine("..", "..", "WebStudio");
}
if (Elements.Count == 1)
{

View File

@ -34,6 +34,7 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Threading.Progress;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.Data.Backup.Contracts;
@ -378,7 +379,7 @@ namespace ASC.Data.Backup.Service
var dateTime = coreBaseSettings.Standalone ? DateTime.Now : DateTime.UtcNow;
var backupName = string.Format("{0}_{1:yyyy-MM-dd_HH-mm-ss}.{2}", tenantManager.GetTenant(TenantId).TenantAlias, dateTime, ArchiveFormat);
var tempFile = Path.Combine(TempFolder, backupName);
var tempFile = CrossPlatform.PathCombine(TempFolder, backupName);
var storagePath = tempFile;
try
{

View File

@ -28,7 +28,8 @@ using System;
using System.IO;
using ASC.Common;
using ASC.Common.Utils;
namespace ASC.Data.Backup.Storage
{
[Scope]
@ -40,7 +41,7 @@ namespace ASC.Data.Backup.Storage
{
throw new FileNotFoundException("Directory not found.");
}
var storagePath = Path.Combine(storageBasePath, Path.GetFileName(localPath));
var storagePath = CrossPlatform.PathCombine(storageBasePath, Path.GetFileName(localPath));
if (localPath != storagePath)
{
File.Copy(localPath, storagePath, true);

View File

@ -36,6 +36,7 @@ using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Data.Backup.EF.Context;
@ -152,9 +153,9 @@ namespace ASC.Data.Backup.Tasks
excluded.Add("res_");
var dir = Path.GetDirectoryName(BackupFilePath);
var subDir = Path.Combine(dir, Path.GetFileNameWithoutExtension(BackupFilePath));
var schemeDir = Path.Combine(subDir, KeyHelper.GetDatabaseSchema());
var dataDir = Path.Combine(subDir, KeyHelper.GetDatabaseData());
var subDir = CrossPlatform.PathCombine(dir, Path.GetFileNameWithoutExtension(BackupFilePath));
var schemeDir = CrossPlatform.PathCombine(subDir, KeyHelper.GetDatabaseSchema());
var dataDir = CrossPlatform.PathCombine(subDir, KeyHelper.GetDatabaseData());
if (!Directory.Exists(schemeDir))
{
@ -227,7 +228,7 @@ namespace ASC.Data.Backup.Tasks
.FirstOrDefault());
creates.Append(";");
var path = Path.Combine(dir, t);
var path = CrossPlatform.PathCombine(dir, t);
using (var stream = File.OpenWrite(path))
{
var bytes = Encoding.UTF8.GetBytes(creates.ToString());
@ -326,7 +327,7 @@ namespace ASC.Data.Backup.Tasks
}
}
var path = Path.Combine(dir, t);
var path = CrossPlatform.PathCombine(dir, t);
var offset = 0;
@ -443,11 +444,11 @@ namespace ASC.Data.Backup.Tasks
Logger.Debug("begin backup storage");
var dir = Path.GetDirectoryName(BackupFilePath);
var subDir = Path.Combine(dir, Path.GetFileNameWithoutExtension(BackupFilePath));
var subDir = CrossPlatform.PathCombine(dir, Path.GetFileNameWithoutExtension(BackupFilePath));
for (var i = 0; i < files.Count; i += TasksLimit)
{
var storageDir = Path.Combine(subDir, KeyHelper.GetStorage());
var storageDir = CrossPlatform.PathCombine(subDir, KeyHelper.GetStorage());
if (!Directory.Exists(storageDir))
{
@ -470,7 +471,7 @@ namespace ASC.Data.Backup.Tasks
var restoreInfoXml = new XElement("storage_restore", files.Select(file => (object)file.ToXElement()).ToArray());
var tmpPath = Path.Combine(subDir, KeyHelper.GetStorageRestoreInfoZipKey());
var tmpPath = CrossPlatform.PathCombine(subDir, KeyHelper.GetStorageRestoreInfoZipKey());
Directory.CreateDirectory(Path.GetDirectoryName(tmpPath));
using (var tmpFile = File.OpenWrite(tmpPath))
@ -490,7 +491,7 @@ namespace ASC.Data.Backup.Tasks
private async Task DoDumpFile(BackupFileInfo file, string dir)
{
var storage = StorageFactory.GetStorage(ConfigPath, file.Tenant.ToString(), file.Module);
var filePath = Path.Combine(dir, file.GetZipKey());
var filePath = CrossPlatform.PathCombine(dir, file.GetZipKey());
var dirName = Path.GetDirectoryName(filePath);
Logger.DebugFormat("backup file {0}", filePath);

View File

@ -26,6 +26,7 @@
using System.IO;
using ASC.Common.Utils;
using ASC.Data.Backup.Tasks.Modules;
namespace ASC.Data.Backup.Tasks
@ -66,7 +67,7 @@ namespace ASC.Data.Backup.Tasks
public static string GetZipKey(this BackupFileInfo file)
{
return Path.Combine(file.Module, file.Domain, file.Path);
return CrossPlatform.PathCombine(file.Module, file.Domain, file.Path);
}
public static string GetStorage()

View File

@ -34,6 +34,7 @@ using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Billing;
using ASC.Core.Tenants;
@ -286,7 +287,7 @@ namespace ASC.Data.Backup.Tasks
var key = file.GetZipKey();
if (Dump)
{
key = Path.Combine(KeyHelper.GetStorage(), key);
key = CrossPlatform.PathCombine(KeyHelper.GetStorage(), key);
}
using var stream = dataReader.GetEntry(key);
try

View File

@ -31,6 +31,7 @@ using System.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core.Tenants;
using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Modules;
@ -246,7 +247,7 @@ namespace ASC.Data.Backup.Tasks
if (!Directory.Exists(BackupDirectory ?? DefaultDirectoryName))
Directory.CreateDirectory(BackupDirectory ?? DefaultDirectoryName);
return Path.Combine(BackupDirectory ?? DefaultDirectoryName, tenantAlias + DateTime.UtcNow.ToString("(yyyy-MM-dd HH-mm-ss)") + ".backup");
return CrossPlatform.PathCombine(BackupDirectory ?? DefaultDirectoryName, tenantAlias + DateTime.UtcNow.ToString("(yyyy-MM-dd HH-mm-ss)") + ".backup");
}
}

View File

@ -27,6 +27,8 @@
using System.IO;
using System.Reflection;
using ASC.Common.Utils;
namespace ASC.Data.Backup.Utils
{
internal static class PathHelper
@ -40,7 +42,7 @@ namespace ASC.Data.Backup.Utils
{
if (!Path.IsPathRooted(path))
{
path = Path.Combine(basePath, path);
path = CrossPlatform.PathCombine(basePath, path);
}
return Path.GetFullPath(path);
}
@ -49,7 +51,7 @@ namespace ASC.Data.Backup.Utils
{
if (!Path.HasExtension(path))
{
path = Path.Combine(path, "Web.config");
path = CrossPlatform.PathCombine(path, "Web.config");
}
return ToRootedPath(path);
}
@ -59,7 +61,7 @@ namespace ASC.Data.Backup.Utils
string tempPath;
do
{
tempPath = Path.Combine(tempDir, Path.GetRandomFileName());
tempPath = CrossPlatform.PathCombine(tempDir, Path.GetRandomFileName());
} while (File.Exists(tempPath));
return tempPath;
}

View File

@ -26,6 +26,8 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@ -50,7 +52,7 @@ namespace ASC.Data.Storage.Encryption
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5019/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "Encryption",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Data.Storage.Encryption": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "Encryption",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5019",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "Encryption",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5019",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5019/"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -6,7 +6,8 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
@ -28,7 +29,7 @@ namespace ASC.Data.Storage.Migration
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,36 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5018/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "storage.migration",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Data.Storage.Migration": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "storage.migration",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5018",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "storage.migration",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5018",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5018/"
"distributionName": "Ubuntu-20.04"
}
}
}
}

View File

@ -18,6 +18,11 @@
<DebugType>none</DebugType>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
<EmbeddedResource Remove="Properties\**" />
<None Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<None Remove="protos\SearchItem.proto" />
</ItemGroup>
@ -37,9 +42,6 @@
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\SearchItem.proto" />
</ItemGroup>

View File

@ -6,6 +6,7 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core.Notify.Senders;
using ASC.Notify.Config;
@ -30,7 +31,7 @@ namespace ASC.Notify
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5005/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "notify",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Notify": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "notify",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5005",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "notify",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5005",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5005/"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -32,7 +32,8 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
@ -55,7 +56,7 @@ namespace ASC.Socket.IO.Svc
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5017/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "socket",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Socket.IO.Svc": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "socket",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5001",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "socket",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5001",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -87,7 +87,7 @@ namespace ASC.Socket.IO.Svc
UseShellExecute = false,
FileName = "node",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = string.Format("\"{0}\"", Path.GetFullPath(Path.Combine(HostEnvironment.ContentRootPath, settings.Path, "app.js"))),
Arguments = string.Format("\"{0}\"", Path.GetFullPath(CrossPlatform.PathCombine(HostEnvironment.ContentRootPath, settings.Path, "app.js"))),
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
};
StartInfo.EnvironmentVariables.Add("core.machinekey", Configuration["core:machinekey"]);
@ -105,7 +105,7 @@ namespace ASC.Socket.IO.Svc
}
LogDir = Logger.LogDirectory;
StartInfo.EnvironmentVariables.Add("logPath", Path.Combine(LogDir, "web.socketio.log"));
StartInfo.EnvironmentVariables.Add("logPath", CrossPlatform.PathCombine(LogDir, "web.socketio.log"));
StartNode();
}
catch (Exception e)

View File

@ -6,6 +6,7 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core.Notify;
using ASC.Notify;
using ASC.Web.Studio.Core.Notify;
@ -31,7 +32,7 @@ namespace ASC.Studio.Notify
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,33 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5006/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "studio.notify",
"log__dir": "../../../Logs"
}
},
"ASC.Studio.Notify": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "studio.notify",
"log__dir": "../../../Logs"
"log__dir": "../../../Logs",
"ASPNETCORE_URLS": "http://localhost:5006",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "studio.notify",
"log__dir": "../../../Logs",
"ASPNETCORE_URLS": "http://localhost:5006",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5006/"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -26,6 +26,8 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@ -50,7 +52,7 @@ namespace ASC.TelegramService
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51702/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "telegram",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.TelegramService": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "telegram",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:51702",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "telegram",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:51702",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:51702/"
"distributionName": "Ubuntu-20.04"
}
}
}
}

View File

@ -32,7 +32,8 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
@ -55,7 +56,7 @@ namespace ASC.Thumbnails.Svc
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5016/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "thumbnails",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.Thumbnails.Svc": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "thumbnails",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5016",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "thumbnails",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5016",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5016/"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -67,7 +67,7 @@ namespace ASC.Thumbnails.Svc
UseShellExecute = false,
FileName = "node",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = string.Format("\"{0}\"", Path.GetFullPath(Path.Combine(HostEnvironment.ContentRootPath, settings.Path, "index.js"))),
Arguments = string.Format("\"{0}\"", Path.GetFullPath(CrossPlatform.PathCombine(HostEnvironment.ContentRootPath, settings.Path, "index.js"))),
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
};
@ -77,7 +77,7 @@ namespace ASC.Thumbnails.Svc
savePath += "/";
}
StartInfo.EnvironmentVariables.Add("port", settings.Port);
StartInfo.EnvironmentVariables.Add("logPath", Path.Combine(Logger.LogDirectory, "web.thumbnails.log"));
StartInfo.EnvironmentVariables.Add("logPath", CrossPlatform.PathCombine(Logger.LogDirectory, "web.thumbnails.log"));
StartInfo.EnvironmentVariables.Add("savePath", Path.GetFullPath(savePath));
StartNode(cancellationToken);

View File

@ -31,7 +31,8 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
@ -54,7 +55,7 @@ namespace ASC.UrlShortener.Svc
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");

View File

@ -1,35 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5015/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "urlshortener",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.UrlShortener.Svc": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "urlshortener",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5017",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "urlshortener",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5017",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5015/"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -116,7 +116,7 @@ namespace ASC.UrlShortener.Svc
UseShellExecute = false,
FileName = "node",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = string.Format("\"{0}\"", Path.GetFullPath(Path.Combine(hostEnvironment.ContentRootPath, path))),
Arguments = string.Format("\"{0}\"", Path.GetFullPath(CrossPlatform.PathCombine(hostEnvironment.ContentRootPath, path))),
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
};
@ -146,7 +146,7 @@ namespace ASC.UrlShortener.Svc
}
}
startInfo.EnvironmentVariables.Add("logPath", Path.GetFullPath(Path.Combine(hostEnvironment.ContentRootPath, log.LogDirectory, "web.urlshortener.log")));
startInfo.EnvironmentVariables.Add("logPath", Path.GetFullPath(CrossPlatform.PathCombine(hostEnvironment.ContentRootPath, log.LogDirectory, "web.urlshortener.log")));
return startInfo;
}

View File

@ -1,5 +1,5 @@
{
"version": "0.1.3",
"version": "0.1.6",
"npmClient": "yarn",
"packages": [
"packages/asc-web-components",

View File

@ -183,7 +183,7 @@ class FilesFilter {
dtoFilter[FILTER_TYPE] = filterType;
}
if (withSubfolders === "false") {
if (withSubfolders) {
dtoFilter[SEARCH_TYPE] = withSubfolders;
}

View File

@ -453,6 +453,11 @@ export function getProgress() {
return request({ method: "get", url: "/files/fileops" });
}
export function checkFileConflicts(destFolderId, folderIds, fileIds) {
const data = { destFolderId, folderIds, fileIds };
return request({ method: "post", url: "/files/fileops/move", data });
}
export function copyToFolder(
destFolderId,
folderIds,

View File

@ -89,9 +89,13 @@ class PageLayout extends React.Component {
componentDidUpdate(prevProps) {
if (
this.props.hideAside &&
!this.state.isArticlePinned &&
this.props.hideAside !== prevProps.hideAside
(this.props.hideAside &&
!this.state.isArticlePinned &&
this.props.hideAside !== prevProps.hideAside) ||
(this.props.isLoading !== prevProps.isLoading &&
this.props.isLoaded &&
this.state.isArticleVisible &&
!this.state.isArticlePinned)
) {
this.backdropClick();
}

View File

@ -62,9 +62,9 @@ const StyledArticle = styled.article`
`
: `
position: fixed !important;
width: 240px !important;
min-width: 240px;
max-width: 240px;
width: 260px !important;
min-width: 260px;
max-width: 260px;
position: fixed;
height: 100% !important;
top: 0;
@ -73,6 +73,10 @@ const StyledArticle = styled.article`
.resizable-border {
display: none;
}
.newItem {
right: -24px;
}
`
: `
display: none;

View File

@ -103,6 +103,12 @@ export const ShareAccessRights = Object.freeze({
CustomFilter: 8,
});
export const ConflictResolveType = Object.freeze({
Skip: 0,
Overwrite: 1,
Duplicate: 2,
});
export const i18nBaseSettings = {
lng: localStorage.getItem(LANGUAGE) || "en",
supportedLngs: ["en", "ru"],

View File

@ -34,6 +34,7 @@ class SettingsStore {
organizationName = "ONLYOFFICE";
greetingSettings = "Web Office Applications";
enableAdmMess = false;
enabledJoin = false;
urlLicense = "https://gnu.org/licenses/gpl-3.0.html";
urlSupport = "https://helpdesk.onlyoffice.com/";
logoUrl = combineUrl(proxyURL, "/static/images/nav.logo.opened.react.svg");

View File

@ -6,11 +6,7 @@ import TopLoaderService from "@appserver/components/top-loading-indicator";
export const toUrlParams = (obj, skipNull) => {
let str = "";
for (var key in obj) {
if (
(skipNull && !obj[key] && key !== "withSubfolders") ||
(key === "withSubfolders" && obj[key] !== "false")
)
continue;
if (skipNull && !obj[key]) continue;
if (str !== "") {
str += "&";
@ -210,3 +206,10 @@ export function deleteCookie(name) {
"max-age": -1,
});
}
export function clickBackdrop() {
var elms = document.getElementsByClassName("backdrop-active");
if (elms && elms.length > 0) {
elms[0].click();
}
}

View File

@ -20,7 +20,8 @@ function getHorizontalCss(labelWidth) {
width: ${labelWidth};
}
.field-body {
flex-grow: ${(props) => props.theme.fieldContainer.horizontal.body.width};
flex-grow: ${(props) =>
props.theme.fieldContainer.horizontal.body.flexGrow};
}
.icon-button {
position: relative;

View File

@ -122,12 +122,14 @@ class GroupButton extends React.Component {
isChecked={checked}
isIndeterminate={isIndeterminate}
onChange={this.checkboxChange}
title={itemLabel}
/>
</StyledCheckbox>
)}
<StyledDropdownToggle
{...this.props}
onClick={this.dropDownToggleClick}
title={itemLabel}
>
{itemLabel}
<Caret isOpen={this.state.isOpen}>
@ -141,6 +143,7 @@ class GroupButton extends React.Component {
open={this.state.isOpen}
clickOutsideAction={this.clickOutsideAction}
showDisabledItems={true}
title={this.state.isOpen ? "" : itemLabel}
>
{React.Children.map(children, (child) => (
<DropDownItem
@ -151,9 +154,11 @@ class GroupButton extends React.Component {
</DropDown>
</>
) : (
<StyledDropdownToggle {...this.props}>{label}</StyledDropdownToggle>
<StyledDropdownToggle {...this.props} title={itemLabel}>
{label}
</StyledDropdownToggle>
)}
{isSeparator && <Separator />}
{isSeparator && <Separator title="" />}
</StyledGroupButton>
);
}

View File

@ -70,7 +70,7 @@ RadioButtonGroup.propTypes = {
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string.isRequired,
label: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.any, PropTypes.string]),
disabled: PropTypes.bool,
})
).isRequired,

View File

@ -83,7 +83,7 @@ RadioButton.propTypes = {
/** Used as HTML `disabled` property for each `<input>` tag */
isDisabled: PropTypes.bool,
/** Name of the radiobutton. If missed, `value` will be used */
label: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.any, PropTypes.string]),
/** Font size of link */
fontSize: PropTypes.string,
/** Font weight of link */

View File

@ -322,11 +322,7 @@ const TreeNodeMenu = styled(TreeNode)`
span.rc-tree-title:first-child {
max-width: 100%;
}
.newItem {
position: absolute;
right: 0px;
top: 2px;
}
.rc-tree-node-selected {
background: ${(props) => props.theme.treeNode.selected.background};
mix-blend-mode: normal;

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/crm",
"version": "0.1.3",
"version": "0.1.6",
"private": "true",
"homepage": "/products/crm",
"title": "ONLYOFFICE",

View File

@ -2,5 +2,6 @@
"ComingSoon": "Coming soon",
"ViewWeb": "View web version",
"OpenApp": "Open your {{title}} app",
"LearnMore": "Learn more"
"LearnMore": "Learn more",
"ModuleDescription": "Manage your contacts and sales"
}

View File

@ -2,5 +2,6 @@
"ComingSoon": "Скоро появится",
"ViewWeb": "Просмотреть веб-версию",
"OpenApp": "Откройте {{title}}",
"LearnMore": "Узнать больше"
"LearnMore": "Узнать больше",
"ModuleDescription": "Управляйте своими контактами и продажами"
}

View File

@ -11,9 +11,9 @@ import ExternalLinkIcon from "../../../../../../public/images/external.link.reac
import Loaders from "@appserver/common/components/Loaders";
import toastr from "studio/toastr";
import PageLayout from "@appserver/common/components/PageLayout";
import { useTranslation } from "react-i18next";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import { isMobile, isIOS } from "react-device-detect";
import { isMobile, isTablet, isIOS } from "react-device-detect";
import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react";
@ -34,14 +34,19 @@ const commonStyles = `
`;
const ComingSoonPage = styled.div`
padding: ${isMobile ? "62px 0 0 0" : "0"};
width: 336px;
padding: ${isTablet ? "106px 0 0 0" : isMobile ? "62px 0 0 0" : "0"};
width: ${isTablet ? "500px" : "336px"};
margin: 0 auto;
.module-logo-icon {
float: left;
margin-top: 8px;
margin-right: 16px;
svg {
width: ${isTablet ? "192px" : "96px"};
height: ${isTablet ? "192px" : "96px"};
}
}
.module-title {
@ -93,7 +98,10 @@ const StyledDesktopContainer = styled(EmptyScreenContainer)`
const ExternalLink = ({ label, href, onClick }) => (
<Box className="link-box">
<ExternalLinkIcon color="#333333" size={isMobile ? "small" : "medium"} />
<ExternalLinkIcon
color="#333333"
size={isMobile || isTablet ? "small" : "medium"}
/>
<Link
as="a"
href={href}
@ -109,20 +117,11 @@ const ExternalLink = ({ label, href, onClick }) => (
</Box>
);
const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
const { t } = useTranslation("ComingSoon");
const Body = ({ modules, match, isLoaded, setCurrentProductId, t, tReady }) => {
const { error } = match.params;
const { pathname, protocol, hostname } = window.location;
const currentModule = modules.find((m) => m.link === pathname);
const {
id,
title,
description,
imageUrl,
link,
originUrl,
helpUrl,
} = currentModule;
const { id, title, imageUrl, link, originUrl, helpUrl } = currentModule;
const url = originUrl ? originUrl : link;
const webLink = combineUrl(
protocol + "//" + hostname,
@ -172,8 +171,8 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
const moduleDescription = (
<Text className="module-info">
{description}{" "}
{helpUrl && (
{t("ModuleDescription")}{" "}
{helpUrl && false && (
<Link
as="a"
href={helpUrl}
@ -189,9 +188,9 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
</Text>
);
return !isLoaded ? (
return !isLoaded || !tReady ? (
<></>
) : isMobile ? (
) : isMobile || isTablet ? (
<ComingSoonPage>
<ReactSVG
className="module-logo-icon"
@ -208,7 +207,11 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
src={imageUrl}
/>
<Box displayProp="flex" flexDirection="column" widthProp="220px">
<Text fontWeight="600" fontSize="19px" className="module-title">
<Text
fontWeight="600"
fontSize={isTablet ? "24px" : "19px"}
className="module-title"
>
{title}
</Text>
{moduleDescription}
@ -245,7 +248,7 @@ const ComingSoonWrapper = inject(({ auth }) => ({
modules: auth.moduleStore.modules,
isLoaded: auth.isLoaded,
setCurrentProductId: auth.settingsStore.setCurrentProductId,
}))(withRouter(ComingSoon));
}))(withRouter(withTranslation("ComingSoon")(ComingSoon)));
export default (props) => (
<I18nextProvider i18n={i18n}>

View File

@ -1,6 +1,10 @@
using System.Collections.Generic;
using System.IO;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@ -16,35 +20,59 @@ namespace ASC.CRM
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
.ConfigureAppConfiguration((hostingContext, config) =>
{
path = Path.GetFullPath(Path.Combine(hostingContext.HostingEnvironment.ContentRootPath, path));
}
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(CrossPlatform.PathCombine(hostingContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
config
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddInMemoryCollection(new Dictionary<string, string>
{
config.SetBasePath(path);
config
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path}
});
})
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration, true, false);
});
});
//if (!FilesIntegration.IsRegisteredFileSecurityProvider("crm", "crm_common"))
//{
// FilesIntegration.RegisterFileSecurityProvider("crm", "crm_common", new FileSecurityProvider());
//}
////Register prodjects' calendar events
//CalendarManager.Instance.RegistryCalendarProvider(userid =>
//{
// if (WebItemSecurity.IsAvailableForUser(WebItemManager.CRMProductID, userid))
// {
// return new List<BaseCalendar> { new CRMCalendar(userid) };
// }
// return new List<BaseCalendar>();
//});
}
}
}

View File

@ -1,31 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5021",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"launchUrl": "http://localhost:5021/api/2.0/crm/info",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__dir": "../../../Logs",
"log__name": "crm",
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5021"
}
},
"ASC.CRM": {
"commandName": "Project",
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"launchUrl": "http://localhost:5021/api/2.0/crm/info",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__dir": "../../../Logs",
"log__name": "crm",
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5021"
},
"applicationUrl": "http://localhost:5021"
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/files",
"version": "0.1.3",
"version": "0.1.6",
"private": "true",
"homepage": "/products/files",
"id": "e67be73d-f9ae-4ce1-8fec-1880cb518cb4",

View File

@ -0,0 +1,14 @@
{
"OKButton": "OK",
"CancelButton": "Cancel",
"ConflictResolveTitle": "Overwrite confirmation",
"ConflictResolveDescription": "The file with the name {{file}} already exists in the folder {{folder}}.",
"ConflictResolveDescriptionFiles": "{{filesCount}} documents with the same name already exist in the folder '{{folder}}'.",
"ConflictResolveSelectAction": "Please select the action:",
"OverwriteTitle": "Overwrite with version update",
"OverwriteDescription": "The file will be added to the file with the same name as a version.",
"CreateTitle": "Create file copy",
"CreateDescription": "There will be two different files in the folder.",
"SkipTitle": "Skip",
"SkipDescription": "No file will be copied. The original file will be retained in the destination folder."
}

View File

@ -0,0 +1,14 @@
{
"OKButton": "ОК",
"CancelButton": "Отмена",
"ConflictResolveTitle": "Подтверждение перезаписи",
"ConflictResolveDescription": "Файл с именем {{file}} уже существует в папке {{folder}}.",
"ConflictResolveDescriptionFiles": "{{filesCount}} документов с одинаковыми именами уже существуют в папке '{{folder}}'.",
"ConflictResolveSelectAction": "Пожалуйста, выберите действие:",
"OverwriteTitle": "Перезаписать с обновлением версии",
"OverwriteDescription": "Файл будет добавлен к файлу с таким же именем как версия.",
"CreateTitle": "Создать копию файла",
"CreateDescription": "В папке будет два разных файла.",
"SkipTitle": "Пропустить",
"SkipDescription": "Файл не будет скопирован. В папке назначения останется исходный файл."
}

View File

@ -98,11 +98,12 @@ const PureThirdPartyListContainer = ({
nextCloudConnectItem,
webDavConnectItem,
setConnectItem,
setThirdPartyDialogVisible,
setConnectDialogVisible,
setSelectedNode,
setSelectedFolder,
getOAuthToken,
openConnectWindow,
setThirdPartyDialogVisible,
history,
}) => {
const redirectAction = () => {
@ -125,7 +126,8 @@ const PureThirdPartyListContainer = ({
"Authorization",
"height=600, width=1020"
);
openConnectWindow(data.title, authModal).then((modal) =>
openConnectWindow(data.title, authModal).then((modal) => {
redirectAction();
getOAuthToken(modal).then((token) => {
const serviceData = {
title: data.title,
@ -134,17 +136,17 @@ const PureThirdPartyListContainer = ({
token,
};
setConnectItem(serviceData);
})
);
setConnectDialogVisible(true);
});
});
} else {
setConnectItem(data);
setConnectDialogVisible(true);
redirectAction();
}
onShowConnectPanel();
};
const onShowConnectPanel = () => {
//setThirdPartyDialogVisible((prev) => !prev); TODO:
setThirdPartyDialogVisible(true);
redirectAction();
};
@ -233,7 +235,11 @@ export default inject(
openConnectWindow,
} = settingsStore.thirdPartyStore;
const { setConnectItem, setThirdPartyDialogVisible } = dialogsStore;
const {
setConnectItem,
setConnectDialogVisible,
setThirdPartyDialogVisible,
} = dialogsStore;
return {
googleConnectItem,
@ -247,9 +253,10 @@ export default inject(
setSelectedFolder,
setSelectedNode,
setConnectItem,
setThirdPartyDialogVisible,
setConnectDialogVisible,
getOAuthToken,
openConnectWindow,
setThirdPartyDialogVisible,
};
}
)(observer(ThirdPartyList));

View File

@ -364,8 +364,7 @@ class TreeFolders extends React.Component {
const treeData = [...this.props.treeFolders];
this.getNewTreeData(treeData, listIds, data.folders, 10);
this.props.needUpdate && this.props.setTreeFolders(treeData);
//this.setState({ treeData });
/* this.props.needUpdate && */ this.props.setTreeFolders(treeData);
})
.catch((err) => toastr.error(err))
.finally(() => {
@ -374,15 +373,16 @@ class TreeFolders extends React.Component {
});
};
onExpand = (data, treeNode) => {
onExpand = (expandedKeys, treeNode) => {
if (treeNode.node && !treeNode.node.props.children) {
if (treeNode.expanded) {
this.onLoadData(treeNode.node, true);
}
}
if (this.props.needUpdate) {
const expandedKeys = data;
this.props.setExpandedKeys(expandedKeys);
} else {
this.props.setExpandedPanelKeys(expandedKeys);
}
};
@ -431,9 +431,10 @@ class TreeFolders extends React.Component {
onSelect,
dragging,
expandedKeys,
expandedPanelKeys,
treeFolders,
data,
} = this.props;
//const loadProp = needUpdate ? { loadData: this.onLoadData } : {};
return (
<StyledTreeMenu
@ -446,9 +447,8 @@ class TreeFolders extends React.Component {
switcherIcon={this.switcherIcon}
onSelect={onSelect}
selectedKeys={selectedKeys}
//{...loadProp}
loadData={this.onLoadData}
expandedKeys={expandedKeys}
expandedKeys={expandedPanelKeys ? expandedPanelKeys : expandedKeys}
onExpand={this.onExpand}
onDragOver={this.onDragOver}
onDragLeave={this.onDragLeave}
@ -458,7 +458,7 @@ class TreeFolders extends React.Component {
gapBetweenNodesTablet="26"
isFullFillSelection={false}
>
{this.getItems(treeFolders)}
{this.getItems(data || treeFolders)}
</StyledTreeMenu>
);
}
@ -488,6 +488,7 @@ export default inject(
isPrivacyFolder,
expandedKeys,
setExpandedKeys,
setExpandedPanelKeys,
} = treeFoldersStore;
const { id /* rootFolderType */ } = selectedFolderStore;
@ -510,6 +511,7 @@ export default inject(
setTreeFolders,
setFilter,
setExpandedKeys,
setExpandedPanelKeys,
};
}
)(observer(TreeFolders));

View File

@ -10,7 +10,7 @@ import ThirdPartyList from "./ThirdPartyList";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router-dom";
import config from "../../../../package.json";
import { combineUrl } from "@appserver/common/utils";
import { clickBackdrop, combineUrl } from "@appserver/common/utils";
import { AppServerConfig } from "@appserver/common/constants";
class ArticleBodyContent extends React.Component {
@ -45,6 +45,7 @@ class ArticleBodyContent extends React.Component {
if (!selectedTreeNode || selectedTreeNode[0] !== data[0]) {
setSelectedNode(data);
setIsLoading(true);
const newFilter = filter.clone();
newFilter.page = 0;
newFilter.startIndex = 0;
@ -60,8 +61,12 @@ class ArticleBodyContent extends React.Component {
if (window.location.pathname.indexOf("/filter") > 0) {
fetchFiles(data[0], newFilter)
.catch((err) => toastr.error(err))
.finally(() => setIsLoading(false));
.finally(() => {
setIsLoading(false);
});
} else {
newFilter.startIndex = 0;
const urlFilter = newFilter.toUrlParams();
history.push(

View File

@ -16,6 +16,7 @@ import {
DeleteDialog,
DownloadDialog,
ThirdPartyDialog,
ConflictResolveDialog,
} from "../dialogs";
const Panels = (props) => {
@ -34,6 +35,7 @@ const Panels = (props) => {
emptyTrashDialogVisible,
thirdPartyDialogVisible,
newFilesPanelVisible,
conflictResolveDialogVisible,
} = props;
return [
@ -63,6 +65,9 @@ const Panels = (props) => {
downloadDialogVisible && <DownloadDialog key="download-dialog" />,
thirdPartyDialogVisible && <ThirdPartyDialog key="thirdparty-dialog" />,
newFilesPanelVisible && <NewFilesPanel key="new-files-panel" />,
conflictResolveDialogVisible && (
<ConflictResolveDialog key="conflict-resolve-dialog" />
),
];
};
@ -81,6 +86,7 @@ export default inject(
emptyTrashDialogVisible,
thirdPartyDialogVisible,
newFilesPanelVisible,
conflictResolveDialogVisible,
connectItem, //TODO:
} = dialogsStore;
@ -103,6 +109,7 @@ export default inject(
emptyTrashDialogVisible,
thirdPartyDialogVisible,
newFilesPanelVisible,
conflictResolveDialogVisible,
};
}
)(observer(Panels));

View File

@ -0,0 +1,184 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import ModalDialogContainer from "../ModalDialogContainer";
import ModalDialog from "@appserver/components/modal-dialog";
import RadioButtonGroup from "@appserver/components/radio-button-group";
import Button from "@appserver/components/button";
import Text from "@appserver/components/text";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { ConflictResolveType } from "@appserver/common/constants";
const ConflictResolveDialog = (props) => {
const {
t,
visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
items,
itemOperationToFolder,
} = props;
const {
destFolderId,
folderIds,
fileIds,
deleteAfter,
folderTitle,
isCopy,
translations,
} = conflictResolveDialogData;
const [resolveType, setResolveType] = useState("overwrite");
const onSelectResolveType = (e) => setResolveType(e.target.value);
const onClose = () => setConflictResolveDialogVisible(false);
const getResolveType = () => {
switch (resolveType) {
case "skip":
return ConflictResolveType.Skip;
case "overwrite":
return ConflictResolveType.Overwrite;
case "create":
return ConflictResolveType.Duplicate;
default:
return ConflictResolveType.Overwrite;
}
};
const onAcceptType = () => {
const conflictResolveType = getResolveType();
let newFileIds = fileIds;
if (conflictResolveType === ConflictResolveType.Skip) {
for (let item of items) {
newFileIds = newFileIds.filter((x) => x.id === item.id);
}
}
if (!folderIds.length && !newFileIds.length) return onClose();
const data = {
destFolderId,
folderIds,
fileIds: newFileIds,
conflictResolveType,
deleteAfter,
isCopy,
translations,
};
onClose();
itemOperationToFolder(data);
};
const radioOptions = [
{
label: (
<div>
<Text>{t("OverwriteTitle")}</Text>
<Text>{t("OverwriteDescription")}</Text>
</div>
),
value: "overwrite",
},
{
label: (
<div>
<Text>{t("CreateTitle")}</Text>
<Text>{t("CreateDescription")}</Text>
</div>
),
value: "create",
},
{
label: (
<div>
<Text>{t("SkipTitle")}</Text>
<Text>{t("SkipDescription")}</Text>
</div>
),
value: "skip",
},
];
const filesCount = items.length;
const singleFile = filesCount === 1;
const file = items[0].title;
return (
<ModalDialogContainer>
<ModalDialog visible={visible} onClose={onClose}>
<ModalDialog.Header>{t("ConflictResolveTitle")}</ModalDialog.Header>
<ModalDialog.Body>
<Text className="conflict-resolve-dialog-text">
{singleFile
? t("ConflictResolveDescription", { file, folder: folderTitle })
: t("ConflictResolveDescriptionFiles", {
filesCount,
folder: folderTitle,
})}
</Text>
<Text className="conflict-resolve-dialog-text">
{t("ConflictResolveSelectAction")}
</Text>
<RadioButtonGroup
className="conflict-resolve-radio-button"
orientation="vertical"
fontSize="13px"
fontWeight="400"
name="group"
onClick={onSelectResolveType}
options={radioOptions}
selected="overwrite"
/>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
className="button-dialog-accept"
key="OkButton"
label={t("OKButton")}
size="medium"
primary
onClick={onAcceptType}
//isLoading={isLoading}
/>
<Button
className="button-dialog"
key="CancelButton"
label={t("CancelButton")}
size="medium"
onClick={onClose}
//isLoading={isLoading}
/>
</ModalDialog.Footer>
</ModalDialog>
</ModalDialogContainer>
);
};
export default inject(({ dialogsStore, uploadDataStore }) => {
const {
conflictResolveDialogVisible: visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
conflictResolveDialogItems: items,
} = dialogsStore;
const { itemOperationToFolder } = uploadDataStore;
return {
items,
visible,
conflictResolveDialogData,
setConflictResolveDialogVisible,
itemOperationToFolder,
};
})(
withRouter(
withTranslation("ConflictResolveDialog")(observer(ConflictResolveDialog))
)
);

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from "react";
import toastr from "@appserver/components/toast";
import toastr from "studio/toastr";
import Button from "@appserver/components/button";
import ModalDialog from "@appserver/components/modal-dialog";
import Checkbox from "@appserver/components/checkbox";
@ -155,6 +155,7 @@ const PureConnectDialogContainer = (props) => {
})
.catch((err) => {
toastr.error(err);
onClose();
setIsLoading(false);
});
}, [

View File

@ -7,10 +7,10 @@ import Text from "@appserver/components/text";
import Checkbox from "@appserver/components/checkbox";
import Scrollbar from "@appserver/components/scrollbar";
import { withTranslation } from "react-i18next";
import { getProgress, removeFiles } from "@appserver/common/api/files";
//import { getProgress, removeFiles } from "@appserver/common/api/files";
import toastr from "studio/toastr";
import { TIMEOUT } from "../../../helpers/constants";
import { loopTreeFolders } from "../../../helpers/files-helpers";
//import { TIMEOUT } from "../../../helpers/constants";
//import { loopTreeFolders } from "../../../helpers/files-helpers";
import { inject, observer } from "mobx-react";
class DeleteDialogComponent extends React.Component {
@ -52,7 +52,11 @@ class DeleteDialogComponent extends React.Component {
deleteSelectedElem: t("DeleteSelectedElem"),
};
deleteAction(translations).catch((err) => toastr.error(err));
const selection = this.state.selection.filter((f) => f.checked);
if (!selection.length) return;
deleteAction(translations, selection).catch((err) => toastr.error(err));
};
onChange = (event) => {

View File

@ -88,46 +88,32 @@ class DownloadDialogComponent extends React.Component {
getDownloadItems = () => {
const { documents, spreadsheets, presentations, other } = this.state;
const items = [];
const files = [];
const folders = [];
for (let item of documents) {
if (item.checked) {
const format =
item.format === 0 ? item.fileExst : this.getTitleLabel(item.format);
items.push({ key: item.id, value: format });
}
}
for (let item of spreadsheets) {
if (item.checked) {
const format =
item.format === 0 ? item.fileExst : this.getTitleLabel(item.format);
items.push({ key: item.id, value: format });
}
}
for (let item of presentations) {
if (item.checked) {
const format =
item.format === 0 ? item.fileExst : this.getTitleLabel(item.format);
items.push({ key: item.id, value: format });
}
}
for (let item of other) {
if (item.checked) {
if (item.fileExst) {
const format =
item.format === 0 ? item.fileExst : this.getTitleLabel(item.format);
items.push({ key: item.id, value: format });
} else {
folders.push(item.id);
const collectItems = (itemList) => {
for (let item of itemList) {
if (item.checked) {
if (item.fileExst) {
const format =
item.format === 0
? item.fileExst
: this.getTitleLabel(item.format);
const viewUrl = item.viewUrl;
files.push({ key: item.id, value: format, viewUrl });
} else {
folders.push(item.id);
}
}
}
}
};
return [items, folders];
collectItems(documents);
collectItems(spreadsheets);
collectItems(presentations);
collectItems(other);
return [files, folders];
};
//TODO: move to actions?
@ -140,11 +126,18 @@ class DownloadDialogComponent extends React.Component {
clearSecondaryProgressData,
} = this.props;
const downloadItems = this.getDownloadItems();
const fileConvertIds = downloadItems[0];
const folderIds = downloadItems[1];
const [fileConvertIds, folderIds] = this.getDownloadItems();
if (fileConvertIds.length || folderIds.length) {
if (fileConvertIds.length === 1 && folderIds.length === 0) {
// Single file download as
const file = fileConvertIds[0];
let viewUrl = file.viewUrl;
if (file.value) {
viewUrl = `${viewUrl}&outputtype=${file.value}`;
}
window.open(viewUrl, "_blank");
this.onClose();
} else if (fileConvertIds.length || folderIds.length) {
setSecondaryProgressBarData({
icon: "file",
visible: true,
@ -155,8 +148,9 @@ class DownloadDialogComponent extends React.Component {
downloadFormatFiles(fileConvertIds, folderIds)
.then((res) => {
this.onClose();
getDownloadProgress(res[0], t("ArchivingData"))
.catch((err) => toastr.error(err));
getDownloadProgress(res[0], t("ArchivingData")).catch((err) =>
toastr.error(err)
);
})
.catch((err) => {
setSecondaryProgressBarData({
@ -438,6 +432,13 @@ class DownloadDialogComponent extends React.Component {
const showOther = otherLength > 1;
const minHeight = otherLength > 2 ? 110 : otherLength * 50;
const isSingleFile =
documents.filter((f) => f.checked).length +
spreadsheets.filter((f) => f.checked).length +
presentations.filter((f) => f.checked).length +
other.filter((f) => f.checked).length ===
1;
return (
<ModalDialogContainer>
<ModalDialog visible={visible} onClose={this.onClose}>
@ -550,7 +551,7 @@ class DownloadDialogComponent extends React.Component {
</>
)}
<Text>{t("ConvertToZip")}</Text>
{!isSingleFile && <Text>{t("ConvertToZip")}</Text>}
<Text>{t("ConvertMessage")}</Text>
</ModalDialog.Body>
<ModalDialog.Footer>

View File

@ -127,6 +127,16 @@ const ModalDialogContainer = styled.div`
width: 90%;
}
}
.conflict-resolve-dialog-text {
padding-bottom: 8px;
}
.conflict-resolve-radio-button {
svg {
overflow: visible;
}
}
`;
export default ModalDialogContainer;

View File

@ -84,16 +84,17 @@ const ThirdPartyDialog = (props) => {
};
const showOAuthModal = (token, serviceData) => {
setConnectDialogVisible(true);
setConnectItem({
title: serviceData.title,
provider_key: serviceData.title,
link: serviceData.link,
token,
});
setConnectDialogVisible(true);
};
const onShowService = (e) => {
setThirdPartyDialogVisible(false);
const item = e.currentTarget.dataset;
const showAccountSetting = !e.currentTarget.dataset.link;
if (!showAccountSetting) {
@ -103,12 +104,14 @@ const ThirdPartyDialog = (props) => {
"height=600, width=1020"
);
openConnectWindow(item.title, authModal).then((modal) =>
getOAuthToken(modal).then((token) => showOAuthModal(token, item))
getOAuthToken(modal).then((token) => {
showOAuthModal(token, item);
setConnectItem(item);
setConnectDialogVisible(true);
})
);
}
setConnectDialogVisible(true);
setConnectItem(item);
setThirdPartyDialogVisible(false);
};

View File

@ -19,13 +19,11 @@ const PureThirdPartyMoveContainer = ({
provider,
selection,
destFolderId,
copyToAction,
moveToAction,
setDestFolderId,
checkOperationConflict,
setThirdPartyMoveDialogVisible,
}) => {
const zIndex = 310;
const conflictResolveType = 0; //Skip = 0, Overwrite = 1, Duplicate = 2 TODO: get from settings
const deleteAfter = true; // TODO: get from settings
const onClose = () => {
@ -33,7 +31,8 @@ const PureThirdPartyMoveContainer = ({
setThirdPartyMoveDialogVisible(false);
};
const getOperationItems = () => {
const startOperation = (e) => {
const isCopy = e.target.dataset.copy;
const folderIds = [];
const fileIds = [];
@ -44,36 +43,16 @@ const PureThirdPartyMoveContainer = ({
folderIds.push(item.id);
}
}
return [folderIds, fileIds];
};
const startMoveOperation = () => {
const result = getOperationItems();
const folderIds = result[0];
const fileIds = result[1];
moveToAction(
const data = {
destFolderId,
folderIds,
fileIds,
conflictResolveType,
deleteAfter
);
onClose();
};
deleteAfter,
isCopy,
};
const startCopyOperation = () => {
const result = getOperationItems();
const folderIds = result[0];
const fileIds = result[1];
copyToAction(
destFolderId,
folderIds,
fileIds,
conflictResolveType,
deleteAfter
);
checkOperationConflict(data);
onClose();
};
@ -93,13 +72,14 @@ const PureThirdPartyMoveContainer = ({
label={t("Move")}
size="big"
primary
onClick={startMoveOperation}
onClick={startOperation}
/>
<Button
data-copy="copy"
className="operation-button"
label={t("Copy")}
size="big"
onClick={startCopyOperation}
onClick={startOperation}
/>
<Button
className="operation-button"
@ -121,7 +101,7 @@ export default inject(({ filesStore, dialogsStore, filesActionsStore }) => {
setDestFolderId,
} = dialogsStore;
const { selection } = filesStore;
const { copyToAction, moveToAction } = filesActionsStore;
const { checkOperationConflict } = filesActionsStore;
return {
visible,
@ -129,8 +109,7 @@ export default inject(({ filesStore, dialogsStore, filesActionsStore }) => {
destFolderId,
setDestFolderId,
provider: selection[0].providerKey,
copyToAction,
moveToAction,
checkOperationConflict,
selection,
};
})(

View File

@ -6,6 +6,7 @@ import DeleteThirdPartyDialog from "./DeleteThirdPartyDialog";
import ConnectDialog from "./ConnectDialog";
import ThirdPartyMoveDialog from "./ThirdPartyMoveDialog";
import ThirdPartyDialog from "./ThirdPartyDialog";
import ConflictResolveDialog from "./ConflictResolveDialog";
export {
EmptyTrashDialog,
@ -16,4 +17,5 @@ export {
ConnectDialog,
ThirdPartyMoveDialog,
ThirdPartyDialog,
ConflictResolveDialog,
};

View File

@ -1,4 +1,4 @@
import React, { memo, useState } from "react";
import React, { useState } from "react";
import styled from "styled-components";
import Button from "@appserver/components/button";
import TextInput from "@appserver/components/text-input";
@ -125,4 +125,4 @@ const EditingWrapperComponent = (props) => {
);
};
export default memo(EditingWrapperComponent);
export default EditingWrapperComponent;

View File

@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useState } from "react";
import { inject, observer } from "mobx-react";
import RowContainer from "@appserver/components/row-container";
import { Consumer } from "@appserver/components/utils/context";
@ -6,9 +6,35 @@ import SimpleFilesRow from "./SimpleFilesRow";
import Loaders from "@appserver/common/components/Loaders";
import { isMobile } from "react-device-detect";
const FilesRowContainer = (props) => {
const { isLoaded, isLoading } = props;
return !isLoaded || (isMobile && isLoading) ? (
let loadTimeout = null;
const FilesRowContainer = ({ isLoaded, isLoading, filesList, tReady }) => {
const [inLoad, setInLoad] = useState(false);
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
useEffect(() => {
if (isLoading) {
cleanTimer();
loadTimeout = setTimeout(() => {
console.log("inLoad", true);
setInLoad(true);
}, 500);
} else {
cleanTimer();
console.log("inLoad", false);
setInLoad(false);
}
return () => {
cleanTimer();
};
}, [isLoading]);
return !isLoaded || (isMobile && inLoad) || !tReady ? (
<Loaders.Rows />
) : (
<Consumer>
@ -18,9 +44,9 @@ const FilesRowContainer = (props) => {
draggable
useReactWindow={false}
>
{props.filesList.map((item) => (
{filesList.map((item, index) => (
<SimpleFilesRow
key={item.id}
key={`${item.id}_${index}`}
item={item}
sectionWidth={context.sectionWidth}
/>

View File

@ -251,13 +251,18 @@ class FilesRowContent extends React.PureComponent {
});
};
// componentDidUpdate(prevProps) {
// if (fileAction) {
// if (fileActionId !== prevProps.fileActionId) {
// this.setState({ editingId: fileActionId });
// }
// }
// }
componentDidUpdate(prevProps) {
const { fileActionId, fileActionExt } = this.props;
if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) {
const itemTitle = this.getDefaultName(fileActionExt);
this.setState({ itemTitle });
}
// if (fileAction) {
// if (fileActionId !== prevProps.fileActionId) {
// this.setState({ editingId: fileActionId });
// }
// }
}
renameTitle = (e) => {
let title = e.target.value;
@ -544,10 +549,9 @@ class FilesRowContent extends React.PureComponent {
item.access === ShareAccessRights.None; // TODO: fix access type for owner (now - None)
const isEdit = id === fileActionId && fileExst === fileActionExt;
const linkStyles =
isTrashFolder || window.innerWidth <= 1024
? { noHover: true }
: { onClick: this.onFilesClick };
const linkStyles = isTrashFolder //|| window.innerWidth <= 1024
? { noHover: true }
: { onClick: this.onFilesClick };
const newItems = item.new || fileStatus === 2;
const showNew = !!newItems;
@ -577,7 +581,7 @@ class FilesRowContent extends React.PureComponent {
isMobile={isMobile}
sideColor={sideColor}
isFile={fileExst || contentLength}
onClick={this.onMobileRowClick}
//onClick={this.onMobileRowClick}
>
<Link
containerWidth="55%"

View File

@ -111,6 +111,8 @@ const SimpleFilesRow = createSelectable((props) => {
setTooltipPosition,
setDownloadDialogVisible,
downloadAction,
confirmDelete,
setDeleteDialogVisible,
} = props;
const {
@ -270,17 +272,21 @@ const SimpleFilesRow = createSelectable((props) => {
return;
}
const translations = {
deleteOperation: t("DeleteOperation"),
};
if (confirmDelete) {
setDeleteDialogVisible(true);
} else {
const translations = {
deleteOperation: t("DeleteOperation"),
};
fileExst || contentLength
? deleteFileAction(id, folderId, translations)
.then(() => toastr.success(t("FileRemoved")))
.catch((err) => toastr.error(err))
: deleteFolderAction(id, parentId, translations)
.then(() => toastr.success(t("FolderRemoved")))
.catch((err) => toastr.error(err));
fileExst || contentLength
? deleteFileAction(id, folderId, translations)
.then(() => toastr.success(t("FileRemoved")))
.catch((err) => toastr.error(err))
: deleteFolderAction(id, parentId, translations)
.then(() => toastr.success(t("FolderRemoved")))
.catch((err) => toastr.error(err));
}
};
const rowContextClick = () => {
@ -560,6 +566,7 @@ const SimpleFilesRow = createSelectable((props) => {
return (
<div ref={props.selectableRef}>
<DragAndDrop
data-title={item.title}
value={value}
className={className}
onDrop={onDrop}
@ -599,6 +606,7 @@ export default inject(
filesActionsStore,
mediaViewerDataStore,
uploadDataStore,
settingsStore,
},
{ item }
) => {
@ -614,6 +622,7 @@ export default inject(
setMoveToPanelVisible,
setCopyPanelVisible,
setDownloadDialogVisible,
setDeleteDialogVisible,
} = dialogsStore;
const {
@ -625,6 +634,7 @@ export default inject(
setDragging,
setStartDrag,
setTooltipPosition,
isFileSelected,
} = filesStore;
const { isRootFolder, id: selectedFolderId } = selectedFolderStore;
@ -669,7 +679,7 @@ export default inject(
isRecycleBin: isRecycleBinFolder,
isRootFolder,
canShare,
checked: selection.some((el) => el.id === item.id),
checked: isFileSelected(item.id, item.parentId),
isFolder,
draggable,
isItemsSelected: !!selection.length,
@ -704,6 +714,8 @@ export default inject(
onSelectItem,
setTooltipPosition,
downloadAction,
confirmDelete: settingsStore.confirmDelete,
setDeleteDialogVisible,
};
}
)(withTranslation("Home")(observer(withRouter(SimpleFilesRow))));

View File

@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Loaders from "@appserver/common/components/Loaders";
@ -10,9 +10,12 @@ import EmptyContainer from "./EmptyContainer";
let currentDroppable = null;
let loadTimeout = null;
const SectionBodyContent = (props) => {
const {
t,
tReady,
fileActionId,
viewAs,
firstLoad,
@ -28,6 +31,31 @@ const SectionBodyContent = (props) => {
moveDragItems,
} = props;
const [inLoad, setInLoad] = useState(false);
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
useEffect(() => {
if (isLoading) {
cleanTimer();
loadTimeout = setTimeout(() => {
console.log("inLoad", true);
setInLoad(true);
}, 500);
} else {
cleanTimer();
console.log("inLoad", false);
setInLoad(false);
}
return () => {
cleanTimer();
};
}, [isLoading]);
useEffect(() => {
const customScrollElm = document.querySelector(
"#customScrollBar > .scroll-body"
@ -98,6 +126,7 @@ const SectionBodyContent = (props) => {
const treeValue = isDragging ? treeClassList[index].split("_")[1] : null;
const elem = e.target.closest(".droppable");
const title = elem && elem.dataset.title;
const value = elem && elem.getAttribute("value");
if ((!value && !treeValue) || isRecycleBinFolder) {
setDragging(false);
@ -109,13 +138,16 @@ const SectionBodyContent = (props) => {
setStartDrag(false);
setDragging(false);
onMoveTo(folderId);
onMoveTo(folderId, title);
return;
};
const onMoveTo = (destFolderId) => {
const onMoveTo = (destFolderId, title) => {
const id = isNaN(+destFolderId) ? destFolderId : +destFolderId;
moveDragItems(id, t("MoveToOperation")); //TODO: then catch
moveDragItems(id, title, {
copy: t("CopyOperation"),
move: t("MoveToOperation"),
}); //TODO: then catch
};
const onDropEvent = () => {
@ -142,7 +174,7 @@ const SectionBodyContent = (props) => {
//console.log("Files Home SectionBodyContent render", props);
return (!fileActionId && isEmptyFilesList) || null ? (
firstLoad || (isMobile && isLoading) ? (
firstLoad || (isMobile && inLoad) ? (
<Loaders.Rows />
) : (
<EmptyContainer />
@ -150,7 +182,7 @@ const SectionBodyContent = (props) => {
) : viewAs === "tile" ? (
<FilesTileContainer />
) : (
<FilesRowContainer />
<FilesRowContainer tReady={tReady} />
);
};

View File

@ -258,32 +258,39 @@ class SectionFilterContent extends React.Component {
return selectedFilterData;
};
isTranslationsLoaded = () => {
const { t, i18n } = this.props;
// isTranslationsLoaded = () => { // used tReady instead of this
// const { t, i18n } = this.props;
const { store, services, language } = i18n;
// const { store, services, language } = i18n;
let translationIsLoaded = false;
try {
translationIsLoaded = store.hasResourceBundle(
services.languageUtils.getLanguagePartFromCode(language),
"Home"
);
} catch {
translationIsLoaded = t("UserStatus") !== "UserStatus";
}
// let translationIsLoaded = false;
// try {
// translationIsLoaded = store.hasResourceBundle(
// services.languageUtils.getLanguagePartFromCode(language),
// "Home"
// );
// } catch {
// translationIsLoaded = t("UserStatus") !== "UserStatus";
// }
return translationIsLoaded;
};
// return translationIsLoaded;
// };
render() {
//console.log("Filter render");
const selectedFilterData = this.getSelectedFilterData();
const { t, firstLoad, sectionWidth } = this.props;
const {
t,
firstLoad,
sectionWidth,
tReady,
isAnyItems,
filterSearch,
} = this.props;
const filterColumnCount =
window.innerWidth < 500 ? {} : { filterColumnCount: 3 };
return firstLoad && !this.isTranslationsLoaded() ? (
return !isAnyItems && !filterSearch ? null : !tReady ? (
<Loaders.Filter />
) : (
<FilterInput
@ -314,10 +321,14 @@ export default inject(({ auth, filesStore, selectedFolderStore }) => {
setIsLoading,
setViewAs,
viewAs,
files,
folders,
} = filesStore;
const { user } = auth.userStore;
const { customNames, culture } = auth.settingsStore;
const isAnyItems = !!files.length || !!folders.length;
const filterSearch = filter.search;
return {
customNames,
@ -331,6 +342,9 @@ export default inject(({ auth, filesStore, selectedFolderStore }) => {
setIsLoading,
fetchFiles,
setViewAs,
isAnyItems,
filterSearch,
};
})(
withRouter(

Some files were not shown because too many files have changed in this diff Show More