Merge branch 'develop' into feature/thumbnails

# Conflicts:
#	products/ASC.Files/Client/src/pages/Home/Section/Filter/index.js
#	yarn.lock
This commit is contained in:
Artem Tarasov 2021-05-11 10:30:19 +03:00
commit 58a41faa4a
166 changed files with 3377 additions and 2416 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ Data/
Logs/ Logs/
**/.DS_Store **/.DS_Store
.eslintcache .eslintcache
build/deploy/

View File

@ -3,12 +3,8 @@
<solution> <solution>
<add key="disableSourceControlIntegration" value="true" /> <add key="disableSourceControlIntegration" value="true" />
</solution> </solution>
<config>
<add key="repositorypath" value="$\..\..\packages" />
</config>
<packageSources> <packageSources>
<add key="Pomelo" value="https://pkgs.dev.azure.com/pomelo-efcore/Pomelo.EntityFrameworkCore.MySql/_packaging/pomelo-efcore-public/nuget/v3/index.json" /> <add key="Custom NuGet Server" value=".nuget\packages" />
<add key="Custom NuGet Server" value="packages" />
<add key="NuGet official package source" value="https://api.nuget.org/v3/index.json" /> <add key="NuGet official package source" value="https://api.nuget.org/v3/index.json" />
</packageSources> </packageSources>
<packageRestore> <packageRestore>

16
build/Jenkinsfile vendored
View File

@ -6,14 +6,14 @@ pipeline {
stage('Unix') { stage('Unix') {
agent { label 'net-core' } agent { label 'net-core' }
stages { stages {
stage('Backend') { stage('Frontend') {
steps { steps {
sh 'yarn install && yarn build' sh 'yarn install && yarn build'
} }
} }
stage('Frontend') { stage('Backend') {
steps { steps {
sh 'dotnet build ASC.Web.sln --configfile .nuget/NuGet.Config' sh 'dotnet build ASC.Web.sln'
} }
} }
} }
@ -21,14 +21,14 @@ pipeline {
stage('Windows') { stage('Windows') {
agent { label 'win-core' } agent { label 'win-core' }
stages { stages {
stage('Backend') { stage('Frontend') {
steps { steps {
bat 'yarn install && yarn build' bat 'yarn install && yarn build'
} }
} }
stage('Frontend') { stage('Backend') {
steps { steps {
bat 'dotnet build ASC.Web.sln --configfile .nuget\\NuGet.Config' bat 'dotnet build ASC.Web.sln'
} }
} }
} }
@ -62,7 +62,7 @@ pipeline {
} }
stage('Files') { stage('Files') {
steps { steps {
sh "dotnet build ASC.Web.sln --configfile .nuget/NuGet.Config && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\"" sh "dotnet build ASC.Web.sln && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\""
} }
} }
} }
@ -90,7 +90,7 @@ pipeline {
} }
stage('Files') { stage('Files') {
steps { steps {
bat "dotnet build ASC.Web.sln --configfile .nuget\\NuGet.Config && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj" bat "dotnet build ASC.Web.sln && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj"
} }
} }
} }

View File

@ -42,7 +42,7 @@ done
echo "== BACK-END-BUILD ==" echo "== BACK-END-BUILD =="
cd ${SRC_PATH} cd ${SRC_PATH}
dotnet restore ASC.Web.sln --configfile .nuget/NuGet.Config ${ARGS} dotnet restore ASC.Web.sln${ARGS}
dotnet build ASC.Web.sln ${ARGS} dotnet build ASC.Web.sln ${ARGS}
echo "== Build ASC.Thumbnails ==" echo "== Build ASC.Thumbnails =="

View File

@ -140,7 +140,7 @@ RUN cd /app/onlyoffice/src/ && \
cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \ cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \
mkdir -p /etc/nginx/includes/ && cp -f config/nginx/includes/onlyoffice*.conf /etc/nginx/includes/ && \ mkdir -p /etc/nginx/includes/ && cp -f config/nginx/includes/onlyoffice*.conf /etc/nginx/includes/ && \
sed -e 's/#//' -i /etc/nginx/conf.d/onlyoffice.conf && \ sed -e 's/#//' -i /etc/nginx/conf.d/onlyoffice.conf && \
dotnet restore ASC.Web.sln --configfile .nuget/NuGet.Config && \ dotnet restore ASC.Web.sln && \
dotnet build -r linux-x64 ASC.Web.sln && \ dotnet build -r linux-x64 ASC.Web.sln && \
cd products/ASC.People/Server && \ cd products/ASC.People/Server && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/products/ASC.People/server && \ dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/products/ASC.People/server && \

View File

@ -44,7 +44,18 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd ${SRC_PATH}/build/install/common/ && \ cd ${SRC_PATH}/build/install/common/ && \
bash build-frontend.sh -sp ${SRC_PATH} && \ bash build-frontend.sh -sp ${SRC_PATH} && \
bash build-backend.sh -sp ${SRC_PATH} -ar "--disable-parallel" && \ bash build-backend.sh -sp ${SRC_PATH} -ar "--disable-parallel" && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel" bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel" && \
rm -rf ${SRC_PATH}/common/* && \
rm -rf ${SRC_PATH}/web/ASC.Web.Core/* && \
rm -rf ${SRC_PATH}/web/ASC.Web.Studio/* && \
rm -rf ${SRC_PATH}/products/ASC.Calendar/Server/* && \
rm -rf ${SRC_PATH}/products/ASC.CRM/Server/* && \
rm -rf ${SRC_PATH}/products/ASC.Files/Server/* && \
rm -rf ${SRC_PATH}/products/ASC.Files/Service/* && \
rm -rf ${SRC_PATH}/products/ASC.Mail/Server/* && \
rm -rf ${SRC_PATH}/products/ASC.People/Server/* && \
rm -rf ${SRC_PATH}/products/ASC.Projects/Server/*
COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf

View File

@ -48,7 +48,7 @@ npm i && cd ../../../)
npm run-script build --prefix products/ASC.People/Client npm run-script build --prefix products/ASC.People/Client
cd %{_builddir}/AppServer-%GIT_BRANCH/ cd %{_builddir}/AppServer-%GIT_BRANCH/
dotnet restore ASC.Web.sln --configfile .nuget/NuGet.Config dotnet restore ASC.Web.sln
dotnet build -r linux-x64 ASC.Web.sln dotnet build -r linux-x64 ASC.Web.sln
cd products/ASC.People/Server cd products/ASC.People/Server
dotnet -d publish --no-build --self-contained -r linux-x64 -o %{_builddir}%{_var}/www/appserver/products/ASC.People/server dotnet -d publish --no-build --self-contained -r linux-x64 -o %{_builddir}%{_var}/www/appserver/products/ASC.People/server

View File

@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -60,7 +60,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0-alpha.2" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0" />
<PackageReference Include="System.Text.Json" Version="5.0.2" /> <PackageReference Include="System.Text.Json" Version="5.0.2" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" /> <PackageReference Include="Telegram.Bot" Version="15.7.1" />
</ItemGroup> </ItemGroup>

View File

@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
@ -6,9 +6,6 @@
<Company>Ascensio System SIA</Company> <Company>Ascensio System SIA</Company>
<Product>ASC.Notify.Textile</Product> <Product>ASC.Notify.Textile</Product>
<Copyright>(c) Ascensio System SIA. All rights reserved</Copyright> <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>

View File

@ -14,6 +14,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" /> <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -24,8 +24,11 @@
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.Utils; using ASC.Common.Utils;
@ -39,18 +42,40 @@ namespace ASC.ApiSystem
{ {
public class Program public class Program
{ {
public static void Main(string[] args) public async static Task Main(string[] args)
{ {
CreateHostBuilder(args).Build().Run(); var host = CreateHostBuilder(args).Build();
await host.RunAsync();
} }
public static IHostBuilder CreateHostBuilder(string[] args) public static IHostBuilder CreateHostBuilder(string[] args) =>
{ Host.CreateDefaultBuilder(args)
return Host.CreateDefaultBuilder(args) .UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
}) })
.ConfigureAppConfiguration((hostingContext, config) => .ConfigureAppConfiguration((hostingContext, config) =>
{ {
@ -76,6 +101,5 @@ namespace ASC.ApiSystem
}); });
}); });
}
} }
} }

View File

@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -23,6 +23,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="SharpCompress" Version="0.26.0" /> <PackageReference Include="SharpCompress" Version="0.26.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,5 +1,7 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using ASC.Common.Utils; using ASC.Common.Utils;
@ -13,14 +15,41 @@ using Microsoft.Extensions.Hosting;
namespace ASC.Data.Backup namespace ASC.Data.Backup
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
await Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
}) })
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -46,10 +75,7 @@ namespace ASC.Data.Backup
{"pathToConf", path } {"pathToConf", path }
} }
); );
}) });
.UseConsoleLifetime()
.Build()
.RunAsync();
}
} }
} }

View File

@ -22,6 +22,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="SharpCompress" Version="0.26.0" /> <PackageReference Include="SharpCompress" Version="0.26.0" />
</ItemGroup> </ItemGroup>

View File

@ -22,8 +22,10 @@
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
* *
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using ASC.Common.Utils; using ASC.Common.Utils;
@ -38,13 +40,40 @@ namespace ASC.Data.Storage.Encryption
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
await Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
}) })
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -69,10 +98,6 @@ namespace ASC.Data.Storage.Encryption
.AddJsonFile("kafka.json") .AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true) .AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) });
.UseConsoleLifetime()
.Build()
.RunAsync();
}
} }
} }

View File

@ -4,6 +4,11 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\ASC.Common\ASC.Common.csproj" /> <ProjectReference Include="..\..\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" /> <ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />

View File

@ -19,9 +19,17 @@ namespace ASC.Data.Storage.Migration
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
await Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -64,10 +72,6 @@ namespace ASC.Data.Storage.Migration
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration); builder.Register(context.Configuration);
}) });
.UseConsoleLifetime()
.Build()
.RunAsync();
}
} }
} }

View File

@ -13,7 +13,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -21,9 +21,17 @@ namespace ASC.Notify
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
var host = Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -73,18 +81,6 @@ namespace ASC.Notify
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration); builder.Register(context.Configuration);
}) });
.UseConsoleLifetime()
.Build();
using (host)
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
} }
} }

View File

@ -16,6 +16,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="WebSocketSharp" Version="1.0.3-rc11" /> <PackageReference Include="WebSocketSharp" Version="1.0.3-rc11" />
</ItemGroup> </ItemGroup>

View File

@ -46,9 +46,17 @@ namespace ASC.Socket.IO.Svc
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
var host = Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -90,18 +98,7 @@ namespace ASC.Socket.IO.Svc
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration, false, false); builder.Register(context.Configuration, false, false);
}) });
.UseConsoleLifetime() }
.Build(); }
using (host)
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
}
}

View File

@ -10,6 +10,11 @@
<DebugSymbols>false</DebugSymbols> <DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" /> <ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
<ProjectReference Include="..\..\ASC.Data.Encryption\ASC.Data.Encryption.csproj" /> <ProjectReference Include="..\..\ASC.Data.Encryption\ASC.Data.Encryption.csproj" />

View File

@ -22,9 +22,17 @@ namespace ASC.Studio.Notify
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
var host = Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -67,18 +75,6 @@ namespace ASC.Studio.Notify
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration); builder.Register(context.Configuration);
}) });
.UseConsoleLifetime()
.Build();
using (host)
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
} }
} }

View File

@ -13,7 +13,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" /> <PackageReference Include="Telegram.Bot" Version="15.7.1" />
</ItemGroup> </ItemGroup>

View File

@ -22,8 +22,10 @@
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
* *
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using ASC.Common.Utils; using ASC.Common.Utils;
@ -38,13 +40,40 @@ namespace ASC.TelegramService
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
await Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
}) })
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
@ -69,10 +98,6 @@ namespace ASC.TelegramService
.AddJsonFile("kafka.json") .AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true) .AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) });
.UseConsoleLifetime()
.Build()
.RunAsync();
}
} }
} }

View File

@ -21,5 +21,10 @@
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
</Project> </Project>

View File

@ -26,6 +26,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using ASC.Common; using ASC.Common;
@ -45,11 +46,19 @@ using Microsoft.Extensions.Hosting;
namespace ASC.Thumbnails.Svc namespace ASC.Thumbnails.Svc
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
var host = Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => .ConfigureAppConfiguration((hostContext, config) =>
{ {
var buided = config.Build(); var buided = config.Build();
@ -89,18 +98,6 @@ namespace ASC.Thumbnails.Svc
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration, false, false); builder.Register(context.Configuration, false, false);
}) });
.UseConsoleLifetime()
.Build();
using (host)
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
} }
} }

View File

@ -13,7 +13,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -44,59 +44,60 @@ using Microsoft.Extensions.Hosting;
namespace ASC.UrlShortener.Svc namespace ASC.UrlShortener.Svc
{ {
public class Program public class Program
{ {
public static async Task Main(string[] args) public async static Task Main(string[] args)
{ {
var host = Host.CreateDefaultBuilder(args) var host = CreateHostBuilder(args).Build();
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) => await host.RunAsync();
{ }
var buided = config.Build();
var path = buided["pathToConf"]; public static IHostBuilder CreateHostBuilder(string[] args) =>
if (!Path.IsPathRooted(path)) Host.CreateDefaultBuilder(args)
{ .UseSystemd()
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path)); .UseWindowsService()
} .UseServiceProviderFactory(new AutofacServiceProviderFactory())
config.SetBasePath(path); .ConfigureAppConfiguration((hostContext, config) =>
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production"); {
config var buided = config.Build();
.AddJsonFile("appsettings.json") var path = buided["pathToConf"];
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile($"urlshortener.{env}.json", true) if (!Path.IsPathRooted(path))
.AddJsonFile("storage.json") {
.AddJsonFile("kafka.json") path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
.AddJsonFile($"kafka.{env}.json", true) }
.AddEnvironmentVariables()
.AddCommandLine(args) config.SetBasePath(path);
.AddInMemoryCollection(new Dictionary<string, string>
{ var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");
{"pathToConf", path }
} config.AddJsonFile("appsettings.json")
); .AddJsonFile($"appsettings.{env}.json", true)
}) .AddJsonFile($"urlshortener.{env}.json", true)
.ConfigureServices((hostContext, services) => .AddJsonFile("storage.json")
{ .AddJsonFile("kafka.json")
services.AddMemoryCache(); .AddJsonFile($"kafka.{env}.json", true)
var diHelper = new DIHelper(services); .AddEnvironmentVariables()
LogNLogExtension.ConfigureLog(diHelper, "ASC.UrlShortener.Svc"); .AddCommandLine(args)
services.AddHostedService<UrlShortenerServiceLauncher>(); .AddInMemoryCollection(new Dictionary<string, string>
diHelper.TryAdd<UrlShortenerServiceLauncher>(); {
}) {"pathToConf", path }
.ConfigureContainer<ContainerBuilder>((context, builder) => }
{ );
builder.Register(context.Configuration, false, false); })
}) .ConfigureServices((hostContext, services) =>
.UseConsoleLifetime() {
.Build(); services.AddMemoryCache();
using (host) var diHelper = new DIHelper(services);
{
// Start the host LogNLogExtension.ConfigureLog(diHelper, "ASC.UrlShortener.Svc");
await host.StartAsync(); services.AddHostedService<UrlShortenerServiceLauncher>();
diHelper.TryAdd<UrlShortenerServiceLauncher>();
// Wait for the host to shutdown })
await host.WaitForShutdownAsync(); .ConfigureContainer<ContainerBuilder>((context, builder) =>
} {
} builder.Register(context.Configuration, false, false);
});
} }
} }

View File

@ -4,6 +4,12 @@
"Default": "Information", "Default": "Information",
"Microsoft": "Warning", "Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
},
"EventLog": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*",

View File

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

View File

@ -1,6 +1,7 @@
{ {
"name": "appserver", "name": "appserver",
"private": true, "private": true,
"version": "0.1.9",
"workspaces": [ "workspaces": [
"packages/asc-web-components", "packages/asc-web-components",
"packages/asc-web-common", "packages/asc-web-common",
@ -16,14 +17,16 @@
], ],
"scripts": { "scripts": {
"wipe": "rimraf node_modules yarn.lock web/**/node_modules products/**/node_modules", "wipe": "rimraf node_modules yarn.lock web/**/node_modules products/**/node_modules",
"build": "yarn workspaces run build", "build": "concurrently \"wsrun --parallel build\"",
"start": "concurrently \"wsrun --parallel start\"", "start": "concurrently \"wsrun --parallel start\"",
"start-prod": "concurrently \"wsrun --parallel start-prod\"", "start-prod": "concurrently \"wsrun --parallel start-prod\"",
"serve": "concurrently \"wsrun --parallel serve\"", "serve": "concurrently \"wsrun --parallel serve\"",
"test": "yarn workspace @appserver/components test", "test": "yarn workspace @appserver/components test",
"clean": "concurrently \"wsrun --parallel clean\"", "clean": "concurrently \"wsrun --parallel clean\"",
"storybook": "yarn workspace @appserver/components storybook", "storybook": "yarn workspace @appserver/components storybook",
"storybook-build": "yarn workspace @appserver/components run storybook-build" "storybook-build": "yarn workspace @appserver/components run storybook-build",
"bump": "lerna version --no-push --no-git-tag-version",
"deploy": "rimraf build/deploy && concurrently \"wsrun --parallel deploy\""
}, },
"devDependencies": { "devDependencies": {
"lerna": "^3.22.1", "lerna": "^3.22.1",

View File

@ -12,7 +12,7 @@ export function openEdit(fileId, version, doc) {
} }
if (doc) { if (doc) {
params.push(`version=${version}`); params.push(`doc=${doc}`);
} }
const paramsString = params.length > 0 ? `?${params.join("&")}` : ""; const paramsString = params.length > 0 ? `?${params.join("&")}` : "";
@ -638,8 +638,7 @@ export function getSettingsFiles() {
} }
export function markAsFavorite(ids) { export function markAsFavorite(ids) {
let items = ids.map((id) => +id); const data = { fileIds: ids };
const data = { fileIds: items };
const options = { const options = {
method: "post", method: "post",
url: "/files/favorites", url: "/files/favorites",
@ -650,8 +649,7 @@ export function markAsFavorite(ids) {
} }
export function removeFromFavorite(ids) { export function removeFromFavorite(ids) {
let items = ids.map((id) => +id); const data = { fileIds: ids };
const data = { fileIds: items };
const options = { const options = {
method: "delete", method: "delete",
url: "/files/favorites", url: "/files/favorites",

View File

@ -1,4 +1,4 @@
import styled from "styled-components"; import styled, { keyframes, css } from "styled-components";
const backgroundColor = "none"; const backgroundColor = "none";
const color = "#2DA7DB"; const color = "#2DA7DB";
@ -11,6 +11,15 @@ const StyledCircleWrap = styled.div`
cursor: pointer; cursor: pointer;
`; `;
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const StyledCircle = styled.div` const StyledCircle = styled.div`
.circle__mask, .circle__mask,
.circle__fill { .circle__fill {
@ -20,14 +29,24 @@ const StyledCircle = styled.div`
border-radius: 50%; border-radius: 50%;
} }
.circle__mask { ${(props) =>
clip: rect(0px, 54px, 54px, 27px); props.percent > 0
} ? css`
.circle__mask {
clip: rect(0px, 54px, 54px, 27px);
}
.circle__fill { .circle__fill {
animation: fill-rotate ease-in-out none; animation: fill-rotate ease-in-out none;
transform: rotate(${(props) => props.percent * 1.8}deg); transform: rotate(${(props) => props.percent * 1.8}deg);
} }
`
: css`
.circle__fill {
animation: ${rotate360} 2s linear infinite;
transform: translate(0);
}
`}
.circle__mask .circle__fill { .circle__mask .circle__fill {
clip: rect(0px, 27px, 54px, 0px); clip: rect(0px, 27px, 54px, 0px);

View File

@ -15,7 +15,7 @@ import CrossIcon from "../../../../public/images/cross.react.svg";
import commonIconsStyles from "@appserver/components/utils/common-icons-style"; import commonIconsStyles from "@appserver/components/utils/common-icons-style";
const StyledVideoViewer = styled(VideoViewer)` const StyledVideoViewer = styled(VideoViewer)`
z-index: 4001; z-index: 301;
`; `;
const mediaTypes = Object.freeze({ const mediaTypes = Object.freeze({
audio: 1, audio: 1,
@ -181,12 +181,14 @@ class MediaViewer extends React.Component {
} }
componentWillUnmount() { componentWillUnmount() {
this.hammer.off("swipeleft", this.nextMedia); if (this.hammer) {
this.hammer.off("swiperight", this.prevMedia); this.hammer.off("swipeleft", this.nextMedia);
this.hammer.off("pinchout", this.prevMedia); this.hammer.off("swiperight", this.prevMedia);
this.hammer.off("pinchin", this.prevMedia); this.hammer.off("pinchout", this.prevMedia);
this.hammer.off("pinchend", this.prevMedia); this.hammer.off("pinchin", this.prevMedia);
this.hammer.off("doubletap", this.prevMedia); this.hammer.off("pinchend", this.prevMedia);
this.hammer.off("doubletap", this.prevMedia);
}
document.removeEventListener("keydown", this.onKeydown, false); document.removeEventListener("keydown", this.onKeydown, false);
document.removeEventListener("keyup", this.onKeyup, false); document.removeEventListener("keyup", this.onKeyup, false);
} }

View File

@ -6,7 +6,7 @@ const StyledMediaViewer = styled.div`
overflow: hidden; overflow: hidden;
.videoViewerOverlay { .videoViewerOverlay {
position: fixed; position: fixed;
z-index: 4000; z-index: 300;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
@ -15,7 +15,7 @@ const StyledMediaViewer = styled.div`
opacity: 0.5; opacity: 0.5;
} }
.mediaViewerToolbox { .mediaViewerToolbox {
z-index: 4001; z-index: 301;
padding-top: 14px; padding-top: 14px;
padding-bottom: 14px; padding-bottom: 14px;
height: 20px; height: 20px;
@ -31,7 +31,7 @@ const StyledMediaViewer = styled.div`
right: 0; right: 0;
bottom: 5px; bottom: 5px;
margin-right: 10px; margin-right: 10px;
z-index: 4005; z-index: 305;
} }
.deleteBtnContainer, .deleteBtnContainer,
.downloadBtnContainer { .downloadBtnContainer {
@ -41,7 +41,7 @@ const StyledMediaViewer = styled.div`
line-height: 19px; line-height: 19px;
} }
.details { .details {
z-index: 4002; z-index: 302;
padding-top: 14px; padding-top: 14px;
padding-bottom: 14px; padding-bottom: 14px;
height: 20px; height: 20px;

View File

@ -38,11 +38,11 @@ const StyledMediaDownloadIcon = styled(MediaDownloadIcon)`
const StyledViewer = styled(Viewer)` const StyledViewer = styled(Viewer)`
.react-viewer-footer { .react-viewer-footer {
bottom: 5px !important; bottom: 5px !important;
z-index: 4001 !important; z-index: 301 !important;
overflow: visible; overflow: visible;
} }
.react-viewer-canvas { .react-viewer-canvas {
z-index: 4000 !important; z-index: 300 !important;
margin-top: 50px; margin-top: 50px;
} }
.react-viewer-navbar, .react-viewer-navbar,

View File

@ -4,7 +4,7 @@ import styled from "styled-components";
const ScrollButton = styled.div` const ScrollButton = styled.div`
cursor: ${(props) => (props.inactive ? "default" : "pointer")}; cursor: ${(props) => (props.inactive ? "default" : "pointer")};
opacity: ${(props) => (props.inactive ? "0.2" : "1")}; opacity: ${(props) => (props.inactive ? "0.2" : "1")};
z-index: 4005; z-index: 305;
position: fixed; position: fixed;
top: calc(50% - 20px); top: calc(50% - 20px);

View File

@ -19,7 +19,7 @@ const StyledControls = styled.div`
height: ${(props) => props.height}px; height: ${(props) => props.height}px;
display: block; display: block;
position: fixed; position: fixed;
z-index: 4001; z-index: 301;
${(props) => !props.isVideo && "background-color: rgba(11,11,11,0.7);"} ${(props) => !props.isVideo && "background-color: rgba(11,11,11,0.7);"}
top: calc(50% + ${(props) => props.top}px); top: calc(50% + ${(props) => props.top}px);
left: ${(props) => props.left}px; left: ${(props) => props.left}px;
@ -174,13 +174,13 @@ const StyledVideoViewer = styled.div`
height: ${(props) => props.height}px; height: ${(props) => props.height}px;
left: ${(props) => props.left}px; left: ${(props) => props.left}px;
top: calc(50% - ${(props) => props.top / 2}px); top: calc(50% - ${(props) => props.top / 2}px);
z-index: 4001; z-index: 301;
position: fixed; position: fixed;
padding-bottom: 40px; padding-bottom: 40px;
background-color: rgba(11, 11, 11, 0.7); background-color: rgba(11, 11, 11, 0.7);
video { video {
z-index: 4000; z-index: 300;
} }
} }
`; `;

View File

@ -111,7 +111,7 @@ class SectionBody extends React.Component {
const focusProps = autoFocus const focusProps = autoFocus
? { ? {
ref: this.focusRef, ref: this.focusRef,
tabIndex: 1, tabIndex: -1,
} }
: {}; : {};

View File

@ -163,3 +163,27 @@ export const LoaderStyle = {
import config from "./AppServerConfig"; import config from "./AppServerConfig";
export const AppServerConfig = config; export const AppServerConfig = config;
/**
* Enum for Tenant trusted domains on registration.
* @readonly
*/
export const TenantTrustedDomainsType = Object.freeze({
None: 0,
Custom: 1,
All: 2,
});
export const FilesFormats = Object.freeze({
OriginalFormat: 0,
TxtFormat: 1,
DocxFormat: 2,
OdtFormat: 3,
OdsFormat: 4,
OdpFormat: 5,
PdfFormat: 6,
RtfFormat: 7,
XlsxFormat: 8,
PptxFormat: 9,
CustomFormat: 10,
});

View File

@ -1,12 +1,13 @@
{ {
"name": "@appserver/common", "name": "@appserver/common",
"version": "0.0.2", "version": "0.1.9",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "echo 'skip it'", "build": "echo 'skip it'",
"start": "echo 'skip it'", "start": "echo 'skip it'",
"start-prod": "echo 'skip it'", "start-prod": "echo 'skip it'",
"clean": "echo 'skip it'" "clean": "echo 'skip it'",
"deploy": "echo 'skip it'"
}, },
"api": { "api": {
"url": "/api/2.0", "url": "/api/2.0",

View File

@ -8,7 +8,7 @@ import UserStore from "./UserStore";
import { logout as logoutDesktop, desktopConstants } from "../desktop"; import { logout as logoutDesktop, desktopConstants } from "../desktop";
import { combineUrl, isAdmin } from "../utils"; import { combineUrl, isAdmin } from "../utils";
import isEmpty from "lodash/isEmpty"; import isEmpty from "lodash/isEmpty";
import { AppServerConfig } from "../constants"; import { AppServerConfig, LANGUAGE } from "../constants";
const { proxyURL } = AppServerConfig; const { proxyURL } = AppServerConfig;
class AuthStore { class AuthStore {
@ -43,7 +43,14 @@ class AuthStore {
return Promise.all(requests); return Promise.all(requests);
}; };
setLanguage() {
if (this.userStore.user.cultureName) {
localStorage.getItem(LANGUAGE) !== this.userStore.user.cultureName &&
localStorage.setItem(LANGUAGE, this.userStore.user.cultureName);
} else {
localStorage.setItem(LANGUAGE, this.settingsStore.culture || "en-US");
}
}
get isLoaded() { get isLoaded() {
let success = false; let success = false;
if (this.isAuthenticated) { if (this.isAuthenticated) {
@ -51,6 +58,8 @@ class AuthStore {
this.userStore.isLoaded && this.userStore.isLoaded &&
this.moduleStore.isLoaded && this.moduleStore.isLoaded &&
this.settingsStore.isLoaded; this.settingsStore.isLoaded;
success && this.setLanguage();
} else { } else {
success = this.settingsStore.isLoaded; success = this.settingsStore.isLoaded;
} }

View File

@ -13,7 +13,8 @@ class SettingsStore {
culture = "en-US"; culture = "en-US";
cultures = []; cultures = [];
trustedDomains = []; trustedDomains = [];
trustedDomainsType = 1; trustedDomainsType = 0;
trustedDomains = [];
timezone = "UTC"; timezone = "UTC";
timezones = []; timezones = [];
utcOffset = "00:00:00"; utcOffset = "00:00:00";

View File

@ -1,6 +1,5 @@
import { action, makeObservable, observable } from "mobx"; import { action, makeObservable, observable } from "mobx";
import api from "../api"; import api from "../api";
import { LANGUAGE } from "../constants";
class UserStore { class UserStore {
user = null; user = null;
@ -21,9 +20,7 @@ class UserStore {
getCurrentUser = async () => { getCurrentUser = async () => {
const user = await api.people.getUser(); const user = await api.people.getUser();
user.cultureName &&
localStorage.getItem(LANGUAGE) !== user.cultureName &&
localStorage.setItem(LANGUAGE, user.cultureName);
this.setUser(user); this.setUser(user);
}; };

View File

@ -133,7 +133,7 @@ export function isAdmin(currentUser, currentProductId) {
productName = "people"; productName = "people";
break; break;
case "e67be73d-f9ae-4ce1-8fec-1880cb518cb4": case "e67be73d-f9ae-4ce1-8fec-1880cb518cb4":
productName = "documents"; productName = "files";
break; break;
default: default:
break; break;
@ -147,21 +147,6 @@ export function isAdmin(currentUser, currentProductId) {
return currentUser.isAdmin || currentUser.isOwner || isProductAdmin; return currentUser.isAdmin || currentUser.isOwner || isProductAdmin;
} }
// export function combineUrl(host = "", ...params) {
// let url = host.replace(/\/+$/, "");
// params.forEach((part) => {
// const newPart = part.trim().replace(/^\/+/, "");
// url += newPart
// ? url.length > 0 && url[url.length - 1] === "/"
// ? newPart
// : `/${newPart}`
// : "";
// });
// return url;
// }
import combineUrlFunc from "./combineUrl"; import combineUrlFunc from "./combineUrl";
export const combineUrl = combineUrlFunc; export const combineUrl = combineUrlFunc;
@ -213,3 +198,29 @@ export function clickBackdrop() {
elms[0].click(); elms[0].click();
} }
} }
export function objectToGetParams(object) {
const params = Object.entries(object)
.filter(([, value]) => value !== undefined && value !== null)
.map(
([key, value]) =>
`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
);
return params.length > 0 ? `?${params.join("&")}` : "";
}
export function toCommunityHostname(hostname) {
let communityHostname;
try {
communityHostname =
hostname.indexOf("m.") > -1
? hostname.substring(2, hostname.length)
: hostname;
} catch (e) {
console.error(e);
communityHostname = hostname;
}
return communityHostname;
}

View File

@ -15,6 +15,7 @@ const StyledLabel = styled.label`
.checkbox { .checkbox {
margin-right: 12px; margin-right: 12px;
overflow: visible;
} }
/* ${(props) => /* ${(props) =>

View File

@ -14,6 +14,8 @@ import {
Dialog, Dialog,
BodyBox, BodyBox,
} from "./styled-modal-dialog"; } from "./styled-modal-dialog";
import Portal from "../portal";
function Header() { function Header() {
return null; return null;
} }
@ -127,62 +129,72 @@ class ModalDialog extends React.Component {
} }
}); });
return this.state.displayType === "modal" ? ( const renderModal = () => {
<Backdrop return this.state.displayType === "modal" ? (
visible={visible}
zIndex={zIndex}
withBackground={true}
isModalDialog
>
<Dialog className={`${className} not-selectable`} id={id} style={style}>
<Content contentHeight={contentHeight} contentWidth={contentWidth}>
<StyledHeader>
<Heading className="heading" size="medium" truncate={true}>
{header ? header.props.children : null}
</Heading>
<CloseButton onClick={onClose}></CloseButton>
</StyledHeader>
<BodyBox paddingProp={bodyPadding}>
{body ? body.props.children : null}
</BodyBox>
<Box>{footer ? footer.props.children : null}</Box>
</Content>
</Dialog>
</Backdrop>
) : (
<Box className={className} id={id} style={style}>
<Backdrop <Backdrop
visible={visible} visible={visible}
onClick={onClose}
zIndex={zIndex} zIndex={zIndex}
isAside={true} withBackground={true}
/> isModalDialog
<Aside
visible={visible}
scale={scale}
zIndex={zIndex}
className="modal-dialog-aside not-selectable"
> >
<Content contentHeight={contentHeight} contentWidth={contentWidth}> <Dialog
<StyledHeader className="modal-dialog-aside-header"> className={`${className} not-selectable`}
<Heading className="heading" size="medium" truncate={true}> id={id}
{header ? header.props.children : null} style={style}
</Heading> >
{scale ? <CloseButton onClick={onClose}></CloseButton> : ""} <Content contentHeight={contentHeight} contentWidth={contentWidth}>
</StyledHeader> <StyledHeader>
<BodyBox <Heading className="heading" size="medium" truncate={true}>
className="modal-dialog-aside-body" {header ? header.props.children : null}
paddingProp={bodyPadding} </Heading>
> <CloseButton onClick={onClose}></CloseButton>
{body ? body.props.children : null} </StyledHeader>
</BodyBox> <BodyBox paddingProp={bodyPadding}>
<Box className="modal-dialog-aside-footer"> {body ? body.props.children : null}
{footer ? footer.props.children : null} </BodyBox>
</Box> <Box>{footer ? footer.props.children : null}</Box>
</Content> </Content>
</Aside> </Dialog>
</Box> </Backdrop>
); ) : (
<Box className={className} id={id} style={style}>
<Backdrop
visible={visible}
onClick={onClose}
zIndex={zIndex}
isAside={true}
/>
<Aside
visible={visible}
scale={scale}
zIndex={zIndex}
className="modal-dialog-aside not-selectable"
>
<Content contentHeight={contentHeight} contentWidth={contentWidth}>
<StyledHeader className="modal-dialog-aside-header">
<Heading className="heading" size="medium" truncate={true}>
{header ? header.props.children : null}
</Heading>
{scale ? <CloseButton onClick={onClose}></CloseButton> : ""}
</StyledHeader>
<BodyBox
className="modal-dialog-aside-body"
paddingProp={bodyPadding}
>
{body ? body.props.children : null}
</BodyBox>
<Box className="modal-dialog-aside-footer">
{footer ? footer.props.children : null}
</Box>
</Content>
</Aside>
</Box>
);
};
const modalDialog = renderModal();
return <Portal element={modalDialog} />;
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@appserver/components", "name": "@appserver/components",
"version": "0.0.2", "version": "0.1.9",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "echo 'skip it'", "build": "echo 'skip it'",
@ -12,7 +12,8 @@
"storybook": "start-storybook -p 8082 -s public", "storybook": "start-storybook -p 8082 -s public",
"storybook-build": "build-storybook", "storybook-build": "build-storybook",
"storybook-serve": "serve storybook-static -p 8082", "storybook-serve": "serve storybook-static -p 8082",
"clean": "echo 'skip it'" "clean": "echo 'skip it'",
"deploy": "echo 'skip it'"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.12.10", "@babel/cli": "^7.12.10",
@ -69,8 +70,7 @@
"email-addresses": "^3.1.0", "email-addresses": "^3.1.0",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"html-to-react": "^1.4.5", "html-to-react": "^1.4.5",
"lodash": "4.17.19", "lodash": "4.17.21",
"lodash-es": "4.17.15",
"moment": "^2.29.1", "moment": "^2.29.1",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"punycode": "^2.1.1", "punycode": "^2.1.1",

View File

@ -423,6 +423,7 @@ class PasswordInput extends React.Component {
simpleView, simpleView,
hideNewPasswordButton, hideNewPasswordButton,
isDisabled, isDisabled,
showCopyLink,
} = this.props; } = this.props;
const { copyLabel, disableCopyAction } = this.state; const { copyLabel, disableCopyAction } = this.state;
@ -461,18 +462,20 @@ class PasswordInput extends React.Component {
) : null} ) : null}
</div> </div>
{this.renderTextTooltip()} {this.renderTextTooltip()}
<CopyLink> {showCopyLink && (
<Link <CopyLink>
type="action" <Link
isHovered={true} type="action"
fontSize="13px" isHovered={true}
className="password-input_link" fontSize="13px"
isSemitransparent={disableCopyAction} className="password-input_link"
onClick={this.copyToClipboard.bind(this, emailInputName)} isSemitransparent={disableCopyAction}
> onClick={this.copyToClipboard.bind(this, emailInputName)}
{copyLabel} >
</Link> {copyLabel}
</CopyLink> </Link>
</CopyLink>
)}
</> </>
)} )}
</StyledInput> </StyledInput>
@ -549,6 +552,8 @@ PasswordInput.propTypes = {
tooltipOffsetLeft: PropTypes.number, tooltipOffsetLeft: PropTypes.number,
/** Set simple view of password input (without tooltips, password progress bar and several additional buttons (copy and generate password) */ /** Set simple view of password input (without tooltips, password progress bar and several additional buttons (copy and generate password) */
simpleView: PropTypes.bool, simpleView: PropTypes.bool,
/** Sets the link to copy the password visible */
showCopyLink: PropTypes.bool,
}; };
PasswordInput.defaultProps = { PasswordInput.defaultProps = {
@ -579,6 +584,7 @@ PasswordInput.defaultProps = {
digits: false, digits: false,
specSymbols: false, specSymbols: false,
}, },
showCopyLink: true,
}; };
export default PasswordInput; export default PasswordInput;

View File

@ -1,7 +1,6 @@
{ {
"name": "@appserver/crm", "name": "@appserver/crm",
"version": "0.1.7", "version": "0.1.9",
"private": "true",
"homepage": "/products/crm", "homepage": "/products/crm",
"title": "ONLYOFFICE", "title": "ONLYOFFICE",
"id": "6743007c-6f95-4d20-8c88-a8601ce5e76d", "id": "6743007c-6f95-4d20-8c88-a8601ce5e76d",
@ -9,8 +8,9 @@
"start": "webpack-cli serve", "start": "webpack-cli serve",
"start-prod": "webpack --mode production && serve dist -p 5014", "start-prod": "webpack --mode production && serve dist -p 5014",
"build": "webpack --mode production", "build": "webpack --mode production",
"deploy": "mkdirp ../../../build/deploy/products/ASC.CRM/client && cp -r -u dist/* ../../../build/deploy/products/ASC.CRM/client",
"serve": "serve dist -p 5014", "serve": "serve dist -p 5014",
"clean": "rm -rf dist" "clean": "rimraf dist"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
@ -26,9 +26,12 @@
"css-loader": "^3.6.0", "css-loader": "^3.6.0",
"html-webpack-plugin": "4.5.0", "html-webpack-plugin": "4.5.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"mkdirp": "^1.0.4",
"rimraf": "^3.0.2",
"serve": "11.3.2", "serve": "11.3.2",
"source-map-loader": "^1.1.2", "source-map-loader": "^1.1.2",
"style-loader": "1.2.1", "style-loader": "1.2.1",
"terser-webpack-plugin": "^5.1.1",
"webpack": "5.14.0", "webpack": "5.14.0",
"webpack-cli": "4.5.0", "webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2", "webpack-dev-server": "3.11.2",
@ -38,14 +41,14 @@
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"attr-accept": "^2.2.2", "attr-accept": "^2.2.2",
"axios": "^0.21.0", "axios": "^0.21.0",
"copy-to-clipboard": "^3.2.0",
"email-addresses": "^3.1.0", "email-addresses": "^3.1.0",
"fast-deep-equal": "^3.1.3",
"i18next": "^19.8.4", "i18next": "^19.8.4",
"i18next-http-backend": "^1.1.0", "i18next-http-backend": "^1.1.0",
"mobx": "^6.1.1", "mobx": "^6.1.1",
"mobx-react": "^7.1.0", "mobx-react": "^7.1.0",
"moment": "^2.29.1", "moment": "^2.29.1",
"copy-to-clipboard": "^3.2.0",
"fast-deep-equal": "^3.1.3",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"rc-tree": "^2.1.4", "rc-tree": "^2.1.4",
"re-resizable": "^6.9.0", "re-resizable": "^6.9.0",
@ -56,8 +59,8 @@
"react-device-detect": "^1.14.0", "react-device-detect": "^1.14.0",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-dropzone": "^11.2.4", "react-dropzone": "^11.2.4",
"react-i18next": "^11.7.3",
"react-hammerjs": "^1.0.1", "react-hammerjs": "^1.0.1",
"react-i18next": "^11.7.3",
"react-onclickoutside": "^6.9.0", "react-onclickoutside": "^6.9.0",
"react-player": "^1.15.3", "react-player": "^1.15.3",
"react-resize-detector": "^5.2.0", "react-resize-detector": "^5.2.0",
@ -75,8 +78,8 @@
"resize-image": "^0.1.0", "resize-image": "^0.1.0",
"sass": "^1.29.0", "sass": "^1.29.0",
"sass-loader": "^10.1.0", "sass-loader": "^10.1.0",
"sjcl": "^1.0.8",
"screenfull": "^5.1.0", "screenfull": "^5.1.0",
"sjcl": "^1.0.8",
"styled-components": "^5.2.1", "styled-components": "^5.2.1",
"workbox-window": "^6.1.1" "workbox-window": "^6.1.1"
} }

View File

@ -19,7 +19,7 @@ import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react"; import { inject } from "mobx-react";
import i18n from "../../i18n"; import i18n from "../../i18n";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import { combineUrl, deleteCookie } from "@appserver/common/utils"; import { toCommunityHostname, deleteCookie } from "@appserver/common/utils";
const commonStyles = ` const commonStyles = `
.link-box { .link-box {
@ -121,12 +121,11 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId, t, tReady }) => {
const { error } = match.params; const { error } = match.params;
const { pathname, protocol, hostname } = window.location; const { pathname, protocol, hostname } = window.location;
const currentModule = modules.find((m) => m.link === pathname); const currentModule = modules.find((m) => m.link === pathname);
const { id, title, imageUrl, link, originUrl, helpUrl } = currentModule; const { id, title, imageUrl, /*link, originUrl,*/ helpUrl } = currentModule;
const url = originUrl ? originUrl : link; //const url = originUrl ? originUrl : link;
const webLink = combineUrl( const communityHostname = toCommunityHostname(hostname);
protocol + "//" + hostname, const webLink = `${protocol}//${communityHostname}/Products/CRM/?desktop_view=true`;
`${url}?desktop_view=true`
);
const appLink = isIOS const appLink = isIOS
? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F" ? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F"
? "message:" ? "message:"

View File

@ -4,6 +4,11 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" /> <ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.DependencyInjection; using ASC.Common.DependencyInjection;
using ASC.Common.Utils; using ASC.Common.Utils;
@ -15,18 +18,40 @@ namespace ASC.CRM
{ {
public class Program public class Program
{ {
public static void Main(string[] args) public async static Task Main(string[] args)
{ {
CreateHostBuilder(args).Build().Run(); var host = CreateHostBuilder(args).Build();
await host.RunAsync();
} }
public static IHostBuilder CreateHostBuilder(string[] args) public static IHostBuilder CreateHostBuilder(string[] args) =>
{ Host.CreateDefaultBuilder(args)
return Host.CreateDefaultBuilder(args) .UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
}) })
.ConfigureAppConfiguration((hostingContext, config) => .ConfigureAppConfiguration((hostingContext, config) =>
{ {
@ -54,25 +79,6 @@ namespace ASC.CRM
.ConfigureContainer<ContainerBuilder>((context, builder) => .ConfigureContainer<ContainerBuilder>((context, builder) =>
{ {
builder.Register(context.Configuration, true, false); 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>();//});
//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,7 +1,6 @@
{ {
"name": "@appserver/calendar", "name": "@appserver/calendar",
"version": "0.1.3", "version": "0.1.9",
"private": "true",
"homepage": "/products/calendar", "homepage": "/products/calendar",
"id": "32d24cb5-7ece-4606-9c94-19216ba42086", "id": "32d24cb5-7ece-4606-9c94-19216ba42086",
"title": "ONLYOFFICE", "title": "ONLYOFFICE",
@ -9,8 +8,9 @@
"start": "webpack-cli serve", "start": "webpack-cli serve",
"start-prod": "webpack --mode production && serve dist -p 5017", "start-prod": "webpack --mode production && serve dist -p 5017",
"build": "webpack --mode production", "build": "webpack --mode production",
"deploy": "mkdirp ../../../build/deploy/products/ASC.Calendar/client && cp -r -u dist/* ../../../build/deploy/products/ASC.Calendar/client",
"serve": "serve dist -p 5017", "serve": "serve dist -p 5017",
"clean": "rm -rf dist" "clean": "rimraf dist"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
@ -26,9 +26,12 @@
"css-loader": "^3.6.0", "css-loader": "^3.6.0",
"html-webpack-plugin": "4.5.0", "html-webpack-plugin": "4.5.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"mkdirp": "^1.0.4",
"rimraf": "^3.0.2",
"serve": "11.3.2", "serve": "11.3.2",
"source-map-loader": "^1.1.2", "source-map-loader": "^1.1.2",
"style-loader": "1.2.1", "style-loader": "1.2.1",
"terser-webpack-plugin": "^5.1.1",
"webpack": "5.14.0", "webpack": "5.14.0",
"webpack-cli": "4.5.0", "webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2", "webpack-dev-server": "3.11.2",
@ -38,14 +41,14 @@
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"attr-accept": "^2.2.2", "attr-accept": "^2.2.2",
"axios": "^0.21.0", "axios": "^0.21.0",
"copy-to-clipboard": "^3.2.0",
"email-addresses": "^3.1.0", "email-addresses": "^3.1.0",
"fast-deep-equal": "^3.1.3",
"i18next": "^19.8.4", "i18next": "^19.8.4",
"i18next-http-backend": "^1.1.0", "i18next-http-backend": "^1.1.0",
"mobx": "^6.1.1", "mobx": "^6.1.1",
"mobx-react": "^7.1.0", "mobx-react": "^7.1.0",
"moment": "^2.29.1", "moment": "^2.29.1",
"copy-to-clipboard": "^3.2.0",
"fast-deep-equal": "^3.1.3",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"rc-tree": "^2.1.4", "rc-tree": "^2.1.4",
"re-resizable": "^6.9.0", "re-resizable": "^6.9.0",
@ -56,8 +59,8 @@
"react-device-detect": "^1.14.0", "react-device-detect": "^1.14.0",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-dropzone": "^11.2.4", "react-dropzone": "^11.2.4",
"react-i18next": "^11.7.3",
"react-hammerjs": "^1.0.1", "react-hammerjs": "^1.0.1",
"react-i18next": "^11.7.3",
"react-onclickoutside": "^6.9.0", "react-onclickoutside": "^6.9.0",
"react-player": "^1.15.3", "react-player": "^1.15.3",
"react-resize-detector": "^5.2.0", "react-resize-detector": "^5.2.0",
@ -75,8 +78,8 @@
"resize-image": "^0.1.0", "resize-image": "^0.1.0",
"sass": "^1.29.0", "sass": "^1.29.0",
"sass-loader": "^10.1.0", "sass-loader": "^10.1.0",
"sjcl": "^1.0.8",
"screenfull": "^5.1.0", "screenfull": "^5.1.0",
"sjcl": "^1.0.8",
"styled-components": "^5.2.1", "styled-components": "^5.2.1",
"workbox-window": "^6.1.1" "workbox-window": "^6.1.1"
} }

View File

@ -19,7 +19,7 @@ import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react"; import { inject } from "mobx-react";
import i18n from "../../i18n"; import i18n from "../../i18n";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import { combineUrl, deleteCookie } from "@appserver/common/utils"; import { toCommunityHostname, deleteCookie } from "@appserver/common/utils";
const commonStyles = ` const commonStyles = `
.link-box { .link-box {
@ -121,12 +121,10 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId, t, tReady }) => {
const { error } = match.params; const { error } = match.params;
const { pathname, protocol, hostname } = window.location; const { pathname, protocol, hostname } = window.location;
const currentModule = modules.find((m) => m.link === pathname); const currentModule = modules.find((m) => m.link === pathname);
const { id, title, imageUrl, link, originUrl, helpUrl } = currentModule; const { id, title, imageUrl, /*link, originUrl,*/ helpUrl } = currentModule;
const url = originUrl ? originUrl : link; //const url = originUrl ? originUrl : link;
const webLink = combineUrl( const communityHostname = toCommunityHostname(hostname);
protocol + "//" + hostname, const webLink = `${protocol}//${communityHostname}/addons/calendar/?desktop_view=true`;
`${url}?desktop_view=true`
);
const appLink = isIOS const appLink = isIOS
? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F" ? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F"
? "message:" ? "message:"

View File

@ -5,6 +5,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
</ItemGroup> </ItemGroup>

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks;
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
@ -12,19 +13,23 @@ namespace ASC.Calendar
{ {
public class Program public class Program
{ {
public static void Main(string[] args) public async static Task Main(string[] args)
{ {
CreateHostBuilder(args).Build().Run(); var host = CreateHostBuilder(args).Build();
await host.RunAsync();
} }
public static IHostBuilder CreateHostBuilder(string[] args) => public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args) Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); webBuilder.UseStartup<Startup>();
}) })
.ConfigureAppConfiguration((hostingContext, config) => .ConfigureAppConfiguration((hostingContext, config) =>
{ {
var buided = config.Build(); var buided = config.Build();
var path = buided["pathToConf"]; var path = buided["pathToConf"];

View File

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

View File

@ -1,7 +1,6 @@
{ {
"name": "@appserver/files", "name": "@appserver/files",
"version": "0.1.7", "version": "0.1.9",
"private": "true",
"homepage": "/products/files", "homepage": "/products/files",
"id": "e67be73d-f9ae-4ce1-8fec-1880cb518cb4", "id": "e67be73d-f9ae-4ce1-8fec-1880cb518cb4",
"title": "ONLYOFFICE", "title": "ONLYOFFICE",
@ -9,8 +8,9 @@
"start": "webpack-cli serve", "start": "webpack-cli serve",
"start-prod": "webpack --mode production && serve dist -p 5008", "start-prod": "webpack --mode production && serve dist -p 5008",
"build": "webpack --mode production", "build": "webpack --mode production",
"deploy": "mkdirp ../../../build/deploy/products/ASC.Files/client && cp -r -u dist/* ../../../build/deploy/products/ASC.Files/client",
"serve": "serve dist -p 5008", "serve": "serve dist -p 5008",
"clean": "rm -rf dist" "clean": "rimraf dist"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
@ -28,11 +28,14 @@
"interpolate-html-plugin": "^4.0.0", "interpolate-html-plugin": "^4.0.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"mini-css-extract-plugin": "^1.3.9", "mini-css-extract-plugin": "^1.3.9",
"mkdirp": "^1.0.4",
"rimraf": "^3.0.2",
"sass": "^1.29.0", "sass": "^1.29.0",
"sass-loader": "^10.1.0", "sass-loader": "^10.1.0",
"serve": "11.3.2", "serve": "11.3.2",
"source-map-loader": "^1.1.2", "source-map-loader": "^1.1.2",
"style-loader": "1.2.1", "style-loader": "1.2.1",
"terser-webpack-plugin": "^5.1.1",
"webpack": "5.14.0", "webpack": "5.14.0",
"webpack-cli": "4.5.0", "webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2", "webpack-dev-server": "3.11.2",

View File

@ -83,7 +83,7 @@ export default function withContextOptions(WrappedComponent) {
onClickLinkForPortal = () => { onClickLinkForPortal = () => {
const { item, homepage, t } = this.props; const { item, homepage, t } = this.props;
const { fileExst, canOpenPlayer, webUrl } = item; const { fileExst, canOpenPlayer, webUrl, id } = item;
const isFile = !!fileExst; const isFile = !!fileExst;
copy( copy(
@ -151,11 +151,8 @@ export default function withContextOptions(WrappedComponent) {
item, item,
setRemoveItem, setRemoveItem,
setDeleteThirdPartyDialogVisible, setDeleteThirdPartyDialogVisible,
confirmDelete,
setDeleteDialogVisible,
t, t,
deleteFileAction, deleteItemAction,
deleteFolderAction,
isThirdPartyFolder, isThirdPartyFolder,
} = this.props; } = this.props;
const { id, title, fileExst, contentLength, folderId, parentId } = item; const { id, title, fileExst, contentLength, folderId, parentId } = item;
@ -167,21 +164,13 @@ export default function withContextOptions(WrappedComponent) {
return; return;
} }
if (confirmDelete) { const translations = {
setDeleteDialogVisible(true); deleteOperation: t("DeleteOperation"),
} else { successRemoveFile: t("FileRemoved"),
const translations = { successRemoveFolder: t("FolderRemoved"),
deleteOperation: t("DeleteOperation"), };
};
fileExst || contentLength deleteItemAction(id, folderId, translations, 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));
}
}; };
onClickShare = () => { onClickShare = () => {
@ -426,7 +415,6 @@ export default function withContextOptions(WrappedComponent) {
auth, auth,
versionHistoryStore, versionHistoryStore,
mediaViewerDataStore, mediaViewerDataStore,
settingsStore,
selectedFolderStore, selectedFolderStore,
dialogsStore, dialogsStore,
treeFoldersStore, treeFoldersStore,
@ -442,9 +430,8 @@ export default function withContextOptions(WrappedComponent) {
downloadAction, downloadAction,
duplicateAction, duplicateAction,
setThirdpartyInfo, setThirdpartyInfo,
deleteFileAction,
deleteFolderAction,
onSelectItem, onSelectItem,
deleteItemAction,
} = filesActionsStore; } = filesActionsStore;
const { const {
setChangeOwnerPanelVisible, setChangeOwnerPanelVisible,
@ -453,7 +440,6 @@ export default function withContextOptions(WrappedComponent) {
setDownloadDialogVisible, setDownloadDialogVisible,
setRemoveItem, setRemoveItem,
setDeleteThirdPartyDialogVisible, setDeleteThirdPartyDialogVisible,
setDeleteDialogVisible,
setSharingPanelVisible, setSharingPanelVisible,
} = dialogsStore; } = dialogsStore;
const { isTabletView } = auth.settingsStore; const { isTabletView } = auth.settingsStore;
@ -486,10 +472,7 @@ export default function withContextOptions(WrappedComponent) {
setMediaViewerData, setMediaViewerData,
setRemoveItem, setRemoveItem,
setDeleteThirdPartyDialogVisible, setDeleteThirdPartyDialogVisible,
confirmDelete: settingsStore.confirmDelete, deleteItemAction,
setDeleteDialogVisible,
deleteFileAction,
deleteFolderAction,
isThirdPartyFolder, isThirdPartyFolder,
onSelectItem, onSelectItem,
setSharingPanelVisible, setSharingPanelVisible,

View File

@ -80,6 +80,7 @@ const ServiceItem = (props) => {
const dataProps = { const dataProps = {
"data-link": capabilityLink, "data-link": capabilityLink,
"data-title": capabilityName, "data-title": capabilityName,
"data-key": capabilityName,
}; };
return ( return (

View File

@ -81,6 +81,7 @@ const PureTreeSettings = ({
history, history,
setIsLoading, setIsLoading,
t, t,
isVisitor,
}) => { }) => {
const { setting } = match.params; const { setting } = match.params;
@ -168,7 +169,7 @@ const PureTreeSettings = ({
title={t("TreeSettingsAdminSettings")} title={t("TreeSettingsAdminSettings")}
/> />
) : null} ) : null}
{enableThirdParty ? ( {enableThirdParty && !isVisitor ? (
<TreeNode <TreeNode
selectable={true} selectable={true}
className="settings-node" className="settings-node"
@ -226,6 +227,7 @@ export default inject(
return { return {
isAdmin: auth.isAdmin, isAdmin: auth.isAdmin,
isVisitor: auth.userStore.user.isVisitor,
isLoading, isLoading,
selectedTreeNode, selectedTreeNode,
enableThirdParty, enableThirdParty,

View File

@ -85,6 +85,7 @@ class ArticleBodyContent extends React.Component {
onTreeDrop, onTreeDrop,
selectedTreeNode, selectedTreeNode,
enableThirdParty, enableThirdParty,
isVisitor,
} = this.props; } = this.props;
return isEmpty(treeFolders) ? ( return isEmpty(treeFolders) ? (
@ -99,7 +100,7 @@ class ArticleBodyContent extends React.Component {
onTreeDrop={onTreeDrop} onTreeDrop={onTreeDrop}
/> />
<TreeSettings /> <TreeSettings />
{enableThirdParty && <ThirdPartyList />} {enableThirdParty && !isVisitor && <ThirdPartyList />}
</> </>
); );
} }
@ -107,6 +108,7 @@ class ArticleBodyContent extends React.Component {
export default inject( export default inject(
({ ({
auth,
filesStore, filesStore,
treeFoldersStore, treeFoldersStore,
selectedFolderStore, selectedFolderStore,
@ -115,10 +117,14 @@ export default inject(
}) => { }) => {
const { fetchFiles, filter, setIsLoading } = filesStore; const { fetchFiles, filter, setIsLoading } = filesStore;
const { treeFolders, setSelectedNode, setTreeFolders } = treeFoldersStore; const { treeFolders, setSelectedNode, setTreeFolders } = treeFoldersStore;
const selectedNode = treeFoldersStore.selectedTreeNode;
const selectedTreeNode = const selectedTreeNode =
treeFoldersStore.selectedTreeNode.length > 0 && selectedNode.length > 0 &&
treeFoldersStore.selectedTreeNode[0] !== "@my" selectedNode[0] !== "@my" &&
? treeFoldersStore.selectedTreeNode selectedNode[0] !== "@common"
? selectedNode
: [selectedFolderStore.id + ""]; : [selectedFolderStore.id + ""];
const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore; const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore;
@ -129,6 +135,7 @@ export default inject(
selectedTreeNode, selectedTreeNode,
filter, filter,
enableThirdParty: settingsStore.enableThirdParty, enableThirdParty: settingsStore.enableThirdParty,
isVisitor: auth.userStore.user.isVisitor,
setIsLoading, setIsLoading,
fetchFiles, fetchFiles,

View File

@ -24,6 +24,10 @@ const Badges = ({
}) => { }) => {
const { id, locked, fileStatus, versionGroup, title, fileExst } = item; const { id, locked, fileStatus, versionGroup, title, fileExst } = item;
const isFavorite = fileStatus === 32;
const isEditing = fileStatus === 1;
const isNewWithFav = fileStatus === 34;
return fileExst ? ( return fileExst ? (
<div className="badges additional-badges"> <div className="badges additional-badges">
{/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && ( {/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && (
@ -48,7 +52,7 @@ const Badges = ({
hoverColor="#3B72A7" hoverColor="#3B72A7"
/> />
)} )}
{locked && ( {locked && accessToEdit && (
<StyledFileActionsLockedIcon <StyledFileActionsLockedIcon
className="badge lock-file icons-group" className="badge lock-file icons-group"
size="small" size="small"
@ -57,7 +61,7 @@ const Badges = ({
onClick={onClickLock} onClick={onClickLock}
/> />
)} )}
{fileStatus === 32 && !isTrashFolder && ( {(isFavorite || isNewWithFav) && !isTrashFolder && (
<StyledFavoriteIcon <StyledFavoriteIcon
className="favorite icons-group" className="favorite icons-group"
size="small" size="small"
@ -67,7 +71,7 @@ const Badges = ({
onClick={onClickFavorite} onClick={onClickFavorite}
/> />
)} )}
{fileStatus === 1 && ( {isEditing && (
<StyledFileActionsConvertEditDocIcon className="badge" size="small" /> <StyledFileActionsConvertEditDocIcon className="badge" size="small" />
)} )}
{versionGroup > 1 && ( {versionGroup > 1 && (
@ -85,7 +89,7 @@ const Badges = ({
data-id={id} data-id={id}
/> />
)} )}
{showNew && ( {(showNew || isNewWithFav) && (
<Badge <Badge
className="badge-version icons-group" className="badge-version icons-group"
backgroundColor="#ED7309" backgroundColor="#ED7309"

View File

@ -110,52 +110,50 @@ const ConflictResolveDialog = (props) => {
const file = items[0].title; const file = items[0].title;
return ( return (
<ModalDialogContainer> <ModalDialogContainer visible={visible} onClose={onClose}>
<ModalDialog visible={visible} onClose={onClose}> <ModalDialog.Header>{t("ConflictResolveTitle")}</ModalDialog.Header>
<ModalDialog.Header>{t("ConflictResolveTitle")}</ModalDialog.Header> <ModalDialog.Body>
<ModalDialog.Body> <Text className="conflict-resolve-dialog-text">
<Text className="conflict-resolve-dialog-text"> {singleFile
{singleFile ? t("ConflictResolveDescription", { file, folder: folderTitle })
? t("ConflictResolveDescription", { file, folder: folderTitle }) : t("ConflictResolveDescriptionFiles", {
: t("ConflictResolveDescriptionFiles", { filesCount,
filesCount, folder: folderTitle,
folder: folderTitle, })}
})} </Text>
</Text> <Text className="conflict-resolve-dialog-text">
<Text className="conflict-resolve-dialog-text"> {t("ConflictResolveSelectAction")}
{t("ConflictResolveSelectAction")} </Text>
</Text> <RadioButtonGroup
<RadioButtonGroup className="conflict-resolve-radio-button"
className="conflict-resolve-radio-button" orientation="vertical"
orientation="vertical" fontSize="13px"
fontSize="13px" fontWeight="400"
fontWeight="400" name="group"
name="group" onClick={onSelectResolveType}
onClick={onSelectResolveType} options={radioOptions}
options={radioOptions} selected="overwrite"
selected="overwrite" />
/> </ModalDialog.Body>
</ModalDialog.Body> <ModalDialog.Footer>
<ModalDialog.Footer> <Button
<Button className="button-dialog-accept"
className="button-dialog-accept" key="OkButton"
key="OkButton" label={t("OKButton")}
label={t("OKButton")} size="medium"
size="medium" primary
primary onClick={onAcceptType}
onClick={onAcceptType} //isLoading={isLoading}
//isLoading={isLoading} />
/> <Button
<Button className="button-dialog"
className="button-dialog" key="CancelButton"
key="CancelButton" label={t("CancelButton")}
label={t("CancelButton")} size="medium"
size="medium" onClick={onClose}
onClick={onClose} //isLoading={isLoading}
//isLoading={isLoading} />
/> </ModalDialog.Footer>
</ModalDialog.Footer>
</ModalDialog>
</ModalDialogContainer> </ModalDialogContainer>
); );
}; };

View File

@ -31,7 +31,15 @@ const PureConnectDialogContainer = (props) => {
openConnectWindow, openConnectWindow,
setConnectDialogVisible, setConnectDialogVisible,
} = props; } = props;
const { corporate, title, link, token, provider_id, provider_key } = item; const {
corporate,
title,
link,
token,
provider_id,
provider_key,
key,
} = item;
const provider = providers.find( const provider = providers.find(
(el) => el.provider_key === item.provider_key (el) => el.provider_key === item.provider_key
@ -105,13 +113,13 @@ const PureConnectDialogContainer = (props) => {
setIsLoading(true); setIsLoading(true);
saveThirdParty( saveThirdParty(
null, urlValue,
null, loginValue,
null, passwordValue,
oAuthToken, oAuthToken,
isCorporate, isCorporate,
customerTitle, customerTitle,
provider_key, provider_key || key,
provider_id provider_id
) )
.then((folderData) => { .then((folderData) => {
@ -155,7 +163,6 @@ const PureConnectDialogContainer = (props) => {
}) })
.catch((err) => { .catch((err) => {
toastr.error(err); toastr.error(err);
onClose();
setIsLoading(false); setIsLoading(false);
}); });
}, [ }, [
@ -234,6 +241,7 @@ const PureConnectDialogContainer = (props) => {
errorMessage={t("RequiredFieldMessage")} errorMessage={t("RequiredFieldMessage")}
> >
<TextInput <TextInput
isAutoFocussed={true}
hasError={!isUrlValid} hasError={!isUrlValid}
isDisabled={isLoading} isDisabled={isLoading}
tabIndex={1} tabIndex={1}

View File

@ -31,53 +31,51 @@ class ConvertDialogComponent extends React.Component {
const { saveOriginalFormat, hideMessage } = this.state; const { saveOriginalFormat, hideMessage } = this.state;
return ( return (
<ModalDialogContainer> <ModalDialogContainer visible={visible} onClose={this.onClose}>
<ModalDialog visible={visible} onClose={this.onClose}> <ModalDialog.Header>{t("ConversionTitle")}</ModalDialog.Header>
<ModalDialog.Header>{t("ConversionTitle")}</ModalDialog.Header> <ModalDialog.Body>
<ModalDialog.Body> <div className="convert_dialog_content">
<div className="convert_dialog_content"> <img
<img className="convert_dialog_image"
className="convert_dialog_image" src="images/convert_alert.png"
src="images/convert_alert.png" alt="convert alert"
alt="convert alert" />
<div className="convert_dialog-content">
<Text>{t("ConversionMessage")}</Text>
<Checkbox
className="convert_dialog_checkbox"
label={t("SaveOriginalFormatMessage")}
isChecked={saveOriginalFormat}
onChange={this.onChangeFormat}
/> />
<div className="convert_dialog-content"> <Checkbox
<Text>{t("ConversionMessage")}</Text> className="convert_dialog_checkbox"
<Checkbox label={t("HideMessage")}
className="convert_dialog_checkbox" isChecked={hideMessage}
label={t("SaveOriginalFormatMessage")} onChange={this.onChangeMessageVisible}
isChecked={saveOriginalFormat}
onChange={this.onChangeFormat}
/>
<Checkbox
className="convert_dialog_checkbox"
label={t("HideMessage")}
isChecked={hideMessage}
onChange={this.onChangeMessageVisible}
/>
</div>
</div>
</ModalDialog.Body>
<ModalDialog.Footer>
<div className="convert_dialog_footer">
<Button
className="convert_dialog_button-accept"
key="ContinueButton"
label={t("ContinueButton")}
size="medium"
primary
onClick={this.onConvert}
/>
<Button
className="convert_dialog_button"
key="CloseButton"
label={t("CloseButton")}
size="medium"
onClick={this.onClose}
/> />
</div> </div>
</ModalDialog.Footer> </div>
</ModalDialog> </ModalDialog.Body>
<ModalDialog.Footer>
<div className="convert_dialog_footer">
<Button
className="convert_dialog_button-accept"
key="ContinueButton"
label={t("ContinueButton")}
size="medium"
primary
onClick={this.onConvert}
/>
<Button
className="convert_dialog_button"
key="CloseButton"
label={t("CloseButton")}
size="medium"
onClick={this.onClose}
/>
</div>
</ModalDialog.Footer>
</ModalDialogContainer> </ModalDialogContainer>
); );
} }

View File

@ -77,7 +77,10 @@ class DeleteDialogComponent extends React.Component {
} }
}; };
onClose = () => this.props.setDeleteDialogVisible(false); onClose = () => {
this.props.setRemoveMediaItem(null);
this.props.setDeleteDialogVisible(false);
};
render() { render() {
const { visible, t, isLoading } = this.props; const { visible, t, isLoading } = this.props;
@ -112,69 +115,67 @@ class DeleteDialogComponent extends React.Component {
const height = filesHeight + foldersHeight; const height = filesHeight + foldersHeight;
return ( return (
<ModalDialogContainer> <ModalDialogContainer visible={visible} onClose={this.onClose}>
<ModalDialog visible={visible} onClose={this.onClose}> <ModalDialog.Header>{title}</ModalDialog.Header>
<ModalDialog.Header>{title}</ModalDialog.Header> <ModalDialog.Body>
<ModalDialog.Body> <div className="modal-dialog-content">
<div className="modal-dialog-content"> <Text className="delete_dialog-header-text">{noteText}</Text>
<Text className="delete_dialog-header-text">{noteText}</Text> <Scrollbar style={{ height, maxHeight: 330 }} stype="mediumBlack">
<Scrollbar style={{ height, maxHeight: 330 }} stype="mediumBlack"> {foldersList.length > 0 && (
{foldersList.length > 0 && ( <Text isBold className="delete_dialog-text">
<Text isBold className="delete_dialog-text"> {t("FoldersModule")}:
{t("FoldersModule")}: </Text>
</Text> )}
)} {foldersList.map((item, index) => (
{foldersList.map((item, index) => ( <Checkbox
<Checkbox truncate
truncate className="modal-dialog-checkbox"
className="modal-dialog-checkbox" value={`${item.fileExst}/${item.id}`}
value={`${item.fileExst}/${item.id}`} onChange={this.onChange}
onChange={this.onChange} key={`checkbox_${index}`}
key={`checkbox_${index}`} isChecked={item.checked}
isChecked={item.checked} label={item.title}
label={item.title} />
/> ))}
))}
{filesList.length > 0 && ( {filesList.length > 0 && (
<Text isBold className="delete_dialog-text"> <Text isBold className="delete_dialog-text">
{t("FilesModule")}: {t("FilesModule")}:
</Text> </Text>
)} )}
{filesList.map((item, index) => ( {filesList.map((item, index) => (
<Checkbox <Checkbox
truncate truncate
className="modal-dialog-checkbox" className="modal-dialog-checkbox"
value={`${item.fileExst}/${item.id}`} value={`${item.fileExst}/${item.id}`}
onChange={this.onChange} onChange={this.onChange}
key={`checkbox_${index}`} key={`checkbox_${index}`}
isChecked={item.checked} isChecked={item.checked}
label={item.title} label={item.title}
/> />
))} ))}
</Scrollbar> </Scrollbar>
</div> </div>
</ModalDialog.Body> </ModalDialog.Body>
<ModalDialog.Footer> <ModalDialog.Footer>
<Button <Button
className="button-dialog-accept" className="button-dialog-accept"
key="OkButton" key="OkButton"
label={t("MoveToTrashButton")} label={t("MoveToTrashButton")}
size="medium" size="medium"
primary primary
onClick={this.onDelete} onClick={this.onDelete}
isLoading={isLoading} isLoading={isLoading}
/> />
<Button <Button
className="button-dialog" className="button-dialog"
key="CancelButton" key="CancelButton"
label={t("CancelButton")} label={t("CancelButton")}
size="medium" size="medium"
onClick={this.onClose} onClick={this.onClose}
isLoading={isLoading} isLoading={isLoading}
/> />
</ModalDialog.Footer> </ModalDialog.Footer>
</ModalDialog>
</ModalDialogContainer> </ModalDialogContainer>
); );
} }
@ -210,11 +211,13 @@ export default inject(
const { const {
deleteDialogVisible: visible, deleteDialogVisible: visible,
setDeleteDialogVisible, setDeleteDialogVisible,
removeMediaItem,
setRemoveMediaItem,
} = dialogsStore; } = dialogsStore;
return { return {
currentFolderId: selectedFolderStore.id, currentFolderId: selectedFolderStore.id,
selection, selection: removeMediaItem ? [removeMediaItem] : selection,
isLoading, isLoading,
treeFolders, treeFolders,
isRecycleBinFolder, isRecycleBinFolder,
@ -229,6 +232,8 @@ export default inject(
clearSecondaryProgressData, clearSecondaryProgressData,
setDeleteDialogVisible, setDeleteDialogVisible,
deleteAction, deleteAction,
setRemoveMediaItem,
}; };
} }
)(withRouter(observer(DeleteDialog))); )(withRouter(observer(DeleteDialog)));

View File

@ -5,6 +5,7 @@ import RowContainer from "@appserver/components/row-container";
import Text from "@appserver/components/text"; import Text from "@appserver/components/text";
import LinkWithDropdown from "@appserver/components/link-with-dropdown"; import LinkWithDropdown from "@appserver/components/link-with-dropdown";
import styled from "styled-components"; import styled from "styled-components";
import { FilesFormats } from "@appserver/common/constants";
const StyledDownloadContent = styled.div` const StyledDownloadContent = styled.div`
.row_content, .row_content,
@ -19,7 +20,6 @@ const DownloadContent = (props) => {
checkedTitle, checkedTitle,
indeterminateTitle, indeterminateTitle,
items, items,
formatKeys,
onSelectFormat, onSelectFormat,
onRowSelect, onRowSelect,
getItemIcon, getItemIcon,
@ -35,7 +35,7 @@ const DownloadContent = (props) => {
label: t("OriginalFormat"), label: t("OriginalFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OriginalFormat, FilesFormats.OriginalFormat,
item, item,
"document" "document"
), ),
@ -45,7 +45,7 @@ const DownloadContent = (props) => {
label: ".txt", label: ".txt",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.TxtFormat, FilesFormats.TxtFormat,
item, item,
"document" "document"
), ),
@ -55,7 +55,7 @@ const DownloadContent = (props) => {
label: ".docx", label: ".docx",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.DocxFormat, FilesFormats.DocxFormat,
item, item,
"document" "document"
), ),
@ -65,7 +65,7 @@ const DownloadContent = (props) => {
label: ".odt", label: ".odt",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OdtFormat, FilesFormats.OdtFormat,
item, item,
"document" "document"
), ),
@ -75,7 +75,7 @@ const DownloadContent = (props) => {
label: ".pdf", label: ".pdf",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.PdfFormat, FilesFormats.PdfFormat,
item, item,
"document" "document"
), ),
@ -85,7 +85,7 @@ const DownloadContent = (props) => {
label: ".rtf", label: ".rtf",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.RtfFormat, FilesFormats.RtfFormat,
item, item,
"document" "document"
), ),
@ -95,7 +95,7 @@ const DownloadContent = (props) => {
label: t("CustomFormat"), label: t("CustomFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.CustomFormat, FilesFormats.CustomFormat,
item, item,
"document" "document"
), ),
@ -108,7 +108,7 @@ const DownloadContent = (props) => {
label: t("OriginalFormat"), label: t("OriginalFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OriginalFormat, FilesFormats.OriginalFormat,
item, item,
"presentation" "presentation"
), ),
@ -118,7 +118,7 @@ const DownloadContent = (props) => {
label: ".odp", label: ".odp",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OdpFormat, FilesFormats.OdpFormat,
item, item,
"presentation" "presentation"
), ),
@ -128,7 +128,7 @@ const DownloadContent = (props) => {
label: ".pdf", label: ".pdf",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.PdfFormat, FilesFormats.PdfFormat,
item, item,
"presentation" "presentation"
), ),
@ -138,7 +138,7 @@ const DownloadContent = (props) => {
label: ".pptx", label: ".pptx",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.PptxFormat, FilesFormats.PptxFormat,
item, item,
"presentation" "presentation"
), ),
@ -148,7 +148,7 @@ const DownloadContent = (props) => {
label: t("CustomFormat"), label: t("CustomFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.CustomFormat, FilesFormats.CustomFormat,
item, item,
"presentation" "presentation"
), ),
@ -161,7 +161,7 @@ const DownloadContent = (props) => {
label: t("OriginalFormat"), label: t("OriginalFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OriginalFormat, FilesFormats.OriginalFormat,
item, item,
"spreadsheet" "spreadsheet"
), ),
@ -171,7 +171,7 @@ const DownloadContent = (props) => {
label: ".odp", label: ".odp",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.OdsFormat, FilesFormats.OdsFormat,
item, item,
"spreadsheet" "spreadsheet"
), ),
@ -181,7 +181,7 @@ const DownloadContent = (props) => {
label: ".pdf", label: ".pdf",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.PdfFormat, FilesFormats.PdfFormat,
item, item,
"spreadsheet" "spreadsheet"
), ),
@ -191,7 +191,7 @@ const DownloadContent = (props) => {
label: ".xlsx", label: ".xlsx",
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.XlsxFormat, FilesFormats.XlsxFormat,
item, item,
"spreadsheet" "spreadsheet"
), ),
@ -201,7 +201,7 @@ const DownloadContent = (props) => {
label: t("CustomFormat"), label: t("CustomFormat"),
onClick: onSelectFormat.bind( onClick: onSelectFormat.bind(
this, this,
formatKeys.CustomFormat, FilesFormats.CustomFormat,
item, item,
"spreadsheet" "spreadsheet"
), ),
@ -256,18 +256,22 @@ const DownloadContent = (props) => {
</Text> </Text>
<></> <></>
<Text fontSize="12px" containerWidth="auto"> <Text fontSize="12px" containerWidth="auto">
{t("ConvertInto")} {(checkedTitle || indeterminateTitle) && t("ConvertInto")}
</Text> </Text>
<LinkWithDropdown {checkedTitle || indeterminateTitle ? (
containerWidth="auto" <LinkWithDropdown
data={formats} containerWidth="auto"
directionX="left" data={formats}
directionY="bottom" directionX="left"
dropdownType="appearDashedAfterHover" directionY="bottom"
fontSize="12px" dropdownType="appearDashedAfterHover"
> fontSize="12px"
{documentsTitle} >
</LinkWithDropdown> {documentsTitle}
</LinkWithDropdown>
) : (
<></>
)}
</RowContent> </RowContent>
</Row> </Row>
)} )}
@ -297,19 +301,26 @@ const DownloadContent = (props) => {
{file.title} {file.title}
</Text> </Text>
<></> <></>
<Text fontSize="12px" containerWidth="auto"> {file.checked && (
{file.checked && t("ConvertInto")} <Text fontSize="12px" containerWidth="auto">
</Text> {t("ConvertInto")}
<LinkWithDropdown </Text>
dropdownType="appearDashedAfterHover" )}
containerWidth="auto"
data={dropdownItems} {file.checked ? (
directionX="left" <LinkWithDropdown
directionY="bottom" dropdownType="appearDashedAfterHover"
fontSize="12px" containerWidth="auto"
> data={dropdownItems}
{format} directionX="left"
</LinkWithDropdown> directionY="bottom"
fontSize="12px"
>
{format}
</LinkWithDropdown>
) : (
<></>
)}
</RowContent> </RowContent>
</Row> </Row>
); );

View File

@ -13,20 +13,7 @@ import { downloadFormatFiles } from "@appserver/common/api/files";
import { TIMEOUT } from "../../../helpers/constants"; import { TIMEOUT } from "../../../helpers/constants";
import DownloadContent from "./DownloadContent"; import DownloadContent from "./DownloadContent";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import { FilesFormats } from "@appserver/common/constants";
const formatKeys = Object.freeze({
OriginalFormat: 0,
TxtFormat: 1,
DocxFormat: 2,
OdtFormat: 3,
OdsFormat: 4,
OdpFormat: 5,
PdfFormat: 6,
RtfFormat: 7,
XlsxFormat: 8,
PptxFormat: 9,
CustomFormat: 10,
});
class DownloadDialogComponent extends React.Component { class DownloadDialogComponent extends React.Component {
constructor(props) { constructor(props) {
@ -39,9 +26,9 @@ class DownloadDialogComponent extends React.Component {
presentations: sortedFiles.presentations, presentations: sortedFiles.presentations,
other: sortedFiles.other, other: sortedFiles.other,
documentsTitleFormat: formatKeys.OriginalFormat, documentsTitleFormat: FilesFormats.OriginalFormat,
spreadsheetsTitleFormat: formatKeys.OriginalFormat, spreadsheetsTitleFormat: FilesFormats.OriginalFormat,
presentationsTitleFormat: formatKeys.OriginalFormat, presentationsTitleFormat: FilesFormats.OriginalFormat,
checkedDocTitle: true, checkedDocTitle: true,
checkedSpreadsheetTitle: true, checkedSpreadsheetTitle: true,
@ -192,8 +179,8 @@ class DownloadDialogComponent extends React.Component {
if (!file) { if (!file) {
for (let file of newDocuments) { for (let file of newDocuments) {
file.format = file.format =
format === formatKeys.CustomFormat || file.fileExst === format format === FilesFormats.CustomFormat || file.fileExst === format
? formatKeys.OriginalFormat ? FilesFormats.OriginalFormat
: format; : format;
} }
this.setState({ this.setState({
@ -207,7 +194,7 @@ class DownloadDialogComponent extends React.Component {
newDoc.format = format; newDoc.format = format;
this.setState({ this.setState({
documents: newDocuments, documents: newDocuments,
documentsTitleFormat: formatKeys.CustomFormat, documentsTitleFormat: FilesFormats.CustomFormat,
}); });
} }
} }
@ -216,8 +203,8 @@ class DownloadDialogComponent extends React.Component {
if (!file) { if (!file) {
for (let file of newSpreadsheets) { for (let file of newSpreadsheets) {
file.format = file.format =
format === formatKeys.CustomFormat || file.fileExst === format format === FilesFormats.CustomFormat || file.fileExst === format
? formatKeys.OriginalFormat ? FilesFormats.OriginalFormat
: format; : format;
} }
this.setState({ this.setState({
@ -231,7 +218,7 @@ class DownloadDialogComponent extends React.Component {
newSpreadsheet.format = format; newSpreadsheet.format = format;
this.setState({ this.setState({
spreadsheets: newSpreadsheets, spreadsheets: newSpreadsheets,
spreadsheetsTitleFormat: formatKeys.CustomFormat, spreadsheetsTitleFormat: FilesFormats.CustomFormat,
}); });
} }
} }
@ -240,8 +227,8 @@ class DownloadDialogComponent extends React.Component {
if (!file) { if (!file) {
for (let file of newPresentations) { for (let file of newPresentations) {
file.format = file.format =
format === formatKeys.CustomFormat || file.fileExst === format format === FilesFormats.CustomFormat || file.fileExst === format
? formatKeys.OriginalFormat ? FilesFormats.OriginalFormat
: format; : format;
} }
this.setState({ this.setState({
@ -255,7 +242,7 @@ class DownloadDialogComponent extends React.Component {
newPresentation.format = format; newPresentation.format = format;
this.setState({ this.setState({
presentations: newPresentations, presentations: newPresentations,
presentationsTitleFormat: formatKeys.CustomFormat, presentationsTitleFormat: FilesFormats.CustomFormat,
}); });
} }
} }
@ -427,6 +414,9 @@ class DownloadDialogComponent extends React.Component {
indeterminateOtherTitle, indeterminateOtherTitle,
} = this.state; } = this.state;
console.log("this.props", this.props);
console.log("this.state", this.state);
const otherLength = other.length; const otherLength = other.length;
const showOther = otherLength > 1; const showOther = otherLength > 1;
@ -440,140 +430,130 @@ class DownloadDialogComponent extends React.Component {
1; 1;
return ( return (
<ModalDialogContainer> <ModalDialogContainer visible={visible} onClose={this.onClose}>
<ModalDialog visible={visible} onClose={this.onClose}> <ModalDialog.Header>{t("DownloadAs")}</ModalDialog.Header>
<ModalDialog.Header>{t("DownloadAs")}</ModalDialog.Header> <ModalDialog.Body>
<ModalDialog.Body> <Text>{t("ChooseFormatText")}</Text>
<Text>{t("ChooseFormatText")}</Text> {documents.length > 0 && (
{documents.length > 0 && ( <DownloadContent
<DownloadContent t={t}
t={t} checkedTitle={checkedDocTitle}
checkedTitle={checkedDocTitle} indeterminateTitle={indeterminateDocTitle}
indeterminateTitle={indeterminateDocTitle} items={documents}
items={documents} onSelectFormat={this.onSelectFormat}
formatKeys={formatKeys} onRowSelect={this.onRowSelect}
onSelectFormat={this.onSelectFormat} getItemIcon={this.getItemIcon}
onRowSelect={this.onRowSelect} getTitleLabel={this.getTitleLabel}
getItemIcon={this.getItemIcon} titleFormat={documentsTitleFormat}
getTitleLabel={this.getTitleLabel} type="document"
titleFormat={documentsTitleFormat} />
type="document" )}
/>
)}
{spreadsheets.length > 0 && ( {spreadsheets.length > 0 && (
<DownloadContent <DownloadContent
t={t} t={t}
checkedTitle={checkedSpreadsheetTitle} checkedTitle={checkedSpreadsheetTitle}
indeterminateTitle={indeterminateSpreadsheetTitle} indeterminateTitle={indeterminateSpreadsheetTitle}
items={spreadsheets} items={spreadsheets}
formatKeys={formatKeys} onSelectFormat={this.onSelectFormat}
onSelectFormat={this.onSelectFormat} onRowSelect={this.onRowSelect}
onRowSelect={this.onRowSelect} getItemIcon={this.getItemIcon}
getItemIcon={this.getItemIcon} getTitleLabel={this.getTitleLabel}
getTitleLabel={this.getTitleLabel} titleFormat={spreadsheetsTitleFormat}
titleFormat={spreadsheetsTitleFormat} type="spreadsheet"
type="spreadsheet" />
/> )}
)}
{presentations.length > 0 && ( {presentations.length > 0 && (
<DownloadContent <DownloadContent
t={t} t={t}
checkedTitle={checkedPresentationTitle} checkedTitle={checkedPresentationTitle}
indeterminateTitle={indeterminatePresentationTitle} indeterminateTitle={indeterminatePresentationTitle}
items={presentations} items={presentations}
formatKeys={formatKeys} onSelectFormat={this.onSelectFormat}
onSelectFormat={this.onSelectFormat} onRowSelect={this.onRowSelect}
onRowSelect={this.onRowSelect} getItemIcon={this.getItemIcon}
getItemIcon={this.getItemIcon} getTitleLabel={this.getTitleLabel}
getTitleLabel={this.getTitleLabel} titleFormat={presentationsTitleFormat}
titleFormat={presentationsTitleFormat} type="presentation"
type="presentation" />
/> )}
)}
{otherLength > 0 && ( {otherLength > 0 && (
<> <>
{showOther && ( {showOther && (
<Row <Row
key="title2" key="title2"
onSelect={this.onRowSelect.bind(this, "All", "other")} onSelect={this.onRowSelect.bind(this, "All", "other")}
checked={checkedOtherTitle} checked={checkedOtherTitle}
indeterminate={indeterminateOtherTitle} indeterminate={indeterminateOtherTitle}
>
<RowContent>
<Text
truncate
type="page"
title={"Other"}
fontSize="14px"
>
{t("Other")}
</Text>
<></>
</RowContent>
</Row>
)}
<RowContainer
useReactWindow
style={{ minHeight: minHeight, padding: "8px 0" }}
itemHeight={50}
> >
{other.map((folder) => { <RowContent>
const element = this.getItemIcon(folder); <Text truncate type="page" title={"Other"} fontSize="14px">
return ( {t("Other")}
<Row </Text>
key={folder.id} <></>
onSelect={this.onRowSelect.bind(this, folder, "other")} </RowContent>
checked={folder.checked} </Row>
element={element} )}
>
<RowContent>
<Text
truncate
type="page"
title={folder.title}
fontSize="14px"
>
{folder.title}
</Text>
<></>
<Text fontSize="12px" containerWidth="auto">
{folder.fileExst && t("OriginalFormat")}
</Text>
</RowContent>
</Row>
);
})}
</RowContainer>
</>
)}
{!isSingleFile && <Text>{t("ConvertToZip")}</Text>} <RowContainer
<Text>{t("ConvertMessage")}</Text> useReactWindow
</ModalDialog.Body> style={{ minHeight: minHeight, padding: "8px 0" }}
<ModalDialog.Footer> itemHeight={50}
<Button >
className="button-dialog-accept" {other.map((folder) => {
key="DownloadButton" const element = this.getItemIcon(folder);
label={t("DownloadButton")} return (
size="medium" <Row
primary key={folder.id}
onClick={this.onDownload} onSelect={this.onRowSelect.bind(this, folder, "other")}
//isLoading={isLoading} checked={folder.checked}
/> element={element}
<Button >
className="button-dialog" <RowContent>
key="CancelButton" <Text
label={t("CancelButton")} truncate
size="medium" type="page"
onClick={this.onClose} title={folder.title}
//isLoading={isLoading} fontSize="14px"
/> >
</ModalDialog.Footer> {folder.title}
</ModalDialog> </Text>
<></>
<Text fontSize="12px" containerWidth="auto">
{folder.fileExst && t("OriginalFormat")}
</Text>
</RowContent>
</Row>
);
})}
</RowContainer>
</>
)}
{!isSingleFile && <Text>{t("ConvertToZip")}</Text>}
<Text>{t("ConvertMessage")}</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
className="button-dialog-accept"
key="DownloadButton"
label={t("DownloadButton")}
size="medium"
primary
onClick={this.onDownload}
//isLoading={isLoading}
/>
<Button
className="button-dialog"
key="CancelButton"
label={t("CancelButton")}
size="medium"
onClick={this.onClose}
//isLoading={isLoading}
/>
</ModalDialog.Footer>
</ModalDialogContainer> </ModalDialogContainer>
); );
} }

View File

@ -115,31 +115,29 @@ const EmptyTrashDialogComponent = (props) => {
]); ]);
return ( return (
<ModalDialogContainer> <ModalDialogContainer visible={visible} onClose={onClose}>
<ModalDialog visible={visible} onClose={onClose}> <ModalDialog.Header>{t("DeleteForeverTitle")}</ModalDialog.Header>
<ModalDialog.Header>{t("DeleteForeverTitle")}</ModalDialog.Header> <ModalDialog.Body>
<ModalDialog.Body> <Text>{t("DeleteForeverNote")}</Text>
<Text>{t("DeleteForeverNote")}</Text> </ModalDialog.Body>
</ModalDialog.Body> <ModalDialog.Footer>
<ModalDialog.Footer> <Button
<Button key="OkButton"
key="OkButton" label={t("DeleteForeverButton")}
label={t("DeleteForeverButton")} size="medium"
size="medium" primary
primary onClick={onEmptyTrash}
onClick={onEmptyTrash} isLoading={isLoading}
isLoading={isLoading} />
/> <Button
<Button className="button-dialog"
className="button-dialog" key="CancelButton"
key="CancelButton" label={t("CancelButton")}
label={t("CancelButton")} size="medium"
size="medium" onClick={onClose}
onClick={onClose} isLoading={isLoading}
isLoading={isLoading} />
/> </ModalDialog.Footer>
</ModalDialog.Footer>
</ModalDialog>
</ModalDialogContainer> </ModalDialogContainer>
); );
}; };

View File

@ -1,7 +1,8 @@
import styled from "styled-components"; import styled from "styled-components";
import { tablet } from "@appserver/components/utils/device"; import { tablet } from "@appserver/components/utils/device";
import ModalDialog from "@appserver/components/modal-dialog";
const ModalDialogContainer = styled.div` const ModalDialogContainer = styled(ModalDialog)`
.flex { .flex {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@ -52,6 +52,7 @@ const ServiceItem = (props) => {
const dataProps = { const dataProps = {
"data-link": capabilityLink, "data-link": capabilityLink,
"data-title": capabilityName, "data-title": capabilityName,
"data-key": capabilityName,
}; };
return <img {...dataProps} {...rest} alt="" />; return <img {...dataProps} {...rest} alt="" />;
@ -222,6 +223,7 @@ const ThirdPartyDialog = (props) => {
onClick={onShowService} onClick={onShowService}
className="service-item service-text" className="service-item service-text"
data-title={webDavConnectItem[0]} data-title={webDavConnectItem[0]}
data-key={webDavConnectItem[0]}
> >
{t("ConnextOtherAccount")} {t("ConnextOtherAccount")}
</Text> </Text>

View File

@ -10,6 +10,7 @@ import AccessComboBox from "./AccessComboBox";
//import equal from "fast-deep-equal/react"; //import equal from "fast-deep-equal/react";
import { getAccessIcon } from "../../../helpers/files-helpers"; import { getAccessIcon } from "../../../helpers/files-helpers";
import { ReactSVG } from "react-svg"; import { ReactSVG } from "react-svg";
import { objectToGetParams } from "@appserver/common/utils";
class SharingRow extends React.Component { class SharingRow extends React.Component {
constructor(props) { constructor(props) {
@ -49,19 +50,42 @@ class SharingRow extends React.Component {
const subject = t("ShareEmailSubject", { itemName }); const subject = t("ShareEmailSubject", { itemName });
const body = t("ShareEmailBody", { itemName, shareLink }); const body = t("ShareEmailBody", { itemName, shareLink });
window.open(`mailto:?subject=${subject}&body=${body}`); const mailtoLink =
"mailto:" +
objectToGetParams({
subject,
body,
});
window.open(mailtoLink);
}; };
onShareTwitter = () => { onShareTwitter = () => {
const encodedLink = encodeURIComponent(this.props.item.sharedTo.shareLink); const { item } = this.props;
window.open(`https://twitter.com/intent/tweet?text=${encodedLink}`); const { shareLink } = item.sharedTo;
const twitterLink =
"https://twitter.com/intent/tweet" +
objectToGetParams({
text: shareLink,
});
window.open(twitterLink);
}; };
onShareFacebook = () => { // onShareFacebook = () => {
window.open( // const { item, selection } = this.props;
`https://www.facebook.com/sharer/sharer.php?u=${this.props.item.sharedTo.shareLink}` // const { shareLink } = item.sharedTo;
);
}; // const facebookLink =
// "https://www.facebook.com/sharer/sharer.php" +
// objectToGetParams({
// u: shareLink,
// t: selection.title ? selection.title : selection[0].title,
// });
// window.open(facebookLink);
// };
render() { render() {
//console.log("SharingRow render"); //console.log("SharingRow render");
@ -120,11 +144,11 @@ class SharingRow extends React.Component {
label: `${t("ShareVia")} e-mail`, label: `${t("ShareVia")} e-mail`,
onClick: this.onShareEmail, onClick: this.onShareEmail,
}, },
{ // {
key: "linkItem_3", // key: "linkItem_3",
label: `${t("ShareVia")} Facebook`, // label: `${t("ShareVia")} Facebook`,
onClick: this.onShareFacebook, // onClick: this.onShareFacebook,
}, // },
{ {
key: "linkItem_4", key: "linkItem_4",
label: `${t("ShareVia")} Twitter`, label: `${t("ShareVia")} Twitter`,

View File

@ -77,14 +77,10 @@ class SharingPanelComponent extends React.Component {
}; };
updateRowData = (newRowData) => { updateRowData = (newRowData) => {
const { setFile, setFolder } = this.props; const { getFileInfo, getFolderInfo } = this.props;
for (let item of newRowData) { for (let item of newRowData) {
if (!item.fileExst) { !item.fileExst ? getFolderInfo(item.id) : getFileInfo(item.id);
setFolder(item);
} else {
setFile(item);
}
} }
}; };
@ -172,8 +168,8 @@ class SharingPanelComponent extends React.Component {
ownerId ownerId
) )
.then((res) => { .then((res) => {
if (ownerId) { if (!ownerId) {
this.updateRowData(res[0]); this.updateRowData(selection);
} }
if (isPrivacy && isDesktop) { if (isPrivacy && isDesktop) {
if (share.length === 0) return Promise.resolve(); if (share.length === 0) return Promise.resolve();
@ -610,6 +606,8 @@ const SharingPanel = inject(
getShareUsers, getShareUsers,
setShareFiles, setShareFiles,
setIsLoading, setIsLoading,
getFileInfo,
getFolderInfo,
isLoading, isLoading,
} = filesStore; } = filesStore;
const { isPrivacyFolder } = treeFoldersStore; const { isPrivacyFolder } = treeFoldersStore;
@ -644,6 +642,8 @@ const SharingPanel = inject(
setFolder, setFolder,
getShareUsers, getShareUsers,
setShareFiles, setShareFiles,
getFileInfo,
getFolderInfo,
}; };
} }
)(observer(withTranslation("SharingPanel")(SharingPanelComponent))); )(observer(withTranslation("SharingPanel")(SharingPanelComponent)));

View File

@ -13,11 +13,12 @@ const FilesMediaViewer = (props) => {
playlist, playlist,
visible, visible,
currentMediaFileId, currentMediaFileId,
deleteFileAction, deleteItemAction,
setMediaViewerData, setMediaViewerData,
mediaViewerMediaFormats, mediaViewerMediaFormats,
mediaViewerImageFormats, mediaViewerImageFormats,
location, location,
setRemoveMediaItem,
} = props; } = props;
useEffect(() => { useEffect(() => {
@ -60,7 +61,10 @@ const FilesMediaViewer = (props) => {
if (files.length > 0) { if (files.length > 0) {
let file = files.find((file) => file.id === id); let file = files.find((file) => file.id === id);
if (file) deleteFileAction(file.id, file.folderId, translations); if (file) {
setRemoveMediaItem(file);
deleteItemAction(file.id, file.folderId, translations, true);
}
} }
}; };
@ -95,7 +99,13 @@ const FilesMediaViewer = (props) => {
}; };
export default inject( export default inject(
({ filesStore, mediaViewerDataStore, filesActionsStore, formatsStore }) => { ({
filesStore,
mediaViewerDataStore,
filesActionsStore,
formatsStore,
dialogsStore,
}) => {
const { files } = filesStore; const { files } = filesStore;
const { const {
visible, visible,
@ -103,7 +113,7 @@ export default inject(
setMediaViewerData, setMediaViewerData,
playlist, playlist,
} = mediaViewerDataStore; } = mediaViewerDataStore;
const { deleteFileAction } = filesActionsStore; const { deleteItemAction } = filesActionsStore;
const { media, images } = formatsStore.mediaViewersFormatsStore; const { media, images } = formatsStore.mediaViewersFormatsStore;
return { return {
@ -111,10 +121,11 @@ export default inject(
playlist, playlist,
visible: playlist.length > 0 && visible, visible: playlist.length > 0 && visible,
currentMediaFileId, currentMediaFileId,
deleteFileAction, deleteItemAction,
setMediaViewerData, setMediaViewerData,
mediaViewerImageFormats: images, mediaViewerImageFormats: images,
mediaViewerMediaFormats: media, mediaViewerMediaFormats: media,
setRemoveMediaItem: dialogsStore.setRemoveMediaItem,
}; };
} }
)(withRouter(withTranslation("Home")(observer(FilesMediaViewer)))); )(withRouter(withTranslation("Home")(observer(FilesMediaViewer))));

View File

@ -103,5 +103,5 @@ const SimpleFilesRow = createSelectable((props) => {
}); });
export default withTranslation("Home")( export default withTranslation("Home")(
withFileActions(withContextOptions(withRouter(SimpleFilesRow))) withFileActions(withRouter(withContextOptions(SimpleFilesRow)))
); );

View File

@ -262,19 +262,11 @@ class SectionFilterContent extends React.Component {
render() { render() {
//console.log("Filter render"); //console.log("Filter render");
const selectedFilterData = this.getSelectedFilterData(); const selectedFilterData = this.getSelectedFilterData();
const { const { t, sectionWidth, tReady, isFiltered, viewAs } = this.props;
t,
firstLoad,
sectionWidth,
tReady,
isAnyItems,
filterSearch,
viewAs,
} = this.props;
const filterColumnCount = const filterColumnCount =
window.innerWidth < 500 ? {} : { filterColumnCount: 3 }; window.innerWidth < 500 ? {} : { filterColumnCount: 3 };
return !isAnyItems && !filterSearch ? null : !tReady ? ( return !isFiltered ? null : !tReady ? (
<Loaders.Filter /> <Loaders.Filter />
) : ( ) : (
<FilterInput <FilterInput
@ -299,7 +291,6 @@ class SectionFilterContent extends React.Component {
export default inject(({ auth, filesStore, selectedFolderStore }) => { export default inject(({ auth, filesStore, selectedFolderStore }) => {
const { const {
firstLoad,
fetchFiles, fetchFiles,
filter, filter,
setIsLoading, setIsLoading,
@ -311,24 +302,22 @@ export default inject(({ auth, filesStore, selectedFolderStore }) => {
const { user } = auth.userStore; const { user } = auth.userStore;
const { customNames, culture } = auth.settingsStore; const { customNames, culture } = auth.settingsStore;
const isAnyItems = !!files.length || !!folders.length;
const filterSearch = filter.search; const { search, filterType } = filter;
const isFiltered = !!files.length || !!folders.length || search || filterType;
return { return {
customNames, customNames,
user, user,
firstLoad,
selectedFolderId: selectedFolderStore.id, selectedFolderId: selectedFolderStore.id,
selectedItem: filter.selectedItem, selectedItem: filter.selectedItem,
filter, filter,
viewAs, viewAs,
isFiltered,
setIsLoading, setIsLoading,
fetchFiles, fetchFiles,
setViewAs, setViewAs,
isAnyItems,
filterSearch,
}; };
})( })(
withRouter( withRouter(

View File

@ -323,6 +323,7 @@ class SectionHeaderContent extends React.Component {
isOnlyFoldersSelected, isOnlyFoldersSelected,
isFavoritesFolder, isFavoritesFolder,
isRecentFolder, isRecentFolder,
isShareFolder,
} = this.props; } = this.props;
let menu = [ let menu = [
@ -438,6 +439,10 @@ class SectionHeaderContent extends React.Component {
menu.splice(4, 1); menu.splice(4, 1);
} }
if (isShareFolder) {
menu.splice(4, 1);
}
return menu; return menu;
}; };
@ -591,6 +596,7 @@ export default inject(
isPrivacyFolder, isPrivacyFolder,
isFavoritesFolder, isFavoritesFolder,
isRecentFolder, isRecentFolder,
isShareFolder,
} = treeFoldersStore; } = treeFoldersStore;
const { setAction } = fileActionStore; const { setAction } = fileActionStore;
const { const {
@ -614,6 +620,7 @@ export default inject(
isPrivacy: isPrivacyFolder, isPrivacy: isPrivacyFolder,
isFavoritesFolder, isFavoritesFolder,
isRecentFolder, isRecentFolder,
isShareFolder,
filter, filter,
canCreate, canCreate,
selectionCount: selection.length, selectionCount: selection.length,

View File

@ -30,7 +30,13 @@ import config from "../../../package.json";
class PureHome extends React.Component { class PureHome extends React.Component {
componentDidMount() { componentDidMount() {
const { fetchFiles, homepage, setIsLoading, setFirstLoad } = this.props; const {
fetchFiles,
homepage,
setIsLoading,
setFirstLoad,
isVisitor,
} = this.props;
const reg = new RegExp(`${homepage}((/?)$|/filter)`, "gm"); //TODO: Always find? const reg = new RegExp(`${homepage}((/?)$|/filter)`, "gm"); //TODO: Always find?
const match = window.location.pathname.match(reg); const match = window.location.pathname.match(reg);
@ -41,6 +47,7 @@ class PureHome extends React.Component {
if (!filterObj) { if (!filterObj) {
filterObj = FilesFilter.getDefault(); filterObj = FilesFilter.getDefault();
if (isVisitor) filterObj.folder = "@common";
const folderId = filterObj.folder; const folderId = filterObj.folder;
setIsLoading(true); setIsLoading(true);
fetchFiles(folderId, filterObj).finally(() => { fetchFiles(folderId, filterObj).finally(() => {
@ -366,6 +373,7 @@ export default inject(
viewAs, viewAs,
uploaded, uploaded,
isRecycleBinFolder, isRecycleBinFolder,
isVisitor: auth.userStore.user.isVisitor,
primaryProgressDataVisible, primaryProgressDataVisible,
primaryProgressDataPercent, primaryProgressDataPercent,

View File

@ -51,6 +51,7 @@ const SectionBodyContent = ({
myFolderId, myFolderId,
commonFolderId, commonFolderId,
t, t,
isVisitor,
}) => { }) => {
const onChangeStoreForceSave = () => { const onChangeStoreForceSave = () => {
setStoreForceSave(!storeForceSave, "storeForceSave"); setStoreForceSave(!storeForceSave, "storeForceSave");
@ -134,42 +135,51 @@ const SectionBodyContent = ({
onChange={onChangeDeleteConfirm} onChange={onChangeDeleteConfirm}
isChecked={confirmDelete} isChecked={confirmDelete}
/> />
<ToggleButton {!isVisitor && (
isDisabled={true} <>
className="toggle-btn" <ToggleButton
label={t("DisplayRecent")} isDisabled={true}
onChange={(e) => console.log(e)} className="toggle-btn"
isChecked={false} label={t("DisplayRecent")}
/> onChange={(e) => console.log(e)}
<ToggleButton isChecked={false}
isDisabled={true} />
className="toggle-btn"
label={t("DisplayFavorites")} <ToggleButton
onChange={(e) => console.log(e)} isDisabled={true}
isChecked={false} className="toggle-btn"
/> label={t("DisplayFavorites")}
<ToggleButton onChange={(e) => console.log(e)}
isDisabled={true} isChecked={false}
className="toggle-btn" />
label={t("DisplayTemplates")} <ToggleButton
onChange={(e) => console.log(e)} isDisabled={true}
isChecked={false} className="toggle-btn"
/> label={t("DisplayTemplates")}
<Heading className="heading" level={2} size="small"> onChange={(e) => console.log(e)}
{t("StoringFileVersion")} isChecked={false}
</Heading> />
<ToggleButton </>
className="toggle-btn" )}
label={t("UpdateOrCreate")} {!isVisitor && (
onChange={onChangeUpdateIfExist} <>
isChecked={updateIfExist} <Heading className="heading" level={2} size="small">
/> {t("StoringFileVersion")}
<ToggleButton </Heading>
className="toggle-btn" <ToggleButton
label={t("KeepIntermediateVersion")} className="toggle-btn"
onChange={onChangeForceSave} label={t("UpdateOrCreate")}
isChecked={forceSave} onChange={onChangeUpdateIfExist}
/> isChecked={updateIfExist}
/>
<ToggleButton
className="toggle-btn"
label={t("KeepIntermediateVersion")}
onChange={onChangeForceSave}
isChecked={forceSave}
/>
</>
)}
</StyledSettings> </StyledSettings>
); );
}; };
@ -240,6 +250,7 @@ export default inject(
treeFolders, treeFolders,
myFolderId, myFolderId,
commonFolderId, commonFolderId,
isVisitor: auth.userStore.user.isVisitor,
setUpdateIfExist, setUpdateIfExist,
setStoreOriginal, setStoreOriginal,

View File

@ -13,6 +13,7 @@ import StyledVersionRow from "./StyledVersionRow";
import ExternalLinkIcon from "../../../../../public/images/external.link.react.svg"; import ExternalLinkIcon from "../../../../../public/images/external.link.react.svg";
import commonIconsStyles from "@appserver/components/utils/common-icons-style"; import commonIconsStyles from "@appserver/components/utils/common-icons-style";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import toastr from "studio/toastr";
const StyledExternalLinkIcon = styled(ExternalLinkIcon)` const StyledExternalLinkIcon = styled(ExternalLinkIcon)`
${commonIconsStyles} ${commonIconsStyles}

View File

@ -21,6 +21,7 @@ class DialogsStore {
newFilesIds = null; newFilesIds = null;
conflictResolveDialogData = null; conflictResolveDialogData = null;
conflictResolveDialogItems = null; conflictResolveDialogItems = null;
removeMediaItem = null;
constructor() { constructor() {
makeAutoObservable(this); makeAutoObservable(this);
@ -104,6 +105,10 @@ class DialogsStore {
setConflictResolveDialogItems = (items) => { setConflictResolveDialogItems = (items) => {
this.conflictResolveDialogItems = items; this.conflictResolveDialogItems = items;
}; };
setRemoveMediaItem = (removeMediaItem) => {
this.removeMediaItem = removeMediaItem;
};
} }
export default new DialogsStore(); export default new DialogsStore();

View File

@ -71,17 +71,18 @@ class FilesActionStore {
} }
if (folderIds.length || fileIds.length) { if (folderIds.length || fileIds.length) {
setSecondaryProgressBarData({
icon: "trash",
visible: true,
label: translations.deleteOperation,
percent: 0,
alert: false,
});
return removeFiles(folderIds, fileIds, deleteAfter, immediately) return removeFiles(folderIds, fileIds, deleteAfter, immediately)
.then((res) => { .then((res) => {
const id = res[0] && res[0].id ? res[0].id : null; const id = res[0] && res[0].id ? res[0].id : null;
const currentProcess = res.find((x) => x.id === id);
setSecondaryProgressBarData({
icon: "trash",
visible: true,
label: translations.deleteOperation,
percent: currentProcess.progress,
alert: false,
});
this.loopDeleteOperation(id, translations); this.loopDeleteOperation(id, translations);
}) })
.catch((err) => { .catch((err) => {
@ -267,25 +268,41 @@ class FilesActionStore {
setSelection([item]); setSelection([item]);
}; };
deleteItemAction = (itemId, currentFolderId, translations, isFile) => {
const {
setSecondaryProgressBarData,
} = this.uploadDataStore.secondaryProgressDataStore;
if (this.settingsStore.confirmDelete) {
this.dialogsStore.setDeleteDialogVisible(true);
} else {
setSecondaryProgressBarData({
icon: "trash",
visible: true,
percent: 0,
label: translations.deleteOperation,
alert: false,
});
isFile
? deleteFileAction(itemId, currentFolderId, translations)
: deleteFolderAction(itemId, currentFolderId, translations);
}
};
deleteFileAction = (fileId, currentFolderId, translations) => { deleteFileAction = (fileId, currentFolderId, translations) => {
const { const {
setSecondaryProgressBarData, setSecondaryProgressBarData,
clearSecondaryProgressData, clearSecondaryProgressData,
} = this.uploadDataStore.secondaryProgressDataStore; } = this.uploadDataStore.secondaryProgressDataStore;
setSecondaryProgressBarData({
icon: "trash",
visible: true,
percent: 0,
label: translations.deleteOperation,
alert: false,
});
return deleteFile(fileId) return deleteFile(fileId)
.then((res) => { .then((res) => {
const id = res[0] && res[0].id ? res[0].id : null; const id = res[0] && res[0].id ? res[0].id : null;
this.loopDeleteProgress(id, currentFolderId, false, translations); this.loopDeleteProgress(id, currentFolderId, false, translations);
}) })
.then(() => toastr.success(translations.successRemoveFile))
.catch((err) => { .catch((err) => {
toastr.error(err);
setSecondaryProgressBarData({ setSecondaryProgressBarData({
visible: true, visible: true,
alert: true, alert: true,
@ -300,19 +317,14 @@ class FilesActionStore {
clearSecondaryProgressData, clearSecondaryProgressData,
} = this.uploadDataStore.secondaryProgressDataStore; } = this.uploadDataStore.secondaryProgressDataStore;
setSecondaryProgressBarData({
icon: "trash",
visible: true,
percent: 0,
label: translations.deleteOperation,
alert: false,
});
return deleteFolder(folderId, currentFolderId) return deleteFolder(folderId, currentFolderId)
.then((res) => { .then((res) => {
const id = res[0] && res[0].id ? res[0].id : null; const id = res[0] && res[0].id ? res[0].id : null;
this.loopDeleteProgress(id, currentFolderId, true, translations); this.loopDeleteProgress(id, currentFolderId, true, translations);
}) })
.then(() => toastr.success(translations.successRemoveFolder))
.catch((err) => { .catch((err) => {
toastr.error(err);
setSecondaryProgressBarData({ setSecondaryProgressBarData({
visible: true, visible: true,
alert: true, alert: true,

View File

@ -6,6 +6,7 @@ import {
FileType, FileType,
FileAction, FileAction,
AppServerConfig, AppServerConfig,
FilesFormats,
} from "@appserver/common/constants"; } from "@appserver/common/constants";
import history from "@appserver/common/history"; import history from "@appserver/common/history";
import { createTreeFolders } from "../helpers/files-helpers"; import { createTreeFolders } from "../helpers/files-helpers";
@ -123,6 +124,7 @@ class FilesStore {
if (this.isInit) return; if (this.isInit) return;
const { isAuthenticated } = this.authStore; const { isAuthenticated } = this.authStore;
const { const {
getPortalCultures, getPortalCultures,
isDesktopClient, isDesktopClient,
@ -370,10 +372,10 @@ class FilesStore {
const isVisitor = const isVisitor =
(this.userStore.user && this.userStore.user.isVisitor) || false; (this.userStore.user && this.userStore.user.isVisitor) || false;
const isFile = !!item.fileExst || item.contentLength; const isFile = !!item.fileExst || item.contentLength;
const isFavorite = item.fileStatus === 32; const isFavorite = item.fileStatus === 32 || item.fileStatus === 34;
const isFullAccess = item.access < 2; const isFullAccess = item.access < 2;
const withoutShare = false; //TODO: need this prop const withoutShare = false; //TODO: need this prop
const isThirdPartyItem = item.providerKey; const isThirdPartyItem = !!item.providerKey;
const hasNew = item.new > 0; const hasNew = item.new > 0;
const canConvert = false; //TODO: fix of added convert check; const canConvert = false; //TODO: fix of added convert check;
const isEncrypted = item.encrypted; const isEncrypted = item.encrypted;
@ -384,13 +386,18 @@ class FilesStore {
isRecycleBinFolder, isRecycleBinFolder,
isPrivacyFolder, isPrivacyFolder,
isRecentFolder, isRecentFolder,
isShareFolder, isCommon,
isCommonFolder, isShare,
isFavoritesFolder, isFavoritesFolder,
isThirdPartyFolder,
isMyFolder,
} = this.treeFoldersStore; } = this.treeFoldersStore;
const { isRootFolder } = this.selectedFolderStore;
const isThirdPartyFolder = item.providerKey && isRootFolder;
const isShareFolder = isShare(item.rootFolderType);
const isCommonFolder = isCommon(item.rootFolderType);
const { isDesktopClient } = this.settingsStore; const { isDesktopClient } = this.settingsStore;
if (isFile) { if (isFile) {
@ -498,12 +505,7 @@ class FilesStore {
]); ]);
} }
if ( if (isFavoritesFolder || isPrivacyFolder || isRecentFolder) {
isCommonFolder ||
isFavoritesFolder ||
isPrivacyFolder ||
isRecentFolder
) {
fileOptions = this.removeOptions(fileOptions, [ fileOptions = this.removeOptions(fileOptions, [
"copy", "copy",
"move-to", "move-to",
@ -547,6 +549,7 @@ class FilesStore {
"rename", "rename",
"block-unblock-version", "block-unblock-version",
"copy", "copy",
"sharing-settings",
]); ]);
} }
@ -575,7 +578,7 @@ class FilesStore {
]); ]);
} }
if (isCommonFolder) if (isCommonFolder) {
if (!this.userAccess) { if (!this.userAccess) {
fileOptions = this.removeOptions(fileOptions, [ fileOptions = this.removeOptions(fileOptions, [
"owner-change", "owner-change",
@ -587,6 +590,7 @@ class FilesStore {
fileOptions = this.removeOptions(fileOptions, ["separator2"]); fileOptions = this.removeOptions(fileOptions, ["separator2"]);
} }
} }
}
if (withoutShare) { if (withoutShare) {
fileOptions = this.removeOptions(fileOptions, [ fileOptions = this.removeOptions(fileOptions, [
@ -605,6 +609,10 @@ class FilesStore {
fileOptions = this.removeOptions(fileOptions, ["separator2"]); fileOptions = this.removeOptions(fileOptions, ["separator2"]);
} }
if (isShareFolder) {
fileOptions = this.removeOptions(fileOptions, ["move-to", "delete"]);
}
return fileOptions; return fileOptions;
} else { } else {
let folderOptions = [ let folderOptions = [
@ -631,6 +639,13 @@ class FilesStore {
folderOptions = this.removeOptions(folderOptions, ["copy"]); folderOptions = this.removeOptions(folderOptions, ["copy"]);
} }
if (isShareFolder) {
folderOptions = this.removeOptions(folderOptions, [
"move-to",
"delete",
]);
}
if (isRecycleBinFolder) { if (isRecycleBinFolder) {
folderOptions = this.removeOptions(folderOptions, [ folderOptions = this.removeOptions(folderOptions, [
"open", "open",
@ -686,6 +701,14 @@ class FilesStore {
folderOptions = this.removeOptions(folderOptions, ["unsubscribe"]); folderOptions = this.removeOptions(folderOptions, ["unsubscribe"]);
} }
if (isThirdPartyFolder) {
folderOptions = this.removeOptions(folderOptions, ["move-to"]);
} else {
folderOptions = this.removeOptions(folderOptions, [
"change-thirdparty-info",
]);
}
if (isThirdPartyItem) { if (isThirdPartyItem) {
folderOptions = this.removeOptions(folderOptions, ["owner-change"]); folderOptions = this.removeOptions(folderOptions, ["owner-change"]);
@ -700,10 +723,7 @@ class FilesStore {
]); ]);
} }
folderOptions = this.removeOptions(folderOptions, [ folderOptions = this.removeOptions(folderOptions, ["remove"]);
"remove",
"move-to",
]);
if (!item) { if (!item) {
//For damaged items //For damaged items
@ -1025,10 +1045,6 @@ class FilesStore {
} = this.formatsStore.iconFormatsStore; } = this.formatsStore.iconFormatsStore;
const { canWebEdit } = this.formatsStore.docserviceStore; const { canWebEdit } = this.formatsStore.docserviceStore;
const formatKeys = Object.freeze({
OriginalFormat: 0,
});
let sortedFiles = { let sortedFiles = {
documents: [], documents: [],
spreadsheets: [], spreadsheets: [],
@ -1038,7 +1054,7 @@ class FilesStore {
for (let item of this.selection) { for (let item of this.selection) {
item.checked = true; item.checked = true;
item.format = formatKeys.OriginalFormat; item.format = FilesFormats.OriginalFormat;
if (item.fileExst) { if (item.fileExst) {
if (isSpreadsheet(item.fileExst)) { if (isSpreadsheet(item.fileExst)) {
@ -1080,9 +1096,8 @@ class FilesStore {
get isAccessedSelected() { get isAccessedSelected() {
return ( return (
(this.selection.length && this.selection.length &&
this.selection.every((x) => x.access === 1 || x.access === 0)) || this.selection.every((x) => x.access === 1 || x.access === 0)
(this.authStore.isAdmin && this.selection.length)
); );
} }
@ -1231,6 +1246,11 @@ class FilesStore {
this.setFile(fileInfo); this.setFile(fileInfo);
}; };
getFolderInfo = async (id) => {
const folderInfo = await api.files.getFolderInfo(id);
this.setFolder(folderInfo);
};
openDocEditor = (id, providerKey = null, tab = null, url = null) => { openDocEditor = (id, providerKey = null, tab = null, url = null) => {
if (providerKey) { if (providerKey) {
tab tab

View File

@ -48,6 +48,9 @@ class TreeFoldersStore {
if (rootItem) rootItem.newItems -= count; if (rootItem) rootItem.newItems -= count;
}; };
isCommon = (commonType) => commonType === FolderType.COMMON;
isShare = (shareType) => shareType === FolderType.SHARE;
get myFolder() { get myFolder() {
return this.treeFolders.find((x) => x.rootFolderName === "@my"); return this.treeFolders.find((x) => x.rootFolderName === "@my");
} }

View File

@ -271,7 +271,7 @@ namespace ASC.Files.Core.Data
} }
} }
return (checkShare ? FromQueryWithShared(q) : FromQuery(q)).Select(ToFolder).ToList(); return (checkShare ? FromQueryWithShared(q) : FromQuery(q)).Select(ToFolder).Distinct().ToList();
} }
public List<Folder<int>> GetParentFolders(int folderId) public List<Folder<int>> GetParentFolders(int folderId)

View File

@ -382,7 +382,7 @@ namespace ASC.Web.Files.Services.WCFService
} }
} }
EntryManager.SetFileStatus(entries.OfType<File<TId>>().Where(r => r.ID != null).ToList()); EntryManager.SetFileStatus(entries);
return new ItemList<FileEntry>(entries); return new ItemList<FileEntry>(entries);
} }
@ -1225,7 +1225,7 @@ namespace ASC.Web.Files.Services.WCFService
} }
catch (Exception e) catch (Exception e)
{ {
throw GenerateException(e); throw GenerateException(e.InnerException ?? e);
} }
} }
else else

View File

@ -37,9 +37,8 @@ using ASC.Files.Core;
using ASC.Files.Core.EF; using ASC.Files.Core.EF;
using ASC.Web.Core.Files; using ASC.Web.Core.Files;
using ASC.Web.Files.Classes; using ASC.Web.Files.Classes;
using ASC.Web.Studio.Core; using ASC.Web.Studio.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OneDrive.Sdk; using Microsoft.OneDrive.Sdk;
@ -171,7 +170,7 @@ namespace ASC.Files.Thirdparty.OneDrive
if (onedriveFile.File == null) return null; if (onedriveFile.File == null) return null;
var file = ServiceProvider.GetService<File<string>>(); var file = GetFile();
file.ID = MakeId(onedriveFile.Id); file.ID = MakeId(onedriveFile.Id);
file.ContentLength = onedriveFile.Size.HasValue ? (long)onedriveFile.Size : 0; file.ContentLength = onedriveFile.Size.HasValue ? (long)onedriveFile.Size : 0;

View File

@ -367,7 +367,9 @@ namespace ASC.Files.Thirdparty
{ {
Id = id, Id = id,
Title = customerTitle, Title = customerTitle,
Token = EncryptPassword(authData.Token), Token = EncryptPassword(authData.Token),
Url = authData.Url,
UserName = authData.Login,
Password = EncryptPassword(authData.Password), Password = EncryptPassword(authData.Password),
UserId = owner, UserId = owner,
FolderType = type, FolderType = type,
@ -390,10 +392,11 @@ namespace ASC.Files.Thirdparty
var createOn = TenantUtil.DateTimeFromUtc(input.CreateOn); var createOn = TenantUtil.DateTimeFromUtc(input.CreateOn);
var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password), token); var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password), token);
if (string.IsNullOrEmpty(token)) throw new ArgumentException("Token can't be null");
if (key == ProviderTypes.Box) if (key == ProviderTypes.Box)
{ {
if (string.IsNullOrEmpty(token))
throw new ArgumentException("Token can't be null");
var box = ServiceProvider.GetService<BoxProviderInfo>(); var box = ServiceProvider.GetService<BoxProviderInfo>();
box.ID = id; box.ID = id;
box.CustomerTitle = providerTitle; box.CustomerTitle = providerTitle;
@ -406,7 +409,10 @@ namespace ASC.Files.Thirdparty
} }
if (key == ProviderTypes.DropboxV2) if (key == ProviderTypes.DropboxV2)
{ {
if (string.IsNullOrEmpty(token))
throw new ArgumentException("Token can't be null");
var drop = ServiceProvider.GetService<DropboxProviderInfo>(); var drop = ServiceProvider.GetService<DropboxProviderInfo>();
drop.ID = id; drop.ID = id;
drop.CustomerTitle = providerTitle; drop.CustomerTitle = providerTitle;
@ -436,7 +442,10 @@ namespace ASC.Files.Thirdparty
} }
if (key == ProviderTypes.GoogleDrive) if (key == ProviderTypes.GoogleDrive)
{ {
if (string.IsNullOrEmpty(token))
throw new ArgumentException("Token can't be null");
var gd = ServiceProvider.GetService<GoogleDriveProviderInfo>(); var gd = ServiceProvider.GetService<GoogleDriveProviderInfo>();
gd.ID = id; gd.ID = id;
gd.CustomerTitle = providerTitle; gd.CustomerTitle = providerTitle;
@ -450,7 +459,10 @@ namespace ASC.Files.Thirdparty
} }
if (key == ProviderTypes.OneDrive) if (key == ProviderTypes.OneDrive)
{ {
if (string.IsNullOrEmpty(token))
throw new ArgumentException("Token can't be null");
var od = ServiceProvider.GetService<OneDriveProviderInfo>(); var od = ServiceProvider.GetService<OneDriveProviderInfo>();
od.ID = id; od.ID = id;
od.CustomerTitle = providerTitle; od.CustomerTitle = providerTitle;

View File

@ -485,8 +485,7 @@ namespace ASC.Web.Files.Services.DocumentService
} }
var folderDao = DaoFactory.GetFolderDao<int>(); var folderDao = DaoFactory.GetFolderDao<int>();
var fileDao = DaoFactory.GetFileDao<int>(); var files = entryManager.GetRecent(filter, false, Guid.Empty, string.Empty, false).Cast<File<int>>();
var files = entryManager.GetRecent(folderDao, fileDao, filter, false, Guid.Empty, string.Empty, false);
var listRecent = from file in files var listRecent = from file in files
where !Equals(_configuration.Document.Info.File.ID, file.ID) where !Equals(_configuration.Document.Info.File.ID, file.ID)

View File

@ -358,9 +358,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
protected void ProgressStep(TId folderId = default, TId fileId = default) protected void ProgressStep(TId folderId = default, TId fileId = default)
{ {
if (folderId.Equals(default(TId)) && fileId.Equals(default(TId)) if (Equals(folderId, default(TId)) && Equals(fileId, default(TId))
|| !folderId.Equals(default(TId)) && Folders.Contains(folderId) || !Equals(folderId, default(TId)) && Folders.Contains(folderId)
|| !fileId.Equals(default(TId)) && Files.Contains(fileId)) || !Equals(fileId, default(TId)) && Files.Contains(fileId))
{ {
processed++; processed++;
PublishTaskInfo(); PublishTaskInfo();

View File

@ -384,9 +384,7 @@ namespace ASC.Web.Files.Utils
} }
else if (parent.FolderType == FolderType.Recent) else if (parent.FolderType == FolderType.Recent)
{ {
var folderDao = DaoFactory.GetFolderDao<T>(); var files = GetRecent(filter, subjectGroup, subjectId, searchText, searchInContent);
var fileDao = DaoFactory.GetFileDao<T>();
var files = GetRecent(folderDao, fileDao, filter, subjectGroup, subjectId, searchText, searchInContent);
entries = entries.Concat(files); entries = entries.Concat(files);
CalculateTotal(); CalculateTotal();
@ -396,7 +394,7 @@ namespace ASC.Web.Files.Utils
var fileDao = DaoFactory.GetFileDao<T>(); var fileDao = DaoFactory.GetFileDao<T>();
var folderDao = DaoFactory.GetFolderDao<T>(); var folderDao = DaoFactory.GetFolderDao<T>();
GetFavorites(folderDao, fileDao, filter, subjectGroup, subjectId, searchText, searchInContent, out var folders, out var files); var (files, folders) = GetFavorites(filter, subjectGroup, subjectId, searchText, searchInContent);
entries = entries.Concat(folders); entries = entries.Concat(folders);
entries = entries.Concat(files); entries = entries.Concat(files);
@ -473,7 +471,7 @@ namespace ASC.Web.Files.Utils
if (0 < count) entries = entries.Take(count); if (0 < count) entries = entries.Take(count);
} }
SetFileStatus(entries.OfType<File<T>>().Where(r => r != null && r.ID != null && r.FileEntryType == FileEntryType.File).ToList()); SetFileStatus(entries.Where(r => r != null && r.FileEntryType == FileEntryType.File).ToList());
return entries; return entries;
void CalculateTotal() void CalculateTotal()
@ -545,53 +543,101 @@ namespace ASC.Web.Files.Utils
return folderList; return folderList;
} }
public IEnumerable<File<T>> GetRecent<T>(IFolderDao<T> folderDao, IFileDao<T> fileDao, FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent) public IEnumerable<FileEntry> GetRecent(FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent)
{ {
var tagDao = DaoFactory.GetTagDao<T>(); var tagDao = DaoFactory.GetTagDao<int>();
var tags = tagDao.GetTags(AuthContext.CurrentAccount.ID, TagType.Recent).ToList(); var tags = tagDao.GetTags(AuthContext.CurrentAccount.ID, TagType.Recent).ToList();
var fileIds = tags.Where(tag => tag.EntryType == FileEntryType.File).Select(tag => (T)Convert.ChangeType(tag.EntryId, typeof(T))).ToArray(); var fileIds = tags.Where(tag => tag.EntryType == FileEntryType.File).ToList();
var files = fileDao.GetFilesFiltered(fileIds, filter, subjectGroup, subjectId, searchText, searchInContent);
files = files.Where(file => file.RootFolderType != FolderType.TRASH).ToList();
files = FileSecurity.FilterRead(files).ToList(); List<FileEntry> files = GetRecentByIds(fileIds.Where(r => r.EntryId is int).Select(r=> (int)r.EntryId), filter, subjectGroup, subjectId, searchText, searchInContent).ToList();
files.AddRange(GetRecentByIds(fileIds.Where(r => r.EntryId is string).Select(r => (string)r.EntryId), filter, subjectGroup, subjectId, searchText, searchInContent));
CheckFolderId(folderDao, files); var listFileIds = fileIds.Select(tag => tag.EntryId).ToList();
var listFileIds = fileIds.ToList(); files = files.OrderBy(file =>
files = files.OrderBy(file => listFileIds.IndexOf(file.ID)).ToList(); {
var fileId = "";
if (file is File<int> fileInt)
{
fileId = fileInt.ID.ToString();
}
else if (file is File<string> fileString)
{
fileId = fileString.ID;
}
return listFileIds.IndexOf(fileId);
}).ToList();
return files; return files;
}
public void GetFavorites<T>(IFolderDao<T> folderDao, IFileDao<T> fileDao, FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent, out IEnumerable<Folder<T>> folders, out IEnumerable<File<T>> files) IEnumerable<FileEntry> GetRecentByIds<T>(IEnumerable<T> fileIds, FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent)
{
folders = new List<Folder<T>>();
files = new List<File<T>>();
var fileSecurity = FileSecurity;
var tagDao = DaoFactory.GetTagDao<T>();
var tags = tagDao.GetTags(AuthContext.CurrentAccount.ID, TagType.Favorite);
if (filter == FilterType.None || filter == FilterType.FoldersOnly)
{ {
var folderIds = tags.Where(tag => tag.EntryType == FileEntryType.Folder).Select(tag => (T)Convert.ChangeType(tag.EntryId, typeof(T))).ToList(); var folderDao = DaoFactory.GetFolderDao<T>();
folders = folderDao.GetFolders(folderIds, filter, subjectGroup, subjectId, searchText, false, false); var fileDao = DaoFactory.GetFileDao<T>();
folders = folders.Where(folder => folder.RootFolderType != FolderType.TRASH).ToList(); var files = fileDao.GetFilesFiltered(fileIds, filter, subjectGroup, subjectId, searchText, searchInContent);
folders = fileSecurity.FilterRead(folders).ToList();
CheckFolderId(folderDao, folders);
}
if (filter != FilterType.FoldersOnly)
{
var fileIds = tags.Where(tag => tag.EntryType == FileEntryType.File).Select(tag => (T)Convert.ChangeType(tag.EntryId, typeof(T))).ToArray();
files = fileDao.GetFilesFiltered(fileIds, filter, subjectGroup, subjectId, searchText, searchInContent);
files = files.Where(file => file.RootFolderType != FolderType.TRASH).ToList(); files = files.Where(file => file.RootFolderType != FolderType.TRASH).ToList();
files = fileSecurity.FilterRead(files).ToList(); files = FileSecurity.FilterRead(files).ToList();
CheckFolderId(folderDao, folders); CheckFolderId(folderDao, files);
return files;
}
}
public (IEnumerable<FileEntry>, IEnumerable<FileEntry>) GetFavorites(FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent)
{
var fileSecurity = FileSecurity;
var tagDao = DaoFactory.GetTagDao<int>();
var tags = tagDao.GetTags(AuthContext.CurrentAccount.ID, TagType.Favorite);
var fileIds = tags.Where(tag => tag.EntryType == FileEntryType.File).ToList();
var folderIds = tags.Where(tag => tag.EntryType == FileEntryType.Folder).ToList();
var (filesInt, foldersInt) = GetFavoritesById(fileIds.Where(r => r.EntryId is int).Select(r => (int)r.EntryId), folderIds.Where(r => r.EntryId is int).Select(r => (int)r.EntryId), filter, subjectGroup, subjectId, searchText, searchInContent);
var (filesString, foldersString) = GetFavoritesById(fileIds.Where(r => r.EntryId is string).Select(r => (string)r.EntryId), folderIds.Where(r => r.EntryId is string).Select(r => (string)r.EntryId), filter, subjectGroup, subjectId, searchText, searchInContent);
var files = new List<FileEntry>();
files.AddRange(filesInt);
files.AddRange(filesString);
var folders = new List<FileEntry>();
folders.AddRange(foldersInt);
folders.AddRange(foldersString);
return (files, folders);
(IEnumerable<FileEntry>, IEnumerable<FileEntry>) GetFavoritesById<T>(IEnumerable<T> fileIds, IEnumerable<T> folderIds, FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent)
{
var folderDao = DaoFactory.GetFolderDao<T>();
var fileDao = DaoFactory.GetFileDao<T>();
var folders = new List<Folder<T>>();
var files = new List<File<T>>();
var fileSecurity = FileSecurity;
if (filter == FilterType.None || filter == FilterType.FoldersOnly)
{
folders = folderDao.GetFolders(folderIds, filter, subjectGroup, subjectId, searchText, false, false);
folders = folders.Where(folder => folder.RootFolderType != FolderType.TRASH).ToList();
folders = fileSecurity.FilterRead(folders).ToList();
CheckFolderId(folderDao, folders);
}
if (filter != FilterType.FoldersOnly)
{
files = fileDao.GetFilesFiltered(fileIds, filter, subjectGroup, subjectId, searchText, searchInContent);
files = files.Where(file => file.RootFolderType != FolderType.TRASH).ToList();
files = fileSecurity.FilterRead(files).ToList();
CheckFolderId(folderDao, folders);
}
return (files, folders);
} }
} }
@ -778,6 +824,12 @@ namespace ASC.Web.Files.Utils
SetFileStatus(new List<File<T>>(1) { file }); SetFileStatus(new List<File<T>>(1) { file });
} }
public void SetFileStatus(IEnumerable<FileEntry> files)
{
SetFileStatus(files.OfType<File<int>>().Where(r=> r.ID != 0));
SetFileStatus(files.OfType<File<string>>().Where(r=> !string.IsNullOrEmpty(r.ID)));
}
public void SetFileStatus<T>(IEnumerable<File<T>> files) public void SetFileStatus<T>(IEnumerable<File<T>> files)
{ {
var tagDao = DaoFactory.GetTagDao<T>(); var tagDao = DaoFactory.GetTagDao<T>();

View File

@ -29,6 +29,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" /> <ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />

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